aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/mpic-msgr.txt63
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/mpic.txt22
-rw-r--r--Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt6
-rw-r--r--Documentation/powerpc/firmware-assisted-dump.txt270
-rw-r--r--Documentation/powerpc/mpc52xx.txt12
-rw-r--r--Documentation/powerpc/phyp-assisted-dump.txt127
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/powerpc/Kconfig18
-rw-r--r--arch/powerpc/Kconfig.debug7
-rw-r--r--arch/powerpc/Makefile1
-rw-r--r--arch/powerpc/boot/Makefile11
-rw-r--r--arch/powerpc/boot/dts/a4m072.dts168
-rw-r--r--arch/powerpc/boot/dts/bluestone.dts127
-rw-r--r--arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi4
-rw-r--r--arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi16
-rw-r--r--arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi4
-rw-r--r--arch/powerpc/boot/dts/fsl/p1010si-post.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/p1020si-post.dtsi6
-rw-r--r--arch/powerpc/boot/dts/fsl/p1021si-post.dtsi7
-rw-r--r--arch/powerpc/boot/dts/fsl/p1022si-post.dtsi12
-rw-r--r--arch/powerpc/boot/dts/fsl/p1023si-post.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/p2020si-post.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/p2041si-post.dtsi2
-rw-r--r--arch/powerpc/boot/dts/fsl/p3041si-post.dtsi2
-rw-r--r--arch/powerpc/boot/dts/fsl/p3060si-post.dtsi6
-rw-r--r--arch/powerpc/boot/dts/fsl/p5020si-post.dtsi2
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi3
-rw-r--r--arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi10
-rw-r--r--arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi6
-rw-r--r--arch/powerpc/boot/dts/ge_imp3a.dts255
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc8536ds.dts6
-rw-r--r--arch/powerpc/boot/dts/mpc8536ds.dtsi93
-rw-r--r--arch/powerpc/boot/dts/mpc8536ds_36b.dts8
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dts306
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds.dtsi306
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds_32b.dts86
-rw-r--r--arch/powerpc/boot/dts/mpc8548cds_36b.dts86
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dtsi50
-rw-r--r--arch/powerpc/boot/dts/p1010rdb.dtsi4
-rw-r--r--arch/powerpc/boot/dts/p1020rdb-pc.dtsi247
-rw-r--r--arch/powerpc/boot/dts/p1020rdb-pc_32b.dts90
-rw-r--r--arch/powerpc/boot/dts/p1020rdb-pc_36b.dts90
-rw-r--r--arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts64
-rw-r--r--arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts142
-rw-r--r--arch/powerpc/boot/dts/p1021rdb.dts96
-rw-r--r--arch/powerpc/boot/dts/p1021rdb.dtsi236
-rw-r--r--arch/powerpc/boot/dts/p1021rdb_36b.dts96
-rw-r--r--arch/powerpc/boot/dts/p1022ds.dts274
-rw-r--r--arch/powerpc/boot/dts/p1022ds.dtsi234
-rw-r--r--arch/powerpc/boot/dts/p1022ds_32b.dts103
-rw-r--r--arch/powerpc/boot/dts/p1022ds_36b.dts103
-rw-r--r--arch/powerpc/boot/dts/p1025rdb.dtsi286
-rw-r--r--arch/powerpc/boot/dts/p1025rdb_32b.dts135
-rw-r--r--arch/powerpc/boot/dts/p1025rdb_36b.dts88
-rw-r--r--arch/powerpc/boot/dts/p2020rdb-pc.dtsi241
-rw-r--r--arch/powerpc/boot/dts/p2020rdb-pc_32b.dts96
-rw-r--r--arch/powerpc/boot/dts/p2020rdb-pc_36b.dts96
-rw-r--r--arch/powerpc/boot/dts/p2020rdb.dts4
-rwxr-xr-xarch/powerpc/boot/wrapper22
-rw-r--r--arch/powerpc/configs/85xx/ge_imp3a_defconfig257
-rw-r--r--arch/powerpc/configs/86xx/gef_ppc9a_defconfig1
-rw-r--r--arch/powerpc/configs/86xx/gef_sbc310_defconfig1
-rw-r--r--arch/powerpc/configs/86xx/gef_sbc610_defconfig2
-rw-r--r--arch/powerpc/configs/iseries_defconfig236
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig27
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig1
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig1
-rw-r--r--arch/powerpc/include/asm/abs_addr.h21
-rw-r--r--arch/powerpc/include/asm/atomic.h59
-rw-r--r--arch/powerpc/include/asm/cputable.h12
-rw-r--r--arch/powerpc/include/asm/device.h3
-rw-r--r--arch/powerpc/include/asm/dma.h4
-rw-r--r--arch/powerpc/include/asm/eeh.h134
-rw-r--r--arch/powerpc/include/asm/eeh_event.h33
-rw-r--r--arch/powerpc/include/asm/exception-64s.h113
-rw-r--r--arch/powerpc/include/asm/fadump.h218
-rw-r--r--arch/powerpc/include/asm/firmware.h9
-rw-r--r--arch/powerpc/include/asm/fsl_guts.h6
-rw-r--r--arch/powerpc/include/asm/hw_irq.h63
-rw-r--r--arch/powerpc/include/asm/irqflags.h37
-rw-r--r--arch/powerpc/include/asm/iseries/alpaca.h31
-rw-r--r--arch/powerpc/include/asm/iseries/hv_call.h111
-rw-r--r--arch/powerpc/include/asm/iseries/hv_call_event.h201
-rw-r--r--arch/powerpc/include/asm/iseries/hv_call_sc.h50
-rw-r--r--arch/powerpc/include/asm/iseries/hv_call_xm.h61
-rw-r--r--arch/powerpc/include/asm/iseries/hv_lp_config.h128
-rw-r--r--arch/powerpc/include/asm/iseries/hv_lp_event.h162
-rw-r--r--arch/powerpc/include/asm/iseries/hv_types.h112
-rw-r--r--arch/powerpc/include/asm/iseries/iommu.h37
-rw-r--r--arch/powerpc/include/asm/iseries/it_lp_queue.h78
-rw-r--r--arch/powerpc/include/asm/iseries/lpar_map.h85
-rw-r--r--arch/powerpc/include/asm/iseries/mf.h51
-rw-r--r--arch/powerpc/include/asm/iseries/vio.h265
-rw-r--r--arch/powerpc/include/asm/lppaca.h8
-rw-r--r--arch/powerpc/include/asm/mpic.h9
-rw-r--r--arch/powerpc/include/asm/mpic_msgr.h132
-rw-r--r--arch/powerpc/include/asm/paca.h2
-rw-r--r--arch/powerpc/include/asm/phyp_dump.h47
-rw-r--r--arch/powerpc/include/asm/ppc-pci.h89
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h2
-rw-r--r--arch/powerpc/include/asm/reg.h22
-rw-r--r--arch/powerpc/include/asm/reg_booke.h1
-rw-r--r--arch/powerpc/include/asm/spinlock.h5
-rw-r--r--arch/powerpc/include/asm/system.h38
-rw-r--r--arch/powerpc/include/asm/thread_info.h9
-rw-r--r--arch/powerpc/include/asm/time.h15
-rw-r--r--arch/powerpc/kernel/Makefile10
-rw-r--r--arch/powerpc/kernel/asm-offsets.c16
-rw-r--r--arch/powerpc/kernel/cputable.c20
-rw-r--r--arch/powerpc/kernel/dbell.c2
-rw-r--r--arch/powerpc/kernel/entry_64.S250
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S236
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S314
-rw-r--r--arch/powerpc/kernel/fadump.c1315
-rw-r--r--arch/powerpc/kernel/head_32.S4
-rw-r--r--arch/powerpc/kernel/head_40x.S4
-rw-r--r--arch/powerpc/kernel/head_64.S62
-rw-r--r--arch/powerpc/kernel/head_8xx.S4
-rw-r--r--arch/powerpc/kernel/head_booke.h4
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S2
-rw-r--r--arch/powerpc/kernel/idle.c6
-rw-r--r--arch/powerpc/kernel/idle_book3e.S25
-rw-r--r--arch/powerpc/kernel/idle_power4.S24
-rw-r--r--arch/powerpc/kernel/idle_power7.S23
-rw-r--r--arch/powerpc/kernel/iommu.c8
-rw-r--r--arch/powerpc/kernel/irq.c212
-rw-r--r--arch/powerpc/kernel/isa-bridge.c3
-rw-r--r--arch/powerpc/kernel/lparcfg.c108
-rw-r--r--arch/powerpc/kernel/misc.S1
-rw-r--r--arch/powerpc/kernel/of_platform.c6
-rw-r--r--arch/powerpc/kernel/paca.c12
-rw-r--r--arch/powerpc/kernel/pci-common.c15
-rw-r--r--arch/powerpc/kernel/process.c27
-rw-r--r--arch/powerpc/kernel/prom.c98
-rw-r--r--arch/powerpc/kernel/prom_init.c15
-rw-r--r--arch/powerpc/kernel/rtas_pci.c3
-rw-r--r--arch/powerpc/kernel/setup-common.c14
-rw-r--r--arch/powerpc/kernel/signal.c13
-rw-r--r--arch/powerpc/kernel/signal_32.c11
-rw-r--r--arch/powerpc/kernel/sysfs.c7
-rw-r--r--arch/powerpc/kernel/time.c116
-rw-r--r--arch/powerpc/kernel/traps.c6
-rw-r--r--arch/powerpc/kernel/vio.c18
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S5
-rw-r--r--arch/powerpc/kvm/book3s_hv.c1
-rw-r--r--arch/powerpc/lib/locks.c24
-rw-r--r--arch/powerpc/mm/fault.c181
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c19
-rw-r--r--arch/powerpc/mm/hash_utils_64.c20
-rw-r--r--arch/powerpc/mm/icswx.c23
-rw-r--r--arch/powerpc/mm/icswx.h6
-rw-r--r--arch/powerpc/mm/pgtable_32.c2
-rw-r--r--arch/powerpc/mm/slb.c6
-rw-r--r--arch/powerpc/mm/slb_low.S16
-rw-r--r--arch/powerpc/mm/stab.c9
-rw-r--r--arch/powerpc/oprofile/common.c3
-rw-r--r--arch/powerpc/perf/Makefile14
-rw-r--r--arch/powerpc/perf/callchain.c (renamed from arch/powerpc/kernel/perf_callchain.c)2
-rw-r--r--arch/powerpc/perf/core-book3s.c (renamed from arch/powerpc/kernel/perf_event.c)0
-rw-r--r--arch/powerpc/perf/core-fsl-emb.c (renamed from arch/powerpc/kernel/perf_event_fsl_emb.c)0
-rw-r--r--arch/powerpc/perf/e500-pmu.c (renamed from arch/powerpc/kernel/e500-pmu.c)0
-rw-r--r--arch/powerpc/perf/mpc7450-pmu.c (renamed from arch/powerpc/kernel/mpc7450-pmu.c)0
-rw-r--r--arch/powerpc/perf/power4-pmu.c (renamed from arch/powerpc/kernel/power4-pmu.c)0
-rw-r--r--arch/powerpc/perf/power5+-pmu.c (renamed from arch/powerpc/kernel/power5+-pmu.c)0
-rw-r--r--arch/powerpc/perf/power5-pmu.c (renamed from arch/powerpc/kernel/power5-pmu.c)0
-rw-r--r--arch/powerpc/perf/power6-pmu.c (renamed from arch/powerpc/kernel/power6-pmu.c)2
-rw-r--r--arch/powerpc/perf/power7-pmu.c (renamed from arch/powerpc/kernel/power7-pmu.c)0
-rw-r--r--arch/powerpc/perf/ppc970-pmu.c (renamed from arch/powerpc/kernel/ppc970-pmu.c)2
-rw-r--r--arch/powerpc/platforms/44x/Kconfig1
-rw-r--r--arch/powerpc/platforms/44x/currituck.c2
-rw-r--r--arch/powerpc/platforms/44x/iss4xx.c3
-rw-r--r--arch/powerpc/platforms/44x/ppc44x_simple.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc5200_simple.c1
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c10
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig27
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/corenet_ds.c4
-rw-r--r--arch/powerpc/platforms/85xx/ge_imp3a.c246
-rw-r--r--arch/powerpc/platforms/85xx/ksi8560.c3
-rw-r--r--arch/powerpc/platforms/85xx/mpc8536_ds.c4
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c3
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c84
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c6
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_mds.c40
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_rdb.c222
-rw-r--r--arch/powerpc/platforms/85xx/p1010rdb.c5
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c207
-rw-r--r--arch/powerpc/platforms/85xx/p1023_rds.c5
-rw-r--r--arch/powerpc/platforms/85xx/sbc8548.c3
-rw-r--r--arch/powerpc/platforms/85xx/sbc8560.c3
-rw-r--r--arch/powerpc/platforms/85xx/socrates.c3
-rw-r--r--arch/powerpc/platforms/85xx/stx_gp3.c3
-rw-r--r--arch/powerpc/platforms/85xx/tqm85xx.c2
-rw-r--r--arch/powerpc/platforms/85xx/xes_mpc85xx.c4
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig3
-rw-r--r--arch/powerpc/platforms/86xx/Makefile7
-rw-r--r--arch/powerpc/platforms/86xx/gef_ppc9a.c2
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc310.c2
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc610.c2
-rw-r--r--arch/powerpc/platforms/86xx/pic.c5
-rw-r--r--arch/powerpc/platforms/Kconfig11
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/setup.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c2
-rw-r--r--arch/powerpc/platforms/chrp/setup.c3
-rw-r--r--arch/powerpc/platforms/embedded6xx/holly.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/linkstation.c3
-rw-r--r--arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c6
-rw-r--r--arch/powerpc/platforms/embedded6xx/storcenter.c3
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig39
-rw-r--r--arch/powerpc/platforms/iseries/Makefile9
-rw-r--r--arch/powerpc/platforms/iseries/call_hpt.h102
-rw-r--r--arch/powerpc/platforms/iseries/call_pci.h309
-rw-r--r--arch/powerpc/platforms/iseries/call_sm.h37
-rw-r--r--arch/powerpc/platforms/iseries/dt.c643
-rw-r--r--arch/powerpc/platforms/iseries/exception.S311
-rw-r--r--arch/powerpc/platforms/iseries/exception.h58
-rw-r--r--arch/powerpc/platforms/iseries/htab.c257
-rw-r--r--arch/powerpc/platforms/iseries/hvcall.S94
-rw-r--r--arch/powerpc/platforms/iseries/hvlog.c35
-rw-r--r--arch/powerpc/platforms/iseries/hvlpconfig.c39
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c260
-rw-r--r--arch/powerpc/platforms/iseries/ipl_parms.h68
-rw-r--r--arch/powerpc/platforms/iseries/irq.c399
-rw-r--r--arch/powerpc/platforms/iseries/irq.h13
-rw-r--r--arch/powerpc/platforms/iseries/it_exp_vpd_panel.h51
-rw-r--r--arch/powerpc/platforms/iseries/it_lp_naca.h80
-rw-r--r--arch/powerpc/platforms/iseries/ksyms.c21
-rw-r--r--arch/powerpc/platforms/iseries/lpardata.c318
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c341
-rw-r--r--arch/powerpc/platforms/iseries/main_store.h165
-rw-r--r--arch/powerpc/platforms/iseries/mf.c1275
-rw-r--r--arch/powerpc/platforms/iseries/misc.S26
-rw-r--r--arch/powerpc/platforms/iseries/naca.h24
-rw-r--r--arch/powerpc/platforms/iseries/pci.c919
-rw-r--r--arch/powerpc/platforms/iseries/pci.h58
-rw-r--r--arch/powerpc/platforms/iseries/proc.c120
-rw-r--r--arch/powerpc/platforms/iseries/processor_vpd.h85
-rw-r--r--arch/powerpc/platforms/iseries/release_data.h63
-rw-r--r--arch/powerpc/platforms/iseries/setup.c718
-rw-r--r--arch/powerpc/platforms/iseries/setup.h27
-rw-r--r--arch/powerpc/platforms/iseries/smp.c88
-rw-r--r--arch/powerpc/platforms/iseries/spcomm_area.h34
-rw-r--r--arch/powerpc/platforms/iseries/vio.c556
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c677
-rw-r--r--arch/powerpc/platforms/iseries/vpd_areas.h88
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c42
-rw-r--r--arch/powerpc/platforms/powermac/pic.c1
-rw-r--r--arch/powerpc/platforms/powernv/pci.c1
-rw-r--r--arch/powerpc/platforms/powernv/setup.c1
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig2
-rw-r--r--arch/powerpc/platforms/pseries/Makefile4
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c1044
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c44
-rw-r--r--arch/powerpc/platforms/pseries/eeh_dev.c102
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c213
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c55
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c565
-rw-r--r--arch/powerpc/platforms/pseries/eeh_sysfs.c25
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c1
-rw-r--r--arch/powerpc/platforms/pseries/msi.c2
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c3
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c513
-rw-r--r--arch/powerpc/platforms/pseries/processor_idle.c18
-rw-r--r--arch/powerpc/platforms/pseries/setup.c12
-rw-r--r--arch/powerpc/sysdev/Kconfig4
-rw-r--r--arch/powerpc/sysdev/Makefile4
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_cache_sram.c1
-rw-r--r--arch/powerpc/sysdev/fsl_85xx_l2ctlr.c4
-rw-r--r--arch/powerpc/sysdev/fsl_msi.c1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c4
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c42
-rw-r--r--arch/powerpc/sysdev/ge/Makefile1
-rw-r--r--arch/powerpc/sysdev/ge/ge_pic.c (renamed from arch/powerpc/platforms/86xx/gef_pic.c)2
-rw-r--r--arch/powerpc/sysdev/ge/ge_pic.h (renamed from arch/powerpc/platforms/86xx/gef_pic.h)0
-rw-r--r--arch/powerpc/sysdev/mpic.c104
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c282
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c4
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c70
-rw-r--r--arch/powerpc/xmon/xmon.c33
-rw-r--r--drivers/base/driver.c30
-rw-r--r--drivers/block/viodasd.c809
-rw-r--r--drivers/cdrom/viocd.c739
-rw-r--r--drivers/char/viotape.c1041
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-ge.c (renamed from arch/powerpc/platforms/86xx/gef_gpio.c)30
-rw-r--r--drivers/misc/carma/carma-fpga.c114
-rw-r--r--drivers/mtd/nand/Kconfig10
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c1072
-rw-r--r--drivers/scsi/Kconfig3
-rw-r--r--drivers/scsi/ibmvscsi/Makefile1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c12
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h1
-rw-r--r--drivers/scsi/ibmvscsi/iseries_vscsi.c173
-rw-r--r--drivers/tty/hvc/Kconfig14
-rw-r--r--drivers/tty/hvc/Makefile1
-rw-r--r--drivers/tty/hvc/hvc_iseries.c599
-rw-r--r--drivers/tty/hvc/hvc_udbg.c8
-rw-r--r--drivers/tty/hvc/hvc_vio.c4
-rw-r--r--drivers/tty/serial/Kconfig2
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--fs/proc/vmcore.c23
-rw-r--r--include/linux/atomic.h2
-rw-r--r--include/linux/device.h4
-rw-r--r--include/linux/of.h10
-rw-r--r--include/linux/pci.h7
-rw-r--r--init/do_mounts_rd.c4
317 files changed, 11233 insertions, 17284 deletions
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mpic-msgr.txt b/Documentation/devicetree/bindings/powerpc/fsl/mpic-msgr.txt
new file mode 100644
index 000000000000..bc8ded641ab6
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/mpic-msgr.txt
@@ -0,0 +1,63 @@
1* FSL MPIC Message Registers
2
3This binding specifies what properties must be available in the device tree
4representation of the message register blocks found in some FSL MPIC
5implementations.
6
7Required properties:
8
9 - compatible: Specifies the compatibility list for the message register
10 block. The type shall be <string-list> and the value shall be of the form
11 "fsl,mpic-v<version>-msgr", where <version> is the version number of
12 the MPIC containing the message registers.
13
14 - reg: Specifies the base physical address(s) and size(s) of the
15 message register block's addressable register space. The type shall be
16 <prop-encoded-array>.
17
18 - interrupts: Specifies a list of interrupt-specifiers which are available
19 for receiving interrupts. Interrupt-specifier consists of two cells: first
20 cell is interrupt-number and second cell is level-sense. The type shall be
21 <prop-encoded-array>.
22
23Optional properties:
24
25 - mpic-msgr-receive-mask: Specifies what registers in the containing block
26 are allowed to receive interrupts. The value is a bit mask where a set
27 bit at bit 'n' indicates that message register 'n' can receive interrupts.
28 Note that "bit 'n'" is numbered from LSB for PPC hardware. The type shall
29 be <u32>. If not present, then all of the message registers in the block
30 are available.
31
32Aliases:
33
34 An alias should be created for every message register block. They are not
35 required, though. However, a particular implementation of this binding
36 may require aliases to be present. Aliases are of the form
37 'mpic-msgr-block<n>', where <n> is an integer specifying the block's number.
38 Numbers shall start at 0.
39
40Example:
41
42 aliases {
43 mpic-msgr-block0 = &mpic_msgr_block0;
44 mpic-msgr-block1 = &mpic_msgr_block1;
45 };
46
47 mpic_msgr_block0: mpic-msgr-block@41400 {
48 compatible = "fsl,mpic-v3.1-msgr";
49 reg = <0x41400 0x200>;
50 // Message registers 0 and 2 in this block can receive interrupts on
51 // sources 0xb0 and 0xb2, respectively.
52 interrupts = <0xb0 2 0xb2 2>;
53 mpic-msgr-receive-mask = <0x5>;
54 };
55
56 mpic_msgr_block1: mpic-msgr-block@42400 {
57 compatible = "fsl,mpic-v3.1-msgr";
58 reg = <0x42400 0x200>;
59 // Message registers 0 and 2 in this block can receive interrupts on
60 // sources 0xb4 and 0xb6, respectively.
61 interrupts = <0xb4 2 0xb6 2>;
62 mpic-msgr-receive-mask = <0x5>;
63 };
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
index 2cf38bd841fd..dc5744636a57 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
@@ -56,7 +56,27 @@ PROPERTIES
56 to the client. The presence of this property also mandates 56 to the client. The presence of this property also mandates
57 that any initialization related to interrupt sources shall 57 that any initialization related to interrupt sources shall
58 be limited to sources explicitly referenced in the device tree. 58 be limited to sources explicitly referenced in the device tree.
59 59
60 - big-endian
61 Usage: optional
62 Value type: <empty>
63 If present the MPIC will be assumed to be big-endian. Some
64 device-trees omit this property on MPIC nodes even when the MPIC is
65 in fact big-endian, so certain boards override this property.
66
67 - single-cpu-affinity
68 Usage: optional
69 Value type: <empty>
70 If present the MPIC will be assumed to only be able to route
71 non-IPI interrupts to a single CPU at a time (EG: Freescale MPIC).
72
73 - last-interrupt-source
74 Usage: optional
75 Value type: <u32>
76 Some MPICs do not correctly report the number of hardware sources
77 in the global feature registers. If specified, this field will
78 override the value read from MPIC_GREG_FEATURE_LAST_SRC.
79
60INTERRUPT SPECIFIER DEFINITION 80INTERRUPT SPECIFIER DEFINITION
61 81
62 Interrupt specifiers consists of 4 cells encoded as 82 Interrupt specifiers consists of 4 cells encoded as
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
index 5d586e1ccaf5..5693877ab377 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
@@ -6,8 +6,10 @@ Required properties:
6 etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on 6 etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
7 the parent type. 7 the parent type.
8 8
9- reg : should contain the address and the length of the shared message 9- reg : It may contain one or two regions. The first region should contain
10 interrupt register set. 10 the address and the length of the shared message interrupt register set.
11 The second region should contain the address of aliased MSIIR register for
12 platforms that have such an alias.
11 13
12- msi-available-ranges: use <start count> style section to define which 14- msi-available-ranges: use <start count> style section to define which
13 msi interrupt can be used in the 256 msi interrupts. This property is 15 msi interrupt can be used in the 256 msi interrupts. This property is
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
new file mode 100644
index 000000000000..3007bc98af28
--- /dev/null
+++ b/Documentation/powerpc/firmware-assisted-dump.txt
@@ -0,0 +1,270 @@
1
2 Firmware-Assisted Dump
3 ------------------------
4 July 2011
5
6The goal of firmware-assisted dump is to enable the dump of
7a crashed system, and to do so from a fully-reset system, and
8to minimize the total elapsed time until the system is back
9in production use.
10
11- Firmware assisted dump (fadump) infrastructure is intended to replace
12 the existing phyp assisted dump.
13- Fadump uses the same firmware interfaces and memory reservation model
14 as phyp assisted dump.
15- Unlike phyp dump, fadump exports the memory dump through /proc/vmcore
16 in the ELF format in the same way as kdump. This helps us reuse the
17 kdump infrastructure for dump capture and filtering.
18- Unlike phyp dump, userspace tool does not need to refer any sysfs
19 interface while reading /proc/vmcore.
20- Unlike phyp dump, fadump allows user to release all the memory reserved
21 for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
22- Once enabled through kernel boot parameter, fadump can be
23 started/stopped through /sys/kernel/fadump_registered interface (see
24 sysfs files section below) and can be easily integrated with kdump
25 service start/stop init scripts.
26
27Comparing with kdump or other strategies, firmware-assisted
28dump offers several strong, practical advantages:
29
30-- Unlike kdump, the system has been reset, and loaded
31 with a fresh copy of the kernel. In particular,
32 PCI and I/O devices have been reinitialized and are
33 in a clean, consistent state.
34-- Once the dump is copied out, the memory that held the dump
35 is immediately available to the running kernel. And therefore,
36 unlike kdump, fadump doesn't need a 2nd reboot to get back
37 the system to the production configuration.
38
39The above can only be accomplished by coordination with,
40and assistance from the Power firmware. The procedure is
41as follows:
42
43-- The first kernel registers the sections of memory with the
44 Power firmware for dump preservation during OS initialization.
45 These registered sections of memory are reserved by the first
46 kernel during early boot.
47
48-- When a system crashes, the Power firmware will save
49 the low memory (boot memory of size larger of 5% of system RAM
50 or 256MB) of RAM to the previous registered region. It will
51 also save system registers, and hardware PTE's.
52
53 NOTE: The term 'boot memory' means size of the low memory chunk
54 that is required for a kernel to boot successfully when
55 booted with restricted memory. By default, the boot memory
56 size will be the larger of 5% of system RAM or 256MB.
57 Alternatively, user can also specify boot memory size
58 through boot parameter 'fadump_reserve_mem=' which will
59 override the default calculated size. Use this option
60 if default boot memory size is not sufficient for second
61 kernel to boot successfully.
62
63-- After the low memory (boot memory) area has been saved, the
64 firmware will reset PCI and other hardware state. It will
65 *not* clear the RAM. It will then launch the bootloader, as
66 normal.
67
68-- The freshly booted kernel will notice that there is a new
69 node (ibm,dump-kernel) in the device tree, indicating that
70 there is crash data available from a previous boot. During
71 the early boot OS will reserve rest of the memory above
72 boot memory size effectively booting with restricted memory
73 size. This will make sure that the second kernel will not
74 touch any of the dump memory area.
75
76-- User-space tools will read /proc/vmcore to obtain the contents
77 of memory, which holds the previous crashed kernel dump in ELF
78 format. The userspace tools may copy this info to disk, or
79 network, nas, san, iscsi, etc. as desired.
80
81-- Once the userspace tool is done saving dump, it will echo
82 '1' to /sys/kernel/fadump_release_mem to release the reserved
83 memory back to general use, except the memory required for
84 next firmware-assisted dump registration.
85
86 e.g.
87 # echo 1 > /sys/kernel/fadump_release_mem
88
89Please note that the firmware-assisted dump feature
90is only available on Power6 and above systems with recent
91firmware versions.
92
93Implementation details:
94----------------------
95
96During boot, a check is made to see if firmware supports
97this feature on that particular machine. If it does, then
98we check to see if an active dump is waiting for us. If yes
99then everything but boot memory size of RAM is reserved during
100early boot (See Fig. 2). This area is released once we finish
101collecting the dump from user land scripts (e.g. kdump scripts)
102that are run. If there is dump data, then the
103/sys/kernel/fadump_release_mem file is created, and the reserved
104memory is held.
105
106If there is no waiting dump data, then only the memory required
107to hold CPU state, HPTE region, boot memory dump and elfcore
108header, is reserved at the top of memory (see Fig. 1). This area
109is *not* released: this region will be kept permanently reserved,
110so that it can act as a receptacle for a copy of the boot memory
111content in addition to CPU state and HPTE region, in the case a
112crash does occur.
113
114 o Memory Reservation during first kernel
115
116 Low memory Top of memory
117 0 boot memory size |
118 | | |<--Reserved dump area -->|
119 V V | Permanent Reservation V
120 +-----------+----------/ /----------+---+----+-----------+----+
121 | | |CPU|HPTE| DUMP |ELF |
122 +-----------+----------/ /----------+---+----+-----------+----+
123 | ^
124 | |
125 \ /
126 -------------------------------------------
127 Boot memory content gets transferred to
128 reserved area by firmware at the time of
129 crash
130 Fig. 1
131
132 o Memory Reservation during second kernel after crash
133
134 Low memory Top of memory
135 0 boot memory size |
136 | |<------------- Reserved dump area ----------- -->|
137 V V V
138 +-----------+----------/ /----------+---+----+-----------+----+
139 | | |CPU|HPTE| DUMP |ELF |
140 +-----------+----------/ /----------+---+----+-----------+----+
141 | |
142 V V
143 Used by second /proc/vmcore
144 kernel to boot
145 Fig. 2
146
147Currently the dump will be copied from /proc/vmcore to a
148a new file upon user intervention. The dump data available through
149/proc/vmcore will be in ELF format. Hence the existing kdump
150infrastructure (kdump scripts) to save the dump works fine with
151minor modifications.
152
153The tools to examine the dump will be same as the ones
154used for kdump.
155
156How to enable firmware-assisted dump (fadump):
157-------------------------------------
158
1591. Set config option CONFIG_FA_DUMP=y and build kernel.
1602. Boot into linux kernel with 'fadump=on' kernel cmdline option.
1613. Optionally, user can also set 'fadump_reserve_mem=' kernel cmdline
162 to specify size of the memory to reserve for boot memory dump
163 preservation.
164
165NOTE: If firmware-assisted dump fails to reserve memory then it will
166 fallback to existing kdump mechanism if 'crashkernel=' option
167 is set at kernel cmdline.
168
169Sysfs/debugfs files:
170------------
171
172Firmware-assisted dump feature uses sysfs file system to hold
173the control files and debugfs file to display memory reserved region.
174
175Here is the list of files under kernel sysfs:
176
177 /sys/kernel/fadump_enabled
178
179 This is used to display the fadump status.
180 0 = fadump is disabled
181 1 = fadump is enabled
182
183 This interface can be used by kdump init scripts to identify if
184 fadump is enabled in the kernel and act accordingly.
185
186 /sys/kernel/fadump_registered
187
188 This is used to display the fadump registration status as well
189 as to control (start/stop) the fadump registration.
190 0 = fadump is not registered.
191 1 = fadump is registered and ready to handle system crash.
192
193 To register fadump echo 1 > /sys/kernel/fadump_registered and
194 echo 0 > /sys/kernel/fadump_registered for un-register and stop the
195 fadump. Once the fadump is un-registered, the system crash will not
196 be handled and vmcore will not be captured. This interface can be
197 easily integrated with kdump service start/stop.
198
199 /sys/kernel/fadump_release_mem
200
201 This file is available only when fadump is active during
202 second kernel. This is used to release the reserved memory
203 region that are held for saving crash dump. To release the
204 reserved memory echo 1 to it:
205
206 echo 1 > /sys/kernel/fadump_release_mem
207
208 After echo 1, the content of the /sys/kernel/debug/powerpc/fadump_region
209 file will change to reflect the new memory reservations.
210
211 The existing userspace tools (kdump infrastructure) can be easily
212 enhanced to use this interface to release the memory reserved for
213 dump and continue without 2nd reboot.
214
215Here is the list of files under powerpc debugfs:
216(Assuming debugfs is mounted on /sys/kernel/debug directory.)
217
218 /sys/kernel/debug/powerpc/fadump_region
219
220 This file shows the reserved memory regions if fadump is
221 enabled otherwise this file is empty. The output format
222 is:
223 <region>: [<start>-<end>] <reserved-size> bytes, Dumped: <dump-size>
224
225 e.g.
226 Contents when fadump is registered during first kernel
227
228 # cat /sys/kernel/debug/powerpc/fadump_region
229 CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x0
230 HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x0
231 DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x0
232
233 Contents when fadump is active during second kernel
234
235 # cat /sys/kernel/debug/powerpc/fadump_region
236 CPU : [0x0000006ffb0000-0x0000006fff001f] 0x40020 bytes, Dumped: 0x40020
237 HPTE: [0x0000006fff0020-0x0000006fff101f] 0x1000 bytes, Dumped: 0x1000
238 DUMP: [0x0000006fff1020-0x0000007fff101f] 0x10000000 bytes, Dumped: 0x10000000
239 : [0x00000010000000-0x0000006ffaffff] 0x5ffb0000 bytes, Dumped: 0x5ffb0000
240
241NOTE: Please refer to Documentation/filesystems/debugfs.txt on
242 how to mount the debugfs filesystem.
243
244
245TODO:
246-----
247 o Need to come up with the better approach to find out more
248 accurate boot memory size that is required for a kernel to
249 boot successfully when booted with restricted memory.
250 o The fadump implementation introduces a fadump crash info structure
251 in the scratch area before the ELF core header. The idea of introducing
252 this structure is to pass some important crash info data to the second
253 kernel which will help second kernel to populate ELF core header with
254 correct data before it gets exported through /proc/vmcore. The current
255 design implementation does not address a possibility of introducing
256 additional fields (in future) to this structure without affecting
257 compatibility. Need to come up with the better approach to address this.
258 The possible approaches are:
259 1. Introduce version field for version tracking, bump up the version
260 whenever a new field is added to the structure in future. The version
261 field can be used to find out what fields are valid for the current
262 version of the structure.
263 2. Reserve the area of predefined size (say PAGE_SIZE) for this
264 structure and have unused area as reserved (initialized to zero)
265 for future field additions.
266 The advantage of approach 1 over 2 is we don't need to reserve extra space.
267---
268Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
269This document is based on the original documentation written for phyp
270assisted dump by Linas Vepstas and Manish Ahuja.
diff --git a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
index 10dd4ab93b85..0d540a31ea1a 100644
--- a/Documentation/powerpc/mpc52xx.txt
+++ b/Documentation/powerpc/mpc52xx.txt
@@ -2,7 +2,7 @@ Linux 2.6.x on MPC52xx family
2----------------------------- 2-----------------------------
3 3
4For the latest info, go to http://www.246tNt.com/mpc52xx/ 4For the latest info, go to http://www.246tNt.com/mpc52xx/
5 5
6To compile/use : 6To compile/use :
7 7
8 - U-Boot: 8 - U-Boot:
@@ -10,23 +10,23 @@ To compile/use :
10 if you wish to ). 10 if you wish to ).
11 # make lite5200_defconfig 11 # make lite5200_defconfig
12 # make uImage 12 # make uImage
13 13
14 then, on U-boot: 14 then, on U-boot:
15 => tftpboot 200000 uImage 15 => tftpboot 200000 uImage
16 => tftpboot 400000 pRamdisk 16 => tftpboot 400000 pRamdisk
17 => bootm 200000 400000 17 => bootm 200000 400000
18 18
19 - DBug: 19 - DBug:
20 # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION 20 # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
21 if you wish to ). 21 if you wish to ).
22 # make lite5200_defconfig 22 # make lite5200_defconfig
23 # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz 23 # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
24 # make zImage.initrd 24 # make zImage.initrd
25 # make 25 # make
26 26
27 then in DBug: 27 then in DBug:
28 DBug> dn -i zImage.initrd.lite5200 28 DBug> dn -i zImage.initrd.lite5200
29 29
30 30
31Some remarks : 31Some remarks :
32 - The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100 32 - The port is named mpc52xxx, and config options are PPC_MPC52xx. The MGT5100
diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt
deleted file mode 100644
index ad340205d96a..000000000000
--- a/Documentation/powerpc/phyp-assisted-dump.txt
+++ /dev/null
@@ -1,127 +0,0 @@
1
2 Hypervisor-Assisted Dump
3 ------------------------
4 November 2007
5
6The goal of hypervisor-assisted dump is to enable the dump of
7a crashed system, and to do so from a fully-reset system, and
8to minimize the total elapsed time until the system is back
9in production use.
10
11As compared to kdump or other strategies, hypervisor-assisted
12dump offers several strong, practical advantages:
13
14-- Unlike kdump, the system has been reset, and loaded
15 with a fresh copy of the kernel. In particular,
16 PCI and I/O devices have been reinitialized and are
17 in a clean, consistent state.
18-- As the dump is performed, the dumped memory becomes
19 immediately available to the system for normal use.
20-- After the dump is completed, no further reboots are
21 required; the system will be fully usable, and running
22 in its normal, production mode on its normal kernel.
23
24The above can only be accomplished by coordination with,
25and assistance from the hypervisor. The procedure is
26as follows:
27
28-- When a system crashes, the hypervisor will save
29 the low 256MB of RAM to a previously registered
30 save region. It will also save system state, system
31 registers, and hardware PTE's.
32
33-- After the low 256MB area has been saved, the
34 hypervisor will reset PCI and other hardware state.
35 It will *not* clear RAM. It will then launch the
36 bootloader, as normal.
37
38-- The freshly booted kernel will notice that there
39 is a new node (ibm,dump-kernel) in the device tree,
40 indicating that there is crash data available from
41 a previous boot. It will boot into only 256MB of RAM,
42 reserving the rest of system memory.
43
44-- Userspace tools will parse /sys/kernel/release_region
45 and read /proc/vmcore to obtain the contents of memory,
46 which holds the previous crashed kernel. The userspace
47 tools may copy this info to disk, or network, nas, san,
48 iscsi, etc. as desired.
49
50 For Example: the values in /sys/kernel/release-region
51 would look something like this (address-range pairs).
52 CPU:0x177fee000-0x10000: HPTE:0x177ffe020-0x1000: /
53 DUMP:0x177fff020-0x10000000, 0x10000000-0x16F1D370A
54
55-- As the userspace tools complete saving a portion of
56 dump, they echo an offset and size to
57 /sys/kernel/release_region to release the reserved
58 memory back to general use.
59
60 An example of this is:
61 "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
62 which will release 256MB at the 1GB boundary.
63
64Please note that the hypervisor-assisted dump feature
65is only available on Power6-based systems with recent
66firmware versions.
67
68Implementation details:
69----------------------
70
71During boot, a check is made to see if firmware supports
72this feature on this particular machine. If it does, then
73we check to see if a active dump is waiting for us. If yes
74then everything but 256 MB of RAM is reserved during early
75boot. This area is released once we collect a dump from user
76land scripts that are run. If there is dump data, then
77the /sys/kernel/release_region file is created, and
78the reserved memory is held.
79
80If there is no waiting dump data, then only the highest
81256MB of the ram is reserved as a scratch area. This area
82is *not* released: this region will be kept permanently
83reserved, so that it can act as a receptacle for a copy
84of the low 256MB in the case a crash does occur. See,
85however, "open issues" below, as to whether
86such a reserved region is really needed.
87
88Currently the dump will be copied from /proc/vmcore to a
89a new file upon user intervention. The starting address
90to be read and the range for each data point in provided
91in /sys/kernel/release_region.
92
93The tools to examine the dump will be same as the ones
94used for kdump.
95
96General notes:
97--------------
98Security: please note that there are potential security issues
99with any sort of dump mechanism. In particular, plaintext
100(unencrypted) data, and possibly passwords, may be present in
101the dump data. Userspace tools must take adequate precautions to
102preserve security.
103
104Open issues/ToDo:
105------------
106 o The various code paths that tell the hypervisor that a crash
107 occurred, vs. it simply being a normal reboot, should be
108 reviewed, and possibly clarified/fixed.
109
110 o Instead of using /sys/kernel, should there be a /sys/dump
111 instead? There is a dump_subsys being created by the s390 code,
112 perhaps the pseries code should use a similar layout as well.
113
114 o Is reserving a 256MB region really required? The goal of
115 reserving a 256MB scratch area is to make sure that no
116 important crash data is clobbered when the hypervisor
117 save low mem to the scratch area. But, if one could assure
118 that nothing important is located in some 256MB area, then
119 it would not need to be reserved. Something that can be
120 improved in subsequent versions.
121
122 o Still working the kdump team to integrate this with kdump,
123 some work remains but this would not affect the current
124 patches.
125
126 o Still need to write a shell script, to copy the dump away.
127 Currently I am parsing it manually.
diff --git a/MAINTAINERS b/MAINTAINERS
index 92f9924c4335..58f60356f071 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4071,7 +4071,7 @@ M: Josh Boyer <jwboyer@gmail.com>
4071M: Matt Porter <mporter@kernel.crashing.org> 4071M: Matt Porter <mporter@kernel.crashing.org>
4072W: http://www.penguinppc.org/ 4072W: http://www.penguinppc.org/
4073L: linuxppc-dev@lists.ozlabs.org 4073L: linuxppc-dev@lists.ozlabs.org
4074T: git git://git.infradead.org/users/jwboyer/powerpc-4xx.git 4074T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
4075S: Maintained 4075S: Maintained
4076F: arch/powerpc/platforms/40x/ 4076F: arch/powerpc/platforms/40x/
4077F: arch/powerpc/platforms/44x/ 4077F: arch/powerpc/platforms/44x/
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 303703d716fe..d219ebecabf0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,7 @@ config PPC
134 select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 134 select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
135 select HAVE_GENERIC_HARDIRQS 135 select HAVE_GENERIC_HARDIRQS
136 select HAVE_SPARSE_IRQ 136 select HAVE_SPARSE_IRQ
137 select SPARSE_IRQ
137 select IRQ_PER_CPU 138 select IRQ_PER_CPU
138 select IRQ_DOMAIN 139 select IRQ_DOMAIN
139 select GENERIC_IRQ_SHOW 140 select GENERIC_IRQ_SHOW
@@ -377,13 +378,16 @@ config CRASH_DUMP
377 The same kernel binary can be used as production kernel and dump 378 The same kernel binary can be used as production kernel and dump
378 capture kernel. 379 capture kernel.
379 380
380config PHYP_DUMP 381config FA_DUMP
381 bool "Hypervisor-assisted dump (EXPERIMENTAL)" 382 bool "Firmware-assisted dump"
382 depends on PPC_PSERIES && EXPERIMENTAL 383 depends on PPC64 && PPC_RTAS && CRASH_DUMP
383 help 384 help
384 Hypervisor-assisted dump is meant to be a kdump replacement 385 A robust mechanism to get reliable kernel crash dump with
385 offering robustness and speed not possible without system 386 assistance from firmware. This approach does not use kexec,
386 hypervisor assistance. 387 instead firmware assists in booting the kdump kernel
388 while preserving memory contents. Firmware-assisted dump
389 is meant to be a kdump replacement offering robustness and
390 speed not possible without system firmware assistance.
387 391
388 If unsure, say "N" 392 If unsure, say "N"
389 393
@@ -612,7 +616,7 @@ endmenu
612 616
613config ISA_DMA_API 617config ISA_DMA_API
614 bool 618 bool
615 default !PPC_ISERIES || PCI 619 default PCI
616 620
617menu "Bus options" 621menu "Bus options"
618 622
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 4ccb2a009f74..72d55dbc6119 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -196,13 +196,6 @@ config PPC_EARLY_DEBUG_MAPLE
196 help 196 help
197 Select this to enable early debugging for Maple. 197 Select this to enable early debugging for Maple.
198 198
199config PPC_EARLY_DEBUG_ISERIES
200 bool "iSeries HV Console"
201 depends on PPC_ISERIES
202 help
203 Select this to enable early debugging for legacy iSeries. You need
204 to hit "Ctrl-x Ctrl-x" to see the messages on the console.
205
206config PPC_EARLY_DEBUG_PAS_REALMODE 199config PPC_EARLY_DEBUG_PAS_REALMODE
207 bool "PA Semi real mode" 200 bool "PA Semi real mode"
208 depends on PPC_PASEMI 201 depends on PPC_PASEMI
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b8b105c01c64..6524c6e21896 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -157,6 +157,7 @@ core-y += arch/powerpc/kernel/ \
157 arch/powerpc/net/ 157 arch/powerpc/net/
158core-$(CONFIG_XMON) += arch/powerpc/xmon/ 158core-$(CONFIG_XMON) += arch/powerpc/xmon/
159core-$(CONFIG_KVM) += arch/powerpc/kvm/ 159core-$(CONFIG_KVM) += arch/powerpc/kvm/
160core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/
160 161
161drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ 162drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
162 163
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8844a17ce8ed..e8461cb18d04 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -184,7 +184,6 @@ image-$(CONFIG_PPC_EFIKA) += zImage.chrp
184image-$(CONFIG_PPC_PMAC) += zImage.pmac 184image-$(CONFIG_PPC_PMAC) += zImage.pmac
185image-$(CONFIG_PPC_HOLLY) += dtbImage.holly 185image-$(CONFIG_PPC_HOLLY) += dtbImage.holly
186image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800 186image-$(CONFIG_PPC_PRPMC2800) += dtbImage.prpmc2800
187image-$(CONFIG_PPC_ISERIES) += zImage.iseries
188image-$(CONFIG_DEFAULT_UIMAGE) += uImage 187image-$(CONFIG_DEFAULT_UIMAGE) += uImage
189image-$(CONFIG_EPAPR_BOOT) += zImage.epapr 188image-$(CONFIG_EPAPR_BOOT) += zImage.epapr
190 189
@@ -247,7 +246,7 @@ image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot
247image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads 246image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads
248image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads 247image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads
249image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \ 248image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \
250 cuImage.mpc8548cds \ 249 cuImage.mpc8548cds_32b \
251 cuImage.mpc8555cds 250 cuImage.mpc8555cds
252image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds 251image-$(CONFIG_MPC85xx_MDS) += cuImage.mpc8568mds
253image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \ 252image-$(CONFIG_MPC85xx_DS) += cuImage.mpc8544ds \
@@ -311,12 +310,6 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
311$(obj)/vmlinux.strip: vmlinux 310$(obj)/vmlinux.strip: vmlinux
312 $(STRIP) -s -R .comment $< -o $@ 311 $(STRIP) -s -R .comment $< -o $@
313 312
314# The iseries hypervisor won't take an ET_DYN executable, so this
315# changes the type (byte 17) in the file to ET_EXEC (2).
316$(obj)/zImage.iseries: vmlinux
317 $(STRIP) -s -R .comment $< -o $@
318 printf "\x02" | dd of=$@ conv=notrunc bs=1 seek=17
319
320$(obj)/uImage: vmlinux $(wrapperbits) 313$(obj)/uImage: vmlinux $(wrapperbits)
321 $(call if_changed,wrap,uboot) 314 $(call if_changed,wrap,uboot)
322 315
@@ -364,7 +357,7 @@ install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
364# anything not in $(targets) 357# anything not in $(targets)
365clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ 358clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
366 zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \ 359 zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \
367 zImage.iseries zImage.miboot zImage.pmac zImage.pseries \ 360 zImage.miboot zImage.pmac zImage.pseries \
368 zImage.maple simpleImage.* otheros.bld *.dtb 361 zImage.maple simpleImage.* otheros.bld *.dtb
369 362
370# clean up files cached by wrapper 363# clean up files cached by wrapper
diff --git a/arch/powerpc/boot/dts/a4m072.dts b/arch/powerpc/boot/dts/a4m072.dts
new file mode 100644
index 000000000000..fabe7b7d5f13
--- /dev/null
+++ b/arch/powerpc/boot/dts/a4m072.dts
@@ -0,0 +1,168 @@
1/*
2 * a4m072 board Device Tree Source
3 *
4 * Copyright (C) 2011 DENX Software Engineering GmbH
5 * Heiko Schocher <hs@denx.de>
6 *
7 * Copyright (C) 2007 Semihalf
8 * Marian Balakowicz <m8@semihalf.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16/include/ "mpc5200b.dtsi"
17
18/ {
19 model = "anonymous,a4m072";
20 compatible = "anonymous,a4m072";
21
22 soc5200@f0000000 {
23 #address-cells = <1>;
24 #size-cells = <1>;
25 compatible = "fsl,mpc5200b-immr";
26 ranges = <0 0xf0000000 0x0000c000>;
27 reg = <0xf0000000 0x00000100>;
28 bus-frequency = <0>; /* From boot loader */
29 system-frequency = <0>; /* From boot loader */
30
31 cdm@200 {
32 fsl,init-ext-48mhz-en = <0x0>;
33 fsl,init-fd-enable = <0x01>;
34 fsl,init-fd-counters = <0x3333>;
35 };
36
37 timer@600 {
38 fsl,has-wdt;
39 };
40
41 gpt3: timer@630 { /* General Purpose Timer in GPIO mode */
42 compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
43 gpio-controller;
44 #gpio-cells = <2>;
45 };
46
47 gpt4: timer@640 { /* General Purpose Timer in GPIO mode */
48 compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
49 gpio-controller;
50 #gpio-cells = <2>;
51 };
52
53 gpt5: timer@650 { /* General Purpose Timer in GPIO mode */
54 compatible = "fsl,mpc5200b-gpt-gpio","fsl,mpc5200-gpt-gpio";
55 gpio-controller;
56 #gpio-cells = <2>;
57 };
58
59 spi@f00 {
60 status = "disabled";
61 };
62
63 psc@2000 {
64 compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
65 reg = <0x2000 0x100>;
66 interrupts = <2 1 0>;
67 };
68
69 psc@2200 {
70 compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
71 reg = <0x2200 0x100>;
72 interrupts = <2 2 0>;
73 };
74
75 psc@2400 {
76 compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
77 reg = <0x2400 0x100>;
78 interrupts = <2 3 0>;
79 };
80
81 psc@2600 {
82 status = "disabled";
83 };
84
85 psc@2800 {
86 status = "disabled";
87 };
88
89 psc@2c00 {
90 compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
91 reg = <0x2c00 0x100>;
92 interrupts = <2 4 0>;
93 };
94
95 ethernet@3000 {
96 phy-handle = <&phy0>;
97 };
98
99 mdio@3000 {
100 phy0: ethernet-phy@1f {
101 reg = <0x1f>;
102 interrupts = <1 2 0>; /* IRQ 2 active low */
103 };
104 };
105
106 i2c@3d00 {
107 status = "disabled";
108 };
109
110 i2c@3d40 {
111 hwmon@2e {
112 compatible = "nsc,lm87";
113 reg = <0x2e>;
114 };
115 rtc@51 {
116 compatible = "nxp,rtc8564";
117 reg = <0x51>;
118 };
119 };
120 };
121
122 localbus {
123 compatible = "fsl,mpc5200b-lpb","simple-bus";
124 #address-cells = <2>;
125 #size-cells = <1>;
126 ranges = <0 0 0xfe000000 0x02000000
127 1 0 0x62000000 0x00400000
128 2 0 0x64000000 0x00200000
129 3 0 0x66000000 0x01000000
130 6 0 0x68000000 0x01000000
131 7 0 0x6a000000 0x00000004>;
132
133 flash@0,0 {
134 compatible = "cfi-flash";
135 reg = <0 0 0x02000000>;
136 bank-width = <2>;
137 #size-cells = <1>;
138 #address-cells = <1>;
139 };
140 sram0@1,0 {
141 compatible = "mtd-ram";
142 reg = <1 0x00000 0x00400000>;
143 bank-width = <2>;
144 };
145 };
146
147 pci@f0000d00 {
148 #interrupt-cells = <1>;
149 #size-cells = <2>;
150 #address-cells = <3>;
151 device_type = "pci";
152 compatible = "fsl,mpc5200-pci";
153 reg = <0xf0000d00 0x100>;
154 interrupt-map-mask = <0xf800 0 0 7>;
155 interrupt-map = <
156 /* IDSEL 0x16 */
157 0xc000 0 0 1 &mpc5200_pic 1 3 3
158 0xc000 0 0 2 &mpc5200_pic 1 3 3
159 0xc000 0 0 3 &mpc5200_pic 1 3 3
160 0xc000 0 0 4 &mpc5200_pic 1 3 3>;
161 clock-frequency = <0>; /* From boot loader */
162 interrupts = <2 8 0 2 9 0 2 10 0>;
163 bus-range = <0 0>;
164 ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
165 0x02000000 0 0x90000000 0x90000000 0 0x10000000
166 0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
167 };
168};
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 74876f737407..7bda373f10ef 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -33,7 +33,7 @@
33 aliases { 33 aliases {
34 ethernet0 = &EMAC0; 34 ethernet0 = &EMAC0;
35 serial0 = &UART0; 35 serial0 = &UART0;
36 //serial1 = &UART1; --gcl missing UART1 label 36 serial1 = &UART1;
37 }; 37 };
38 38
39 cpus { 39 cpus {
@@ -52,7 +52,7 @@
52 d-cache-size = <32768>; 52 d-cache-size = <32768>;
53 dcr-controller; 53 dcr-controller;
54 dcr-access-method = "native"; 54 dcr-access-method = "native";
55 //next-level-cache = <&L2C0>; --gcl missing L2C0 label 55 next-level-cache = <&L2C0>;
56 }; 56 };
57 }; 57 };
58 58
@@ -117,6 +117,16 @@
117 dcr-reg = <0x00c 0x002>; 117 dcr-reg = <0x00c 0x002>;
118 }; 118 };
119 119
120 L2C0: l2c {
121 compatible = "ibm,l2-cache-apm82181", "ibm,l2-cache";
122 dcr-reg = <0x020 0x008
123 0x030 0x008>;
124 cache-line-size = <32>;
125 cache-size = <262144>;
126 interrupt-parent = <&UIC1>;
127 interrupts = <11 1>;
128 };
129
120 plb { 130 plb {
121 compatible = "ibm,plb4"; 131 compatible = "ibm,plb4";
122 #address-cells = <2>; 132 #address-cells = <2>;
@@ -182,6 +192,53 @@
182 reg = <0x001a0000 0x00060000>; 192 reg = <0x001a0000 0x00060000>;
183 }; 193 };
184 }; 194 };
195
196 ndfc@1,0 {
197 compatible = "ibm,ndfc";
198 reg = <0x00000003 0x00000000 0x00002000>;
199 ccr = <0x00001000>;
200 bank-settings = <0x80002222>;
201 #address-cells = <1>;
202 #size-cells = <1>;
203 /* 2Gb Nand Flash */
204 nand {
205 #address-cells = <1>;
206 #size-cells = <1>;
207
208 partition@0 {
209 label = "firmware";
210 reg = <0x00000000 0x00C00000>;
211 };
212 partition@c00000 {
213 label = "environment";
214 reg = <0x00C00000 0x00B00000>;
215 };
216 partition@1700000 {
217 label = "kernel";
218 reg = <0x01700000 0x00E00000>;
219 };
220 partition@2500000 {
221 label = "root";
222 reg = <0x02500000 0x08200000>;
223 };
224 partition@a700000 {
225 label = "device-tree";
226 reg = <0x0A700000 0x00B00000>;
227 };
228 partition@b200000 {
229 label = "config";
230 reg = <0x0B200000 0x00D00000>;
231 };
232 partition@bf00000 {
233 label = "diag";
234 reg = <0x0BF00000 0x00C00000>;
235 };
236 partition@cb00000 {
237 label = "vendor";
238 reg = <0x0CB00000 0x3500000>;
239 };
240 };
241 };
185 }; 242 };
186 243
187 UART0: serial@ef600300 { 244 UART0: serial@ef600300 {
@@ -195,11 +252,36 @@
195 interrupts = <0x1 0x4>; 252 interrupts = <0x1 0x4>;
196 }; 253 };
197 254
255 UART1: serial@ef600400 {
256 device_type = "serial";
257 compatible = "ns16550";
258 reg = <0xef600400 0x00000008>;
259 virtual-reg = <0xef600400>;
260 clock-frequency = <0>; /* Filled in by U-Boot */
261 current-speed = <0>; /* Filled in by U-Boot */
262 interrupt-parent = <&UIC0>;
263 interrupts = <0x1 0x4>;
264 };
265
198 IIC0: i2c@ef600700 { 266 IIC0: i2c@ef600700 {
199 compatible = "ibm,iic"; 267 compatible = "ibm,iic";
200 reg = <0xef600700 0x00000014>; 268 reg = <0xef600700 0x00000014>;
201 interrupt-parent = <&UIC0>; 269 interrupt-parent = <&UIC0>;
202 interrupts = <0x2 0x4>; 270 interrupts = <0x2 0x4>;
271 #address-cells = <1>;
272 #size-cells = <0>;
273 rtc@68 {
274 compatible = "stm,m41t80";
275 reg = <0x68>;
276 interrupt-parent = <&UIC0>;
277 interrupts = <0x9 0x8>;
278 };
279 sttm@4C {
280 compatible = "adm,adm1032";
281 reg = <0x4C>;
282 interrupt-parent = <&UIC1>;
283 interrupts = <0x1E 0x8>; /* CPU_THERNAL_L */
284 };
203 }; 285 };
204 286
205 IIC1: i2c@ef600800 { 287 IIC1: i2c@ef600800 {
@@ -250,5 +332,46 @@
250 }; 332 };
251 }; 333 };
252 334
335 PCIE0: pciex@d00000000 {
336 device_type = "pci";
337 #interrupt-cells = <1>;
338 #size-cells = <2>;
339 #address-cells = <3>;
340 compatible = "ibm,plb-pciex-apm821xx", "ibm,plb-pciex";
341 primary;
342 port = <0x0>; /* port number */
343 reg = <0x0000000d 0x00000000 0x20000000 /* Config space access */
344 0x0000000c 0x08010000 0x00001000>; /* Registers */
345 dcr-reg = <0x100 0x020>;
346 sdr-base = <0x300>;
347
348 /* Outbound ranges, one memory and one IO,
349 * later cannot be changed
350 */
351 ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
352 0x02000000 0x00000000 0x00000000 0x0000000f 0x00000000 0x00000000 0x00100000
353 0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
354
355 /* Inbound 2GB range starting at 0 */
356 dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
357
358 /* This drives busses 40 to 0x7f */
359 bus-range = <0x40 0x7f>;
360
361 /* Legacy interrupts (note the weird polarity, the bridge seems
362 * to invert PCIe legacy interrupts).
363 * We are de-swizzling here because the numbers are actually for
364 * port of the root complex virtual P2P bridge. But I want
365 * to avoid putting a node for it in the tree, so the numbers
366 * below are basically de-swizzled numbers.
367 * The real slot is on idsel 0, so the swizzling is 1:1
368 */
369 interrupt-map-mask = <0x0 0x0 0x0 0x7>;
370 interrupt-map = <
371 0x0 0x0 0x0 0x1 &UIC3 0xc 0x4 /* swizzled int A */
372 0x0 0x0 0x0 0x2 &UIC3 0xd 0x4 /* swizzled int B */
373 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
374 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
375 };
253 }; 376 };
254}; 377};
diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
index b37da56018b6..c8b2daa40ac8 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8536si-post.dtsi
@@ -202,7 +202,7 @@
202/include/ "pq3-etsec1-timer-0.dtsi" 202/include/ "pq3-etsec1-timer-0.dtsi"
203 203
204 usb@22000 { 204 usb@22000 {
205 compatible = "fsl,mpc8536-usb2-mph", "fsl-usb2-mph"; 205 compatible = "fsl-usb2-mph-v1.2", "fsl,mpc8536-usb2-mph", "fsl-usb2-mph";
206 reg = <0x22000 0x1000>; 206 reg = <0x22000 0x1000>;
207 #address-cells = <1>; 207 #address-cells = <1>;
208 #size-cells = <0>; 208 #size-cells = <0>;
@@ -210,7 +210,7 @@
210 }; 210 };
211 211
212 usb@23000 { 212 usb@23000 {
213 compatible = "fsl,mpc8536-usb2-mph", "fsl-usb2-mph"; 213 compatible = "fsl-usb2-mph-v1.2", "fsl,mpc8536-usb2-mph", "fsl-usb2-mph";
214 reg = <0x23000 0x1000>; 214 reg = <0x23000 0x1000>;
215 #address-cells = <1>; 215 #address-cells = <1>;
216 #size-cells = <0>; 216 #size-cells = <0>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
index 9d8023a69d7d..579d76cb8e32 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-post.dtsi
@@ -89,6 +89,21 @@
89 }; 89 };
90}; 90};
91 91
92&rio {
93 compatible = "fsl,srio";
94 interrupts = <48 2 0 0>;
95 #address-cells = <2>;
96 #size-cells = <2>;
97 fsl,srio-rmu-handle = <&rmu>;
98 ranges;
99
100 port1 {
101 #address-cells = <2>;
102 #size-cells = <2>;
103 cell-index = <1>;
104 };
105};
106
92&soc { 107&soc {
93 #address-cells = <1>; 108 #address-cells = <1>;
94 #size-cells = <1>; 109 #size-cells = <1>;
@@ -134,6 +149,7 @@
134 149
135/include/ "pq3-sec2.1-0.dtsi" 150/include/ "pq3-sec2.1-0.dtsi"
136/include/ "pq3-mpic.dtsi" 151/include/ "pq3-mpic.dtsi"
152/include/ "pq3-rmu-0.dtsi"
137 153
138 global-utilities@e0000 { 154 global-utilities@e0000 {
139 compatible = "fsl,mpc8548-guts"; 155 compatible = "fsl,mpc8548-guts";
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
index 289f1218d755..720422d83529 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
@@ -43,7 +43,9 @@
43 serial0 = &serial0; 43 serial0 = &serial0;
44 serial1 = &serial1; 44 serial1 = &serial1;
45 ethernet0 = &enet0; 45 ethernet0 = &enet0;
46 ethernet1 = &enet2; 46 ethernet1 = &enet1;
47 ethernet2 = &enet2;
48 ethernet3 = &enet3;
47 pci0 = &pci0; 49 pci0 = &pci0;
48 pci1 = &pci1; 50 pci1 = &pci1;
49 pci2 = &pci2; 51 pci2 = &pci2;
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
index a97d1263372c..0bde9ee8afaf 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -156,6 +156,9 @@
156 156
157/include/ "pq3-dma-0.dtsi" 157/include/ "pq3-dma-0.dtsi"
158/include/ "pq3-usb2-dr-0.dtsi" 158/include/ "pq3-usb2-dr-0.dtsi"
159 usb@22000 {
160 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
161 };
159/include/ "pq3-esdhc-0.dtsi" 162/include/ "pq3-esdhc-0.dtsi"
160 sdhc@2e000 { 163 sdhc@2e000 {
161 compatible = "fsl,p1010-esdhc", "fsl,esdhc"; 164 compatible = "fsl,p1010-esdhc", "fsl,esdhc";
diff --git a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
index 5de5fc351314..68cc5e7f6477 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
@@ -142,7 +142,13 @@
142 142
143/include/ "pq3-dma-0.dtsi" 143/include/ "pq3-dma-0.dtsi"
144/include/ "pq3-usb2-dr-0.dtsi" 144/include/ "pq3-usb2-dr-0.dtsi"
145 usb@22000 {
146 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
147 };
145/include/ "pq3-usb2-dr-1.dtsi" 148/include/ "pq3-usb2-dr-1.dtsi"
149 usb@23000 {
150 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
151 };
146 152
147/include/ "pq3-esdhc-0.dtsi" 153/include/ "pq3-esdhc-0.dtsi"
148 sdhc@2e000 { 154 sdhc@2e000 {
diff --git a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
index 38ba54d1e32e..4252ef85fb7a 100644
--- a/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
@@ -142,8 +142,15 @@
142 142
143/include/ "pq3-dma-0.dtsi" 143/include/ "pq3-dma-0.dtsi"
144/include/ "pq3-usb2-dr-0.dtsi" 144/include/ "pq3-usb2-dr-0.dtsi"
145 usb@22000 {
146 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
147 };
145 148
146/include/ "pq3-esdhc-0.dtsi" 149/include/ "pq3-esdhc-0.dtsi"
150 sdhc@2e000 {
151 sdhci,auto-cmd12;
152 };
153
147/include/ "pq3-sec3.3-0.dtsi" 154/include/ "pq3-sec3.3-0.dtsi"
148 155
149/include/ "pq3-mpic.dtsi" 156/include/ "pq3-mpic.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
index ff9ed1d87929..06216b8c0af5 100644
--- a/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
@@ -35,7 +35,11 @@
35&lbc { 35&lbc {
36 #address-cells = <2>; 36 #address-cells = <2>;
37 #size-cells = <1>; 37 #size-cells = <1>;
38 compatible = "fsl,p1022-elbc", "fsl,elbc", "simple-bus"; 38 /*
39 * The localbus on the P1022 is not a simple-bus because of the eLBC
40 * pin muxing when the DIU is enabled.
41 */
42 compatible = "fsl,p1022-elbc", "fsl,elbc";
39 interrupts = <19 2 0 0>; 43 interrupts = <19 2 0 0>;
40}; 44};
41 45
@@ -199,7 +203,13 @@
199 203
200/include/ "pq3-dma-0.dtsi" 204/include/ "pq3-dma-0.dtsi"
201/include/ "pq3-usb2-dr-0.dtsi" 205/include/ "pq3-usb2-dr-0.dtsi"
206 usb@22000 {
207 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
208 };
202/include/ "pq3-usb2-dr-1.dtsi" 209/include/ "pq3-usb2-dr-1.dtsi"
210 usb@23000 {
211 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
212 };
203 213
204/include/ "pq3-esdhc-0.dtsi" 214/include/ "pq3-esdhc-0.dtsi"
205 sdhc@2e000 { 215 sdhc@2e000 {
diff --git a/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi b/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi
index b06bb4cc1fe8..941fa159cefb 100644
--- a/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1023si-post.dtsi
@@ -142,6 +142,9 @@
142 142
143/include/ "pq3-dma-0.dtsi" 143/include/ "pq3-dma-0.dtsi"
144/include/ "pq3-usb2-dr-0.dtsi" 144/include/ "pq3-usb2-dr-0.dtsi"
145 usb@22000 {
146 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
147 };
145 148
146 crypto: crypto@300000 { 149 crypto: crypto@300000 {
147 compatible = "fsl,sec-v4.2", "fsl,sec-v4.0"; 150 compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
index 332e9e75e6c2..884e01bcb243 100644
--- a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi
@@ -171,6 +171,9 @@
171 171
172/include/ "pq3-dma-0.dtsi" 172/include/ "pq3-dma-0.dtsi"
173/include/ "pq3-usb2-dr-0.dtsi" 173/include/ "pq3-usb2-dr-0.dtsi"
174 usb@22000 {
175 compatible = "fsl-usb2-dr-v1.6", "fsl-usb2-dr";
176 };
174/include/ "pq3-etsec1-0.dtsi" 177/include/ "pq3-etsec1-0.dtsi"
175/include/ "pq3-etsec1-timer-0.dtsi" 178/include/ "pq3-etsec1-timer-0.dtsi"
176 179
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
index 234a399ddeb2..531eab82c6c9 100644
--- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
@@ -309,12 +309,14 @@
309/include/ "qoriq-gpio-0.dtsi" 309/include/ "qoriq-gpio-0.dtsi"
310/include/ "qoriq-usb2-mph-0.dtsi" 310/include/ "qoriq-usb2-mph-0.dtsi"
311 usb0: usb@210000 { 311 usb0: usb@210000 {
312 compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
312 phy_type = "utmi"; 313 phy_type = "utmi";
313 port0; 314 port0;
314 }; 315 };
315 316
316/include/ "qoriq-usb2-dr-0.dtsi" 317/include/ "qoriq-usb2-dr-0.dtsi"
317 usb1: usb@211000 { 318 usb1: usb@211000 {
319 compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
318 dr_mode = "host"; 320 dr_mode = "host";
319 phy_type = "utmi"; 321 phy_type = "utmi";
320 }; 322 };
diff --git a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
index d41d08de7f7e..af4ebc8009e3 100644
--- a/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p3041si-post.dtsi
@@ -336,12 +336,14 @@
336/include/ "qoriq-gpio-0.dtsi" 336/include/ "qoriq-gpio-0.dtsi"
337/include/ "qoriq-usb2-mph-0.dtsi" 337/include/ "qoriq-usb2-mph-0.dtsi"
338 usb0: usb@210000 { 338 usb0: usb@210000 {
339 compatible = "fsl-usb2-mph-v1.6", "fsl-usb2-mph";
339 phy_type = "utmi"; 340 phy_type = "utmi";
340 port0; 341 port0;
341 }; 342 };
342 343
343/include/ "qoriq-usb2-dr-0.dtsi" 344/include/ "qoriq-usb2-dr-0.dtsi"
344 usb1: usb@211000 { 345 usb1: usb@211000 {
346 compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
345 dr_mode = "host"; 347 dr_mode = "host";
346 phy_type = "utmi"; 348 phy_type = "utmi";
347 }; 349 };
diff --git a/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi
index a63edd195ae5..b3e56929eee2 100644
--- a/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi
@@ -291,6 +291,12 @@
291/include/ "qoriq-duart-1.dtsi" 291/include/ "qoriq-duart-1.dtsi"
292/include/ "qoriq-gpio-0.dtsi" 292/include/ "qoriq-gpio-0.dtsi"
293/include/ "qoriq-usb2-mph-0.dtsi" 293/include/ "qoriq-usb2-mph-0.dtsi"
294 usb@210000 {
295 compatible = "fsl-usb2-mph-v2.2", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
296 };
294/include/ "qoriq-usb2-dr-0.dtsi" 297/include/ "qoriq-usb2-dr-0.dtsi"
298 usb@211000 {
299 compatible = "fsl-usb2-dr-v2.2", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
300 };
295/include/ "qoriq-sec4.1-0.dtsi" 301/include/ "qoriq-sec4.1-0.dtsi"
296}; 302};
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
index 914074b91a85..64b6abea8464 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
@@ -339,12 +339,14 @@
339/include/ "qoriq-gpio-0.dtsi" 339/include/ "qoriq-gpio-0.dtsi"
340/include/ "qoriq-usb2-mph-0.dtsi" 340/include/ "qoriq-usb2-mph-0.dtsi"
341 usb0: usb@210000 { 341 usb0: usb@210000 {
342 compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
342 phy_type = "utmi"; 343 phy_type = "utmi";
343 port0; 344 port0;
344 }; 345 };
345 346
346/include/ "qoriq-usb2-dr-0.dtsi" 347/include/ "qoriq-usb2-dr-0.dtsi"
347 usb1: usb@211000 { 348 usb1: usb@211000 {
349 compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
348 dr_mode = "host"; 350 dr_mode = "host";
349 phy_type = "utmi"; 351 phy_type = "utmi";
350 }; 352 };
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi
index a1979ae334a7..3b0650a98478 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-0.dtsi
@@ -1,7 +1,7 @@
1/* 1/*
2 * PQ3 eTSEC device tree stub [ @ offsets 0x24000 ] 2 * PQ3 eTSEC device tree stub [ @ offsets 0x24000 ]
3 * 3 *
4 * Copyright 2011 Freescale Semiconductor Inc. 4 * Copyright 2011-2012 Freescale Semiconductor Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
@@ -41,6 +41,7 @@ ethernet@24000 {
41 compatible = "gianfar"; 41 compatible = "gianfar";
42 reg = <0x24000 0x1000>; 42 reg = <0x24000 0x1000>;
43 ranges = <0x0 0x24000 0x1000>; 43 ranges = <0x0 0x24000 0x1000>;
44 fsl,magic-packet;
44 local-mac-address = [ 00 00 00 00 00 00 ]; 45 local-mac-address = [ 00 00 00 00 00 00 ];
45 interrupts = <29 2 0 0 30 2 0 0 34 2 0 0>; 46 interrupts = <29 2 0 0 30 2 0 0 34 2 0 0>;
46}; 47};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi
index 4c4fdde1ec2a..96693b41f0f1 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-1.dtsi
@@ -1,7 +1,7 @@
1/* 1/*
2 * PQ3 eTSEC device tree stub [ @ offsets 0x25000 ] 2 * PQ3 eTSEC device tree stub [ @ offsets 0x25000 ]
3 * 3 *
4 * Copyright 2011 Freescale Semiconductor Inc. 4 * Copyright 2011-2012 Freescale Semiconductor Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
@@ -41,6 +41,7 @@ ethernet@25000 {
41 compatible = "gianfar"; 41 compatible = "gianfar";
42 reg = <0x25000 0x1000>; 42 reg = <0x25000 0x1000>;
43 ranges = <0x0 0x25000 0x1000>; 43 ranges = <0x0 0x25000 0x1000>;
44 fsl,magic-packet;
44 local-mac-address = [ 00 00 00 00 00 00 ]; 45 local-mac-address = [ 00 00 00 00 00 00 ];
45 interrupts = <35 2 0 0 36 2 0 0 40 2 0 0>; 46 interrupts = <35 2 0 0 36 2 0 0 40 2 0 0>;
46}; 47};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi
index 4b8ab438668a..6b3fab19da1f 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-2.dtsi
@@ -1,7 +1,7 @@
1/* 1/*
2 * PQ3 eTSEC device tree stub [ @ offsets 0x26000 ] 2 * PQ3 eTSEC device tree stub [ @ offsets 0x26000 ]
3 * 3 *
4 * Copyright 2011 Freescale Semiconductor Inc. 4 * Copyright 2011-2012 Freescale Semiconductor Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
@@ -41,6 +41,7 @@ ethernet@26000 {
41 compatible = "gianfar"; 41 compatible = "gianfar";
42 reg = <0x26000 0x1000>; 42 reg = <0x26000 0x1000>;
43 ranges = <0x0 0x26000 0x1000>; 43 ranges = <0x0 0x26000 0x1000>;
44 fsl,magic-packet;
44 local-mac-address = [ 00 00 00 00 00 00 ]; 45 local-mac-address = [ 00 00 00 00 00 00 ];
45 interrupts = <31 2 0 0 32 2 0 0 33 2 0 0>; 46 interrupts = <31 2 0 0 32 2 0 0 33 2 0 0>;
46}; 47};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi
index 40c9137729ae..0da592d93ddd 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-etsec1-3.dtsi
@@ -1,7 +1,7 @@
1/* 1/*
2 * PQ3 eTSEC device tree stub [ @ offsets 0x27000 ] 2 * PQ3 eTSEC device tree stub [ @ offsets 0x27000 ]
3 * 3 *
4 * Copyright 2011 Freescale Semiconductor Inc. 4 * Copyright 2011-2012 Freescale Semiconductor Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
@@ -41,6 +41,7 @@ ethernet@27000 {
41 compatible = "gianfar"; 41 compatible = "gianfar";
42 reg = <0x27000 0x1000>; 42 reg = <0x27000 0x1000>;
43 ranges = <0x0 0x27000 0x1000>; 43 ranges = <0x0 0x27000 0x1000>;
44 fsl,magic-packet;
44 local-mac-address = [ 00 00 00 00 00 00 ]; 45 local-mac-address = [ 00 00 00 00 00 00 ];
45 interrupts = <37 2 0 0 38 2 0 0 39 2 0 0>; 46 interrupts = <37 2 0 0 38 2 0 0 39 2 0 0>;
46}; 47};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
index 5c8046065844..fdedf7b1fe0f 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
@@ -39,6 +39,9 @@ mpic: pic@40000 {
39 reg = <0x40000 0x40000>; 39 reg = <0x40000 0x40000>;
40 compatible = "fsl,mpic"; 40 compatible = "fsl,mpic";
41 device_type = "open-pic"; 41 device_type = "open-pic";
42 big-endian;
43 single-cpu-affinity;
44 last-interrupt-source = <255>;
42}; 45};
43 46
44timer@41100 { 47timer@41100 {
diff --git a/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi
index bf957a7fca2a..d4c9d5daab21 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-sec4.4-0.dtsi
@@ -33,32 +33,32 @@
33 */ 33 */
34 34
35crypto@30000 { 35crypto@30000 {
36 compatible = "fsl,sec4.4", "fsl,sec4.0"; 36 compatible = "fsl,sec-v4.4", "fsl,sec-v4.0";
37 #address-cells = <1>; 37 #address-cells = <1>;
38 #size-cells = <1>; 38 #size-cells = <1>;
39 reg = <0x30000 0x10000>; 39 reg = <0x30000 0x10000>;
40 interrupts = <58 2 0 0>; 40 interrupts = <58 2 0 0>;
41 41
42 sec_jr0: jr@1000 { 42 sec_jr0: jr@1000 {
43 compatible = "fsl,sec4.4-job-ring", "fsl,sec4.0-job-ring"; 43 compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring";
44 reg = <0x1000 0x1000>; 44 reg = <0x1000 0x1000>;
45 interrupts = <45 2 0 0>; 45 interrupts = <45 2 0 0>;
46 }; 46 };
47 47
48 sec_jr1: jr@2000 { 48 sec_jr1: jr@2000 {
49 compatible = "fsl,sec4.4-job-ring", "fsl,sec4.0-job-ring"; 49 compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring";
50 reg = <0x2000 0x1000>; 50 reg = <0x2000 0x1000>;
51 interrupts = <45 2 0 0>; 51 interrupts = <45 2 0 0>;
52 }; 52 };
53 53
54 sec_jr2: jr@3000 { 54 sec_jr2: jr@3000 {
55 compatible = "fsl,sec4.4-job-ring", "fsl,sec4.0-job-ring"; 55 compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring";
56 reg = <0x3000 0x1000>; 56 reg = <0x3000 0x1000>;
57 interrupts = <45 2 0 0>; 57 interrupts = <45 2 0 0>;
58 }; 58 };
59 59
60 sec_jr3: jr@4000 { 60 sec_jr3: jr@4000 {
61 compatible = "fsl,sec4.4-job-ring", "fsl,sec4.0-job-ring"; 61 compatible = "fsl,sec-v4.4-job-ring", "fsl,sec-v4.0-job-ring";
62 reg = <0x4000 0x1000>; 62 reg = <0x4000 0x1000>;
63 interrupts = <45 2 0 0>; 63 interrupts = <45 2 0 0>;
64 }; 64 };
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi
index b9bada6a87dc..08f42271f86a 100644
--- a/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi
+++ b/arch/powerpc/boot/dts/fsl/qoriq-mpic.dtsi
@@ -53,7 +53,7 @@ timer@41100 {
53 53
54msi0: msi@41600 { 54msi0: msi@41600 {
55 compatible = "fsl,mpic-msi"; 55 compatible = "fsl,mpic-msi";
56 reg = <0x41600 0x200>; 56 reg = <0x41600 0x200 0x44140 4>;
57 msi-available-ranges = <0 0x100>; 57 msi-available-ranges = <0 0x100>;
58 interrupts = < 58 interrupts = <
59 0xe0 0 0 0 59 0xe0 0 0 0
@@ -68,7 +68,7 @@ msi0: msi@41600 {
68 68
69msi1: msi@41800 { 69msi1: msi@41800 {
70 compatible = "fsl,mpic-msi"; 70 compatible = "fsl,mpic-msi";
71 reg = <0x41800 0x200>; 71 reg = <0x41800 0x200 0x45140 4>;
72 msi-available-ranges = <0 0x100>; 72 msi-available-ranges = <0 0x100>;
73 interrupts = < 73 interrupts = <
74 0xe8 0 0 0 74 0xe8 0 0 0
@@ -83,7 +83,7 @@ msi1: msi@41800 {
83 83
84msi2: msi@41a00 { 84msi2: msi@41a00 {
85 compatible = "fsl,mpic-msi"; 85 compatible = "fsl,mpic-msi";
86 reg = <0x41a00 0x200>; 86 reg = <0x41a00 0x200 0x46140 4>;
87 msi-available-ranges = <0 0x100>; 87 msi-available-ranges = <0 0x100>;
88 interrupts = < 88 interrupts = <
89 0xf0 0 0 0 89 0xf0 0 0 0
diff --git a/arch/powerpc/boot/dts/ge_imp3a.dts b/arch/powerpc/boot/dts/ge_imp3a.dts
new file mode 100644
index 000000000000..fefae416a097
--- /dev/null
+++ b/arch/powerpc/boot/dts/ge_imp3a.dts
@@ -0,0 +1,255 @@
1/*
2 * GE IMP3A Device Tree Source
3 *
4 * Copyright 2010-2011 GE Intelligent Platforms Embedded Systems, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Based on: P2020 DS Device Tree Source
12 * Copyright 2009 Freescale Semiconductor Inc.
13 */
14
15/include/ "fsl/p2020si-pre.dtsi"
16
17/ {
18 model = "GE_IMP3A";
19 compatible = "ge,imp3a";
20
21 memory {
22 device_type = "memory";
23 };
24
25 lbc: localbus@fef05000 {
26 reg = <0 0xfef05000 0 0x1000>;
27
28 ranges = <0x0 0x0 0x0 0xff000000 0x01000000
29 0x1 0x0 0x0 0xe0000000 0x08000000
30 0x2 0x0 0x0 0xe8000000 0x08000000
31 0x3 0x0 0x0 0xfc100000 0x00020000
32 0x4 0x0 0x0 0xfc000000 0x00008000
33 0x5 0x0 0x0 0xfc008000 0x00008000
34 0x6 0x0 0x0 0xfee00000 0x00040000
35 0x7 0x0 0x0 0xfee80000 0x00040000>;
36
37 /* nor@0,0 is a mirror of part of the memory in nor@1,0
38 nor@0,0 {
39 #address-cells = <1>;
40 #size-cells = <1>;
41 compatible = "ge,imp3a-firmware-mirror", "cfi-flash";
42 reg = <0x0 0x0 0x1000000>;
43 bank-width = <2>;
44 device-width = <1>;
45
46 partition@0 {
47 label = "firmware";
48 reg = <0x0 0x1000000>;
49 read-only;
50 };
51 };
52 */
53
54 nor@1,0 {
55 #address-cells = <1>;
56 #size-cells = <1>;
57 compatible = "ge,imp3a-paged-flash", "cfi-flash";
58 reg = <0x1 0x0 0x8000000>;
59 bank-width = <2>;
60 device-width = <1>;
61
62 partition@0 {
63 label = "user";
64 reg = <0x0 0x7800000>;
65 };
66
67 partition@7800000 {
68 label = "firmware";
69 reg = <0x7800000 0x800000>;
70 read-only;
71 };
72 };
73
74 nvram@3,0 {
75 device_type = "nvram";
76 compatible = "simtek,stk14ca8";
77 reg = <0x3 0x0 0x20000>;
78 };
79
80 fpga@4,0 {
81 compatible = "ge,imp3a-fpga-regs";
82 reg = <0x4 0x0 0x20>;
83 };
84
85 gef_pic: pic@4,20 {
86 #interrupt-cells = <1>;
87 interrupt-controller;
88 device_type = "interrupt-controller";
89 compatible = "ge,imp3a-fpga-pic", "gef,fpga-pic-1.00";
90 reg = <0x4 0x20 0x20>;
91 interrupts = <6 7 0 0>;
92 };
93
94 gef_gpio: gpio@4,400 {
95 #gpio-cells = <2>;
96 compatible = "ge,imp3a-gpio";
97 reg = <0x4 0x400 0x24>;
98 gpio-controller;
99 };
100
101 wdt@4,800 {
102 compatible = "ge,imp3a-fpga-wdt", "gef,fpga-wdt-1.00",
103 "gef,fpga-wdt";
104 reg = <0x4 0x800 0x8>;
105 interrupts = <10 4>;
106 interrupt-parent = <&gef_pic>;
107 };
108
109 /* Second watchdog available, driver currently supports one.
110 wdt@4,808 {
111 compatible = "gef,imp3a-fpga-wdt", "gef,fpga-wdt-1.00",
112 "gef,fpga-wdt";
113 reg = <0x4 0x808 0x8>;
114 interrupts = <9 4>;
115 interrupt-parent = <&gef_pic>;
116 };
117 */
118
119 nand@6,0 {
120 compatible = "fsl,elbc-fcm-nand";
121 reg = <0x6 0x0 0x40000>;
122 };
123
124 nand@7,0 {
125 compatible = "fsl,elbc-fcm-nand";
126 reg = <0x7 0x0 0x40000>;
127 };
128 };
129
130 soc: soc@fef00000 {
131 ranges = <0x0 0 0xfef00000 0x100000>;
132
133 i2c@3000 {
134 hwmon@48 {
135 compatible = "national,lm92";
136 reg = <0x48>;
137 };
138
139 hwmon@4c {
140 compatible = "adi,adt7461";
141 reg = <0x4c>;
142 };
143
144 rtc@51 {
145 compatible = "epson,rx8581";
146 reg = <0x51>;
147 };
148
149 eti@6b {
150 compatible = "dallas,ds1682";
151 reg = <0x6b>;
152 };
153 };
154
155 usb@22000 {
156 phy_type = "ulpi";
157 dr_mode = "host";
158 };
159
160 mdio@24520 {
161 phy0: ethernet-phy@0 {
162 interrupt-parent = <&gef_pic>;
163 interrupts = <0xc 0x4>;
164 reg = <0x1>;
165 };
166 phy1: ethernet-phy@1 {
167 interrupt-parent = <&gef_pic>;
168 interrupts = <0xb 0x4>;
169 reg = <0x2>;
170 };
171 tbi0: tbi-phy@11 {
172 reg = <0x11>;
173 device_type = "tbi-phy";
174 };
175 };
176
177 mdio@25520 {
178 tbi1: tbi-phy@11 {
179 reg = <0x11>;
180 device_type = "tbi-phy";
181 };
182 };
183
184 mdio@26520 {
185 status = "disabled";
186 };
187
188 enet0: ethernet@24000 {
189 tbi-handle = <&tbi0>;
190 phy-handle = <&phy0>;
191 phy-connection-type = "gmii";
192 };
193
194 enet1: ethernet@25000 {
195 tbi-handle = <&tbi1>;
196 phy-handle = <&phy1>;
197 phy-connection-type = "gmii";
198 };
199
200 enet2: ethernet@26000 {
201 status = "disabled";
202 };
203 };
204
205 pci0: pcie@fef08000 {
206 ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
207 0x1000000 0x0 0x00000000 0 0xfe020000 0x0 0x10000>;
208 reg = <0 0xfef08000 0 0x1000>;
209
210 pcie@0 {
211 ranges = <0x2000000 0x0 0xc0000000
212 0x2000000 0x0 0xc0000000
213 0x0 0x20000000
214
215 0x1000000 0x0 0x0
216 0x1000000 0x0 0x0
217 0x0 0x10000>;
218 };
219 };
220
221 pci1: pcie@fef09000 {
222 reg = <0 0xfef09000 0 0x1000>;
223 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
224 0x1000000 0x0 0x00000000 0 0xfe010000 0x0 0x10000>;
225
226 pcie@0 {
227 ranges = <0x2000000 0x0 0xa0000000
228 0x2000000 0x0 0xa0000000
229 0x0 0x20000000
230
231 0x1000000 0x0 0x0
232 0x1000000 0x0 0x0
233 0x0 0x10000>;
234 };
235
236 };
237
238 pci2: pcie@fef0a000 {
239 reg = <0 0xfef0a000 0 0x1000>;
240 ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
241 0x1000000 0x0 0x00000000 0 0xfe000000 0x0 0x10000>;
242
243 pcie@0 {
244 ranges = <0x2000000 0x0 0x80000000
245 0x2000000 0x0 0x80000000
246 0x0 0x20000000
247
248 0x1000000 0x0 0x0
249 0x1000000 0x0 0x0
250 0x0 0x10000>;
251 };
252 };
253};
254
255/include/ "fsl/p2020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index c0e450a551bf..81dd513d6308 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -405,6 +405,10 @@
405 reg = <0x1>; 405 reg = <0x1>;
406 device_type = "ethernet-phy"; 406 device_type = "ethernet-phy";
407 }; 407 };
408 tbi-phy@2 {
409 device_type = "tbi-phy";
410 reg = <0x2>;
411 };
408 }; 412 };
409 413
410 qeic: interrupt-controller@80 { 414 qeic: interrupt-controller@80 {
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index c15881574fdc..19736222a0b9 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -1,7 +1,7 @@
1/* 1/*
2 * MPC8536 DS Device Tree Source 2 * MPC8536 DS Device Tree Source
3 * 3 *
4 * Copyright 2008 Freescale Semiconductor, Inc. 4 * Copyright 2008, 2011 Freescale Semiconductor, Inc.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -34,6 +34,10 @@
34 34
35 lbc: localbus@ffe05000 { 35 lbc: localbus@ffe05000 {
36 reg = <0 0xffe05000 0 0x1000>; 36 reg = <0 0xffe05000 0 0x1000>;
37
38 ranges = <0x0 0x0 0x0 0xe8000000 0x08000000
39 0x2 0x0 0x0 0xffa00000 0x00040000
40 0x3 0x0 0x0 0xffdf0000 0x00008000>;
37 }; 41 };
38 42
39 board_soc: soc: soc@ffe00000 { 43 board_soc: soc: soc@ffe00000 {
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dtsi b/arch/powerpc/boot/dts/mpc8536ds.dtsi
index 1462e4cf49d7..cc46dbd9746d 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dtsi
+++ b/arch/powerpc/boot/dts/mpc8536ds.dtsi
@@ -32,6 +32,99 @@
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35&lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x8000000>;
41 bank-width = <2>;
42 device-width = <1>;
43
44 partition@0 {
45 reg = <0x0 0x03000000>;
46 label = "ramdisk-nor";
47 };
48
49 partition@3000000 {
50 reg = <0x03000000 0x00e00000>;
51 label = "diagnostic-nor";
52 read-only;
53 };
54
55 partition@3e00000 {
56 reg = <0x03e00000 0x00200000>;
57 label = "dink-nor";
58 read-only;
59 };
60
61 partition@4000000 {
62 reg = <0x04000000 0x00400000>;
63 label = "kernel-nor";
64 };
65
66 partition@4400000 {
67 reg = <0x04400000 0x03b00000>;
68 label = "fs-nor";
69 };
70
71 partition@7f00000 {
72 reg = <0x07f00000 0x00080000>;
73 label = "dtb-nor";
74 };
75
76 partition@7f80000 {
77 reg = <0x07f80000 0x00080000>;
78 label = "u-boot-nor";
79 read-only;
80 };
81 };
82
83 nand@2,0 {
84 #address-cells = <1>;
85 #size-cells = <1>;
86 compatible = "fsl,mpc8536-fcm-nand",
87 "fsl,elbc-fcm-nand";
88 reg = <0x2 0x0 0x40000>;
89
90 partition@0 {
91 reg = <0x0 0x02000000>;
92 label = "u-boot-nand";
93 read-only;
94 };
95
96 partition@2000000 {
97 reg = <0x02000000 0x10000000>;
98 label = "fs-nand";
99 };
100
101 partition@12000000 {
102 reg = <0x12000000 0x08000000>;
103 label = "ramdisk-nand";
104 };
105
106 partition@1a000000 {
107 reg = <0x1a000000 0x04000000>;
108 label = "kernel-nand";
109 };
110
111 partition@1e000000 {
112 reg = <0x1e000000 0x01000000>;
113 label = "dtb-nand";
114 };
115
116 partition@1f000000 {
117 reg = <0x1f000000 0x21000000>;
118 label = "empty-nand";
119 };
120 };
121
122 board-control@3,0 {
123 compatible = "fsl,mpc8536ds-fpga-pixis";
124 reg = <0x3 0x0 0x8000>;
125 };
126};
127
35&board_soc { 128&board_soc {
36 i2c@3100 { 129 i2c@3100 {
37 rtc@68 { 130 rtc@68 {
diff --git a/arch/powerpc/boot/dts/mpc8536ds_36b.dts b/arch/powerpc/boot/dts/mpc8536ds_36b.dts
index 8f4b929b1d1d..f8a3b3413176 100644
--- a/arch/powerpc/boot/dts/mpc8536ds_36b.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds_36b.dts
@@ -1,7 +1,7 @@
1/* 1/*
2 * MPC8536DS Device Tree Source (36-bit address map) 2 * MPC8536DS Device Tree Source (36-bit address map)
3 * 3 *
4 * Copyright 2008-2009 Freescale Semiconductor, Inc. 4 * Copyright 2008-2009, 2011 Freescale Semiconductor, Inc.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -33,7 +33,11 @@
33 }; 33 };
34 34
35 lbc: localbus@ffe05000 { 35 lbc: localbus@ffe05000 {
36 reg = <0 0xffe05000 0 0x1000>; 36 reg = <0xf 0xffe05000 0 0x1000>;
37
38 ranges = <0x0 0x0 0xf 0xe8000000 0x08000000
39 0x2 0x0 0xf 0xffa00000 0x00040000
40 0x3 0x0 0xf 0xffdf0000 0x00008000>;
37 }; 41 };
38 42
39 board_soc: soc: soc@fffe00000 { 43 board_soc: soc: soc@fffe00000 {
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
deleted file mode 100644
index 07b8dae0f46e..000000000000
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ /dev/null
@@ -1,306 +0,0 @@
1/*
2 * MPC8548 CDS Device Tree Source
3 *
4 * Copyright 2006, 2008 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/include/ "fsl/mpc8548si-pre.dtsi"
13
14/ {
15 model = "MPC8548CDS";
16 compatible = "MPC8548CDS", "MPC85xxCDS";
17
18 aliases {
19 ethernet0 = &enet0;
20 ethernet1 = &enet1;
21 ethernet2 = &enet2;
22 ethernet3 = &enet3;
23 serial0 = &serial0;
24 serial1 = &serial1;
25 pci0 = &pci0;
26 pci1 = &pci1;
27 pci2 = &pci2;
28 };
29
30 memory {
31 device_type = "memory";
32 reg = <0 0 0x0 0x8000000>; // 128M at 0x0
33 };
34
35 lbc: localbus@e0005000 {
36 reg = <0 0xe0005000 0 0x1000>;
37 };
38
39 soc: soc8548@e0000000 {
40 ranges = <0 0x0 0xe0000000 0x100000>;
41
42 i2c@3000 {
43 eeprom@50 {
44 compatible = "atmel,24c64";
45 reg = <0x50>;
46 };
47
48 eeprom@56 {
49 compatible = "atmel,24c64";
50 reg = <0x56>;
51 };
52
53 eeprom@57 {
54 compatible = "atmel,24c64";
55 reg = <0x57>;
56 };
57 };
58
59 i2c@3100 {
60 eeprom@50 {
61 compatible = "atmel,24c64";
62 reg = <0x50>;
63 };
64 };
65
66 enet0: ethernet@24000 {
67 tbi-handle = <&tbi0>;
68 phy-handle = <&phy0>;
69 };
70
71 mdio@24520 {
72 phy0: ethernet-phy@0 {
73 interrupts = <5 1 0 0>;
74 reg = <0x0>;
75 device_type = "ethernet-phy";
76 };
77 phy1: ethernet-phy@1 {
78 interrupts = <5 1 0 0>;
79 reg = <0x1>;
80 device_type = "ethernet-phy";
81 };
82 phy2: ethernet-phy@2 {
83 interrupts = <5 1 0 0>;
84 reg = <0x2>;
85 device_type = "ethernet-phy";
86 };
87 phy3: ethernet-phy@3 {
88 interrupts = <5 1 0 0>;
89 reg = <0x3>;
90 device_type = "ethernet-phy";
91 };
92 tbi0: tbi-phy@11 {
93 reg = <0x11>;
94 device_type = "tbi-phy";
95 };
96 };
97
98 enet1: ethernet@25000 {
99 tbi-handle = <&tbi1>;
100 phy-handle = <&phy1>;
101 };
102
103 mdio@25520 {
104 tbi1: tbi-phy@11 {
105 reg = <0x11>;
106 device_type = "tbi-phy";
107 };
108 };
109
110 enet2: ethernet@26000 {
111 tbi-handle = <&tbi2>;
112 phy-handle = <&phy2>;
113 };
114
115 mdio@26520 {
116 tbi2: tbi-phy@11 {
117 reg = <0x11>;
118 device_type = "tbi-phy";
119 };
120 };
121
122 enet3: ethernet@27000 {
123 tbi-handle = <&tbi3>;
124 phy-handle = <&phy3>;
125 };
126
127 mdio@27520 {
128 tbi3: tbi-phy@11 {
129 reg = <0x11>;
130 device_type = "tbi-phy";
131 };
132 };
133 };
134
135 pci0: pci@e0008000 {
136 reg = <0 0xe0008000 0 0x1000>;
137 ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x10000000
138 0x1000000 0x0 0x00000000 0 0xe2000000 0x0 0x800000>;
139 clock-frequency = <66666666>;
140 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
141 interrupt-map = <
142 /* IDSEL 0x4 (PCIX Slot 2) */
143 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
144 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
145 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
146 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
147
148 /* IDSEL 0x5 (PCIX Slot 3) */
149 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
150 0x2800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
151 0x2800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
152 0x2800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
153
154 /* IDSEL 0x6 (PCIX Slot 4) */
155 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
156 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
157 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
158 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
159
160 /* IDSEL 0x8 (PCIX Slot 5) */
161 0x4000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
162 0x4000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
163 0x4000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
164 0x4000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
165
166 /* IDSEL 0xC (Tsi310 bridge) */
167 0x6000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
168 0x6000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
169 0x6000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
170 0x6000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
171
172 /* IDSEL 0x14 (Slot 2) */
173 0xa000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
174 0xa000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
175 0xa000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
176 0xa000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
177
178 /* IDSEL 0x15 (Slot 3) */
179 0xa800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
180 0xa800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
181 0xa800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
182 0xa800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
183
184 /* IDSEL 0x16 (Slot 4) */
185 0xb000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
186 0xb000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
187 0xb000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
188 0xb000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
189
190 /* IDSEL 0x18 (Slot 5) */
191 0xc000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
192 0xc000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
193 0xc000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
194 0xc000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
195
196 /* IDSEL 0x1C (Tsi310 bridge PCI primary) */
197 0xe000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
198 0xe000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
199 0xe000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
200 0xe000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
201
202 pci_bridge@1c {
203 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
204 interrupt-map = <
205
206 /* IDSEL 0x00 (PrPMC Site) */
207 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
208 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
209 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
210 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
211
212 /* IDSEL 0x04 (VIA chip) */
213 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
214 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
215 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
216 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
217
218 /* IDSEL 0x05 (8139) */
219 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
220
221 /* IDSEL 0x06 (Slot 6) */
222 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
223 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
224 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
225 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
226
227 /* IDESL 0x07 (Slot 7) */
228 0x3800 0x0 0x0 0x1 &mpic 0x3 0x1 0 0
229 0x3800 0x0 0x0 0x2 &mpic 0x0 0x1 0 0
230 0x3800 0x0 0x0 0x3 &mpic 0x1 0x1 0 0
231 0x3800 0x0 0x0 0x4 &mpic 0x2 0x1 0 0>;
232
233 reg = <0xe000 0x0 0x0 0x0 0x0>;
234 #interrupt-cells = <1>;
235 #size-cells = <2>;
236 #address-cells = <3>;
237 ranges = <0x2000000 0x0 0x80000000
238 0x2000000 0x0 0x80000000
239 0x0 0x20000000
240 0x1000000 0x0 0x0
241 0x1000000 0x0 0x0
242 0x0 0x80000>;
243 clock-frequency = <33333333>;
244
245 isa@4 {
246 device_type = "isa";
247 #interrupt-cells = <2>;
248 #size-cells = <1>;
249 #address-cells = <2>;
250 reg = <0x2000 0x0 0x0 0x0 0x0>;
251 ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
252 interrupt-parent = <&i8259>;
253
254 i8259: interrupt-controller@20 {
255 interrupt-controller;
256 device_type = "interrupt-controller";
257 reg = <0x1 0x20 0x2
258 0x1 0xa0 0x2
259 0x1 0x4d0 0x2>;
260 #address-cells = <0>;
261 #interrupt-cells = <2>;
262 compatible = "chrp,iic";
263 interrupts = <0 1 0 0>;
264 interrupt-parent = <&mpic>;
265 };
266
267 rtc@70 {
268 compatible = "pnpPNP,b00";
269 reg = <0x1 0x70 0x2>;
270 };
271 };
272 };
273 };
274
275 pci1: pci@e0009000 {
276 reg = <0 0xe0009000 0 0x1000>;
277 ranges = <0x2000000 0x0 0x90000000 0 0x90000000 0x0 0x10000000
278 0x1000000 0x0 0x00000000 0 0xe2800000 0x0 0x800000>;
279 clock-frequency = <66666666>;
280 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
281 interrupt-map = <
282
283 /* IDSEL 0x15 */
284 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0
285 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
286 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
287 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
288 };
289
290 pci2: pcie@e000a000 {
291 reg = <0 0xe000a000 0 0x1000>;
292 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
293 0x1000000 0x0 0x00000000 0 0xe3000000 0x0 0x100000>;
294 pcie@0 {
295 ranges = <0x2000000 0x0 0xa0000000
296 0x2000000 0x0 0xa0000000
297 0x0 0x20000000
298
299 0x1000000 0x0 0x0
300 0x1000000 0x0 0x0
301 0x0 0x100000>;
302 };
303 };
304};
305
306/include/ "fsl/mpc8548si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dtsi b/arch/powerpc/boot/dts/mpc8548cds.dtsi
new file mode 100644
index 000000000000..c61f525e4740
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8548cds.dtsi
@@ -0,0 +1,306 @@
1/*
2 * MPC8548CDS Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&board_lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x01000000>;
41 bank-width = <2>;
42 device-width = <2>;
43
44 partition@0 {
45 reg = <0x0 0x0b00000>;
46 label = "ramdisk-nor";
47 };
48
49 partition@300000 {
50 reg = <0x0b00000 0x0400000>;
51 label = "kernel-nor";
52 };
53
54 partition@700000 {
55 reg = <0x0f00000 0x060000>;
56 label = "dtb-nor";
57 };
58
59 partition@760000 {
60 reg = <0x0f60000 0x020000>;
61 label = "env-nor";
62 read-only;
63 };
64
65 partition@780000 {
66 reg = <0x0f80000 0x080000>;
67 label = "u-boot-nor";
68 read-only;
69 };
70 };
71
72 board-control@1,0 {
73 compatible = "fsl,mpc8548cds-fpga";
74 reg = <0x1 0x0 0x1000>;
75 };
76};
77
78&board_soc {
79 i2c@3000 {
80 eeprom@50 {
81 compatible = "atmel,24c64";
82 reg = <0x50>;
83 };
84
85 eeprom@56 {
86 compatible = "atmel,24c64";
87 reg = <0x56>;
88 };
89
90 eeprom@57 {
91 compatible = "atmel,24c64";
92 reg = <0x57>;
93 };
94 };
95
96 i2c@3100 {
97 eeprom@50 {
98 compatible = "atmel,24c64";
99 reg = <0x50>;
100 };
101 };
102
103 enet0: ethernet@24000 {
104 tbi-handle = <&tbi0>;
105 phy-handle = <&phy0>;
106 };
107
108 mdio@24520 {
109 phy0: ethernet-phy@0 {
110 interrupts = <5 1 0 0>;
111 reg = <0x0>;
112 device_type = "ethernet-phy";
113 };
114 phy1: ethernet-phy@1 {
115 interrupts = <5 1 0 0>;
116 reg = <0x1>;
117 device_type = "ethernet-phy";
118 };
119 phy2: ethernet-phy@2 {
120 interrupts = <5 1 0 0>;
121 reg = <0x2>;
122 device_type = "ethernet-phy";
123 };
124 phy3: ethernet-phy@3 {
125 interrupts = <5 1 0 0>;
126 reg = <0x3>;
127 device_type = "ethernet-phy";
128 };
129 tbi0: tbi-phy@11 {
130 reg = <0x11>;
131 device_type = "tbi-phy";
132 };
133 };
134
135 enet1: ethernet@25000 {
136 tbi-handle = <&tbi1>;
137 phy-handle = <&phy1>;
138 };
139
140 mdio@25520 {
141 tbi1: tbi-phy@11 {
142 reg = <0x11>;
143 device_type = "tbi-phy";
144 };
145 };
146
147 enet2: ethernet@26000 {
148 tbi-handle = <&tbi2>;
149 phy-handle = <&phy2>;
150 };
151
152 mdio@26520 {
153 tbi2: tbi-phy@11 {
154 reg = <0x11>;
155 device_type = "tbi-phy";
156 };
157 };
158
159 enet3: ethernet@27000 {
160 tbi-handle = <&tbi3>;
161 phy-handle = <&phy3>;
162 };
163
164 mdio@27520 {
165 tbi3: tbi-phy@11 {
166 reg = <0x11>;
167 device_type = "tbi-phy";
168 };
169 };
170};
171
172&board_pci0 {
173 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
174 interrupt-map = <
175 /* IDSEL 0x4 (PCIX Slot 2) */
176 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
177 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
178 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
179 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
180
181 /* IDSEL 0x5 (PCIX Slot 3) */
182 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
183 0x2800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
184 0x2800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
185 0x2800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
186
187 /* IDSEL 0x6 (PCIX Slot 4) */
188 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
189 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
190 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
191 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
192
193 /* IDSEL 0x8 (PCIX Slot 5) */
194 0x4000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
195 0x4000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
196 0x4000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
197 0x4000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
198
199 /* IDSEL 0xC (Tsi310 bridge) */
200 0x6000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
201 0x6000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
202 0x6000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
203 0x6000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
204
205 /* IDSEL 0x14 (Slot 2) */
206 0xa000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
207 0xa000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
208 0xa000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
209 0xa000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
210
211 /* IDSEL 0x15 (Slot 3) */
212 0xa800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
213 0xa800 0x0 0x0 0x2 &mpic 0x2 0x1 0 0
214 0xa800 0x0 0x0 0x3 &mpic 0x3 0x1 0 0
215 0xa800 0x0 0x0 0x4 &mpic 0x0 0x1 0 0
216
217 /* IDSEL 0x16 (Slot 4) */
218 0xb000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
219 0xb000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
220 0xb000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
221 0xb000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
222
223 /* IDSEL 0x18 (Slot 5) */
224 0xc000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
225 0xc000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
226 0xc000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
227 0xc000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
228
229 /* IDSEL 0x1C (Tsi310 bridge PCI primary) */
230 0xe000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
231 0xe000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
232 0xe000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
233 0xe000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
234
235 pci_bridge@1c {
236 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
237 interrupt-map = <
238
239 /* IDSEL 0x00 (PrPMC Site) */
240 0000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
241 0000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
242 0000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
243 0000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
244
245 /* IDSEL 0x04 (VIA chip) */
246 0x2000 0x0 0x0 0x1 &mpic 0x0 0x1 0 0
247 0x2000 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
248 0x2000 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
249 0x2000 0x0 0x0 0x4 &mpic 0x3 0x1 0 0
250
251 /* IDSEL 0x05 (8139) */
252 0x2800 0x0 0x0 0x1 &mpic 0x1 0x1 0 0
253
254 /* IDSEL 0x06 (Slot 6) */
255 0x3000 0x0 0x0 0x1 &mpic 0x2 0x1 0 0
256 0x3000 0x0 0x0 0x2 &mpic 0x3 0x1 0 0
257 0x3000 0x0 0x0 0x3 &mpic 0x0 0x1 0 0
258 0x3000 0x0 0x0 0x4 &mpic 0x1 0x1 0 0
259
260 /* IDESL 0x07 (Slot 7) */
261 0x3800 0x0 0x0 0x1 &mpic 0x3 0x1 0 0
262 0x3800 0x0 0x0 0x2 &mpic 0x0 0x1 0 0
263 0x3800 0x0 0x0 0x3 &mpic 0x1 0x1 0 0
264 0x3800 0x0 0x0 0x4 &mpic 0x2 0x1 0 0>;
265
266 reg = <0xe000 0x0 0x0 0x0 0x0>;
267 #interrupt-cells = <1>;
268 #size-cells = <2>;
269 #address-cells = <3>;
270 ranges = <0x2000000 0x0 0x80000000
271 0x2000000 0x0 0x80000000
272 0x0 0x20000000
273 0x1000000 0x0 0x0
274 0x1000000 0x0 0x0
275 0x0 0x80000>;
276 clock-frequency = <33333333>;
277
278 isa@4 {
279 device_type = "isa";
280 #interrupt-cells = <2>;
281 #size-cells = <1>;
282 #address-cells = <2>;
283 reg = <0x2000 0x0 0x0 0x0 0x0>;
284 ranges = <0x1 0x0 0x1000000 0x0 0x0 0x1000>;
285 interrupt-parent = <&i8259>;
286
287 i8259: interrupt-controller@20 {
288 interrupt-controller;
289 device_type = "interrupt-controller";
290 reg = <0x1 0x20 0x2
291 0x1 0xa0 0x2
292 0x1 0x4d0 0x2>;
293 #address-cells = <0>;
294 #interrupt-cells = <2>;
295 compatible = "chrp,iic";
296 interrupts = <0 1 0 0>;
297 interrupt-parent = <&mpic>;
298 };
299
300 rtc@70 {
301 compatible = "pnpPNP,b00";
302 reg = <0x1 0x70 0x2>;
303 };
304 };
305 };
306};
diff --git a/arch/powerpc/boot/dts/mpc8548cds_32b.dts b/arch/powerpc/boot/dts/mpc8548cds_32b.dts
new file mode 100644
index 000000000000..6fd63163fc6b
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8548cds_32b.dts
@@ -0,0 +1,86 @@
1/*
2 * MPC8548 CDS Device Tree Source (32-bit address map)
3 *
4 * Copyright 2006, 2008, 2011-2012 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/include/ "fsl/mpc8548si-pre.dtsi"
13
14/ {
15 model = "MPC8548CDS";
16 compatible = "MPC8548CDS", "MPC85xxCDS";
17
18 memory {
19 device_type = "memory";
20 reg = <0 0 0x0 0x8000000>; // 128M at 0x0
21 };
22
23 board_lbc: lbc: localbus@e0005000 {
24 reg = <0 0xe0005000 0 0x1000>;
25
26 ranges = <0x0 0x0 0x0 0xff000000 0x01000000
27 0x1 0x0 0x0 0xf8004000 0x00001000>;
28
29 };
30
31 board_soc: soc: soc8548@e0000000 {
32 ranges = <0 0x0 0xe0000000 0x100000>;
33 };
34
35 board_pci0: pci0: pci@e0008000 {
36 reg = <0 0xe0008000 0 0x1000>;
37 ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x10000000
38 0x1000000 0x0 0x00000000 0 0xe2000000 0x0 0x800000>;
39 clock-frequency = <66666666>;
40 };
41
42 pci1: pci@e0009000 {
43 reg = <0 0xe0009000 0 0x1000>;
44 ranges = <0x2000000 0x0 0x90000000 0 0x90000000 0x0 0x10000000
45 0x1000000 0x0 0x00000000 0 0xe2800000 0x0 0x800000>;
46 clock-frequency = <66666666>;
47 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
48 interrupt-map = <
49
50 /* IDSEL 0x15 */
51 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0
52 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
53 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
54 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
55 };
56
57 pci2: pcie@e000a000 {
58 reg = <0 0xe000a000 0 0x1000>;
59 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
60 0x1000000 0x0 0x00000000 0 0xe3000000 0x0 0x100000>;
61 pcie@0 {
62 ranges = <0x2000000 0x0 0xa0000000
63 0x2000000 0x0 0xa0000000
64 0x0 0x20000000
65
66 0x1000000 0x0 0x0
67 0x1000000 0x0 0x0
68 0x0 0x100000>;
69 };
70 };
71
72 rio: rapidio@e00c0000 {
73 reg = <0x0 0xe00c0000 0x0 0x20000>;
74 port1 {
75 ranges = <0x0 0x0 0x0 0xc0000000 0x0 0x20000000>;
76 };
77 };
78};
79
80/*
81 * mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings
82 * for interrupt-map & interrupt-map-mask.
83 */
84
85/include/ "fsl/mpc8548si-post.dtsi"
86/include/ "mpc8548cds.dtsi"
diff --git a/arch/powerpc/boot/dts/mpc8548cds_36b.dts b/arch/powerpc/boot/dts/mpc8548cds_36b.dts
new file mode 100644
index 000000000000..10e551b11bd6
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8548cds_36b.dts
@@ -0,0 +1,86 @@
1/*
2 * MPC8548 CDS Device Tree Source (36-bit address map)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12/include/ "fsl/mpc8548si-pre.dtsi"
13
14/ {
15 model = "MPC8548CDS";
16 compatible = "MPC8548CDS", "MPC85xxCDS";
17
18 memory {
19 device_type = "memory";
20 reg = <0 0 0x0 0x8000000>; // 128M at 0x0
21 };
22
23 board_lbc: lbc: localbus@fe0005000 {
24 reg = <0xf 0xe0005000 0 0x1000>;
25
26 ranges = <0x0 0x0 0xf 0xff000000 0x01000000
27 0x1 0x0 0xf 0xf8004000 0x00001000>;
28
29 };
30
31 board_soc: soc: soc8548@fe0000000 {
32 ranges = <0 0xf 0xe0000000 0x100000>;
33 };
34
35 board_pci0: pci0: pci@fe0008000 {
36 reg = <0xf 0xe0008000 0 0x1000>;
37 ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x10000000
38 0x1000000 0x0 0x00000000 0xf 0xe2000000 0x0 0x800000>;
39 clock-frequency = <66666666>;
40 };
41
42 pci1: pci@fe0009000 {
43 reg = <0xf 0xe0009000 0 0x1000>;
44 ranges = <0x2000000 0x0 0xe0000000 0xc 0x10000000 0x0 0x10000000
45 0x1000000 0x0 0x00000000 0xf 0xe2800000 0x0 0x800000>;
46 clock-frequency = <66666666>;
47 interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
48 interrupt-map = <
49
50 /* IDSEL 0x15 */
51 0xa800 0x0 0x0 0x1 &mpic 0xb 0x1 0 0
52 0xa800 0x0 0x0 0x2 &mpic 0x1 0x1 0 0
53 0xa800 0x0 0x0 0x3 &mpic 0x2 0x1 0 0
54 0xa800 0x0 0x0 0x4 &mpic 0x3 0x1 0 0>;
55 };
56
57 pci2: pcie@fe000a000 {
58 reg = <0xf 0xe000a000 0 0x1000>;
59 ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
60 0x1000000 0x0 0x00000000 0xf 0xe3000000 0x0 0x100000>;
61 pcie@0 {
62 ranges = <0x2000000 0x0 0xa0000000
63 0x2000000 0x0 0xa0000000
64 0x0 0x20000000
65
66 0x1000000 0x0 0x0
67 0x1000000 0x0 0x0
68 0x0 0x100000>;
69 };
70 };
71
72 rio: rapidio@fe00c0000 {
73 reg = <0xf 0xe00c0000 0x0 0x20000>;
74 port1 {
75 ranges = <0x0 0x0 0xc 0x40000000 0x0 0x20000000>;
76 };
77 };
78};
79
80/*
81 * mpc8548cds.dtsi must be last to ensure board_pci0 overrides pci0 settings
82 * for interrupt-map & interrupt-map-mask.
83 */
84
85/include/ "fsl/mpc8548si-post.dtsi"
86/include/ "mpc8548cds.dtsi"
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dtsi b/arch/powerpc/boot/dts/mpc8572ds.dtsi
index c3d4fac0532a..14178944e220 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dtsi
+++ b/arch/powerpc/boot/dts/mpc8572ds.dtsi
@@ -41,37 +41,47 @@
41 bank-width = <2>; 41 bank-width = <2>;
42 device-width = <1>; 42 device-width = <1>;
43 43
44 ramdisk@0 { 44 partition@0 {
45 reg = <0x0 0x03000000>; 45 reg = <0x0 0x03000000>;
46 read-only; 46 label = "ramdisk-nor";
47 }; 47 };
48 48
49 diagnostic@3000000 { 49 partition@3000000 {
50 reg = <0x03000000 0x00e00000>; 50 reg = <0x03000000 0x00e00000>;
51 label = "diagnostic-nor";
51 read-only; 52 read-only;
52 }; 53 };
53 54
54 dink@3e00000 { 55 partition@3e00000 {
55 reg = <0x03e00000 0x00200000>; 56 reg = <0x03e00000 0x00200000>;
57 label = "dink-nor";
56 read-only; 58 read-only;
57 }; 59 };
58 60
59 kernel@4000000 { 61 partition@4000000 {
60 reg = <0x04000000 0x00400000>; 62 reg = <0x04000000 0x00400000>;
61 read-only; 63 label = "kernel-nor";
62 }; 64 };
63 65
64 jffs2@4400000 { 66 partition@4400000 {
65 reg = <0x04400000 0x03b00000>; 67 reg = <0x04400000 0x03b00000>;
68 label = "fs-nor";
69 };
70
71 partition@7f00000 {
72 reg = <0x07f00000 0x00060000>;
73 label = "dtb-nor";
66 }; 74 };
67 75
68 dtb@7f00000 { 76 partition@7f60000 {
69 reg = <0x07f00000 0x00080000>; 77 reg = <0x07f60000 0x00020000>;
78 label = "env-nor";
70 read-only; 79 read-only;
71 }; 80 };
72 81
73 u-boot@7f80000 { 82 partition@7f80000 {
74 reg = <0x07f80000 0x00080000>; 83 reg = <0x07f80000 0x00080000>;
84 label = "u-boot-nor";
75 read-only; 85 read-only;
76 }; 86 };
77 }; 87 };
@@ -83,31 +93,35 @@
83 "fsl,elbc-fcm-nand"; 93 "fsl,elbc-fcm-nand";
84 reg = <0x2 0x0 0x40000>; 94 reg = <0x2 0x0 0x40000>;
85 95
86 u-boot@0 { 96 partition@0 {
87 reg = <0x0 0x02000000>; 97 reg = <0x0 0x02000000>;
98 label = "u-boot-nand";
88 read-only; 99 read-only;
89 }; 100 };
90 101
91 jffs2@2000000 { 102 partition@2000000 {
92 reg = <0x02000000 0x10000000>; 103 reg = <0x02000000 0x10000000>;
104 label = "fs-nand";
93 }; 105 };
94 106
95 ramdisk@12000000 { 107 partition@12000000 {
96 reg = <0x12000000 0x08000000>; 108 reg = <0x12000000 0x08000000>;
97 read-only; 109 label = "ramdisk-nand";
98 }; 110 };
99 111
100 kernel@1a000000 { 112 partition@1a000000 {
101 reg = <0x1a000000 0x04000000>; 113 reg = <0x1a000000 0x04000000>;
114 label = "kernel-nand";
102 }; 115 };
103 116
104 dtb@1e000000 { 117 partition@1e000000 {
105 reg = <0x1e000000 0x01000000>; 118 reg = <0x1e000000 0x01000000>;
106 read-only; 119 label = "dtb-nand";
107 }; 120 };
108 121
109 empty@1f000000 { 122 partition@1f000000 {
110 reg = <0x1f000000 0x21000000>; 123 reg = <0x1f000000 0x21000000>;
124 label = "empty-nand";
111 }; 125 };
112 }; 126 };
113 127
diff --git a/arch/powerpc/boot/dts/p1010rdb.dtsi b/arch/powerpc/boot/dts/p1010rdb.dtsi
index d4c4a7730285..49776143a1b8 100644
--- a/arch/powerpc/boot/dts/p1010rdb.dtsi
+++ b/arch/powerpc/boot/dts/p1010rdb.dtsi
@@ -138,7 +138,7 @@
138 #size-cells = <1>; 138 #size-cells = <1>;
139 compatible = "spansion,s25sl12801"; 139 compatible = "spansion,s25sl12801";
140 reg = <0>; 140 reg = <0>;
141 spi-max-frequency = <50000000>; 141 spi-max-frequency = <40000000>;
142 142
143 partition@0 { 143 partition@0 {
144 /* 1MB for u-boot Bootloader Image */ 144 /* 1MB for u-boot Bootloader Image */
@@ -196,7 +196,7 @@
196 }; 196 };
197 197
198 tbi-phy@3 { 198 tbi-phy@3 {
199 device-type = "tbi-phy"; 199 device_type = "tbi-phy";
200 reg = <0x3>; 200 reg = <0x3>;
201 }; 201 };
202 }; 202 };
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc.dtsi b/arch/powerpc/boot/dts/p1020rdb-pc.dtsi
new file mode 100644
index 000000000000..c952cd37cf6d
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc.dtsi
@@ -0,0 +1,247 @@
1/*
2 * P1020 RDB-PC Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x1000000>;
41 bank-width = <2>;
42 device-width = <1>;
43
44 partition@0 {
45 /* This location must not be altered */
46 /* 256KB for Vitesse 7385 Switch firmware */
47 reg = <0x0 0x00040000>;
48 label = "NOR Vitesse-7385 Firmware";
49 read-only;
50 };
51
52 partition@40000 {
53 /* 256KB for DTB Image */
54 reg = <0x00040000 0x00040000>;
55 label = "NOR DTB Image";
56 };
57
58 partition@80000 {
59 /* 3.5 MB for Linux Kernel Image */
60 reg = <0x00080000 0x00380000>;
61 label = "NOR Linux Kernel Image";
62 };
63
64 partition@400000 {
65 /* 11MB for JFFS2 based Root file System */
66 reg = <0x00400000 0x00b00000>;
67 label = "NOR JFFS2 Root File System";
68 };
69
70 partition@f00000 {
71 /* This location must not be altered */
72 /* 512KB for u-boot Bootloader Image */
73 /* 512KB for u-boot Environment Variables */
74 reg = <0x00f00000 0x00100000>;
75 label = "NOR U-Boot Image";
76 read-only;
77 };
78 };
79
80 nand@1,0 {
81 #address-cells = <1>;
82 #size-cells = <1>;
83 compatible = "fsl,p1020-fcm-nand",
84 "fsl,elbc-fcm-nand";
85 reg = <0x1 0x0 0x40000>;
86
87 partition@0 {
88 /* This location must not be altered */
89 /* 1MB for u-boot Bootloader Image */
90 reg = <0x0 0x00100000>;
91 label = "NAND U-Boot Image";
92 read-only;
93 };
94
95 partition@100000 {
96 /* 1MB for DTB Image */
97 reg = <0x00100000 0x00100000>;
98 label = "NAND DTB Image";
99 };
100
101 partition@200000 {
102 /* 4MB for Linux Kernel Image */
103 reg = <0x00200000 0x00400000>;
104 label = "NAND Linux Kernel Image";
105 };
106
107 partition@600000 {
108 /* 4MB for Compressed Root file System Image */
109 reg = <0x00600000 0x00400000>;
110 label = "NAND Compressed RFS Image";
111 };
112
113 partition@a00000 {
114 /* 7MB for JFFS2 based Root file System */
115 reg = <0x00a00000 0x00700000>;
116 label = "NAND JFFS2 Root File System";
117 };
118
119 partition@1100000 {
120 /* 15MB for JFFS2 based Root file System */
121 reg = <0x01100000 0x00f00000>;
122 label = "NAND Writable User area";
123 };
124 };
125
126 L2switch@2,0 {
127 #address-cells = <1>;
128 #size-cells = <1>;
129 compatible = "vitesse-7385";
130 reg = <0x2 0x0 0x20000>;
131 };
132
133 cpld@3,0 {
134 #address-cells = <1>;
135 #size-cells = <1>;
136 compatible = "cpld";
137 reg = <0x3 0x0 0x20000>;
138 read-only;
139 };
140};
141
142&soc {
143 i2c@3000 {
144 rtc@68 {
145 compatible = "pericom,pt7c4338";
146 reg = <0x68>;
147 };
148 };
149
150 spi@7000 {
151 flash@0 {
152 #address-cells = <1>;
153 #size-cells = <1>;
154 compatible = "spansion,s25sl12801";
155 reg = <0>;
156 spi-max-frequency = <40000000>; /* input clock */
157
158 partition@u-boot {
159 /* 512KB for u-boot Bootloader Image */
160 reg = <0x0 0x00080000>;
161 label = "u-boot";
162 read-only;
163 };
164
165 partition@dtb {
166 /* 512KB for DTB Image*/
167 reg = <0x00080000 0x00080000>;
168 label = "dtb";
169 };
170
171 partition@kernel {
172 /* 4MB for Linux Kernel Image */
173 reg = <0x00100000 0x00400000>;
174 label = "kernel";
175 };
176
177 partition@fs {
178 /* 4MB for Compressed RFS Image */
179 reg = <0x00500000 0x00400000>;
180 label = "file system";
181 };
182
183 partition@jffs-fs {
184 /* 7MB for JFFS2 based RFS */
185 reg = <0x00900000 0x00700000>;
186 label = "file system jffs2";
187 };
188 };
189 };
190
191 usb@22000 {
192 phy_type = "ulpi";
193 };
194
195 /* USB2 is shared with localbus, so it must be disabled
196 by default. We can't put 'status = "disabled";' here
197 since U-Boot doesn't clear the status property when
198 it enables USB2. OTOH, U-Boot does create a new node
199 when there isn't any. So, just comment it out.
200 usb@23000 {
201 phy_type = "ulpi";
202 };
203 */
204
205 mdio@24000 {
206 phy0: ethernet-phy@0 {
207 interrupt-parent = <&mpic>;
208 interrupts = <3 1>;
209 reg = <0x0>;
210 };
211
212 phy1: ethernet-phy@1 {
213 interrupt-parent = <&mpic>;
214 interrupts = <2 1>;
215 reg = <0x1>;
216 };
217
218 tbi0: tbi-phy@11 {
219 device_type = "tbi-phy";
220 reg = <0x11>;
221 };
222 };
223
224 mdio@25000 {
225 tbi1: tbi-phy@11 {
226 reg = <0x11>;
227 device_type = "tbi-phy";
228 };
229 };
230
231 enet0: ethernet@b0000 {
232 fixed-link = <1 1 1000 0 0>;
233 phy-connection-type = "rgmii-id";
234
235 };
236
237 enet1: ethernet@b1000 {
238 phy-handle = <&phy0>;
239 tbi-handle = <&tbi1>;
240 phy-connection-type = "sgmii";
241 };
242
243 enet2: ethernet@b2000 {
244 phy-handle = <&phy1>;
245 phy-connection-type = "rgmii-id";
246 };
247};
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_32b.dts b/arch/powerpc/boot/dts/p1020rdb-pc_32b.dts
new file mode 100644
index 000000000000..4de69b726dc5
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_32b.dts
@@ -0,0 +1,90 @@
1/*
2 * P1020 RDB-PC Device Tree Source (32-bit address map)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1020si-pre.dtsi"
36/ {
37 model = "fsl,P1020RDB-PC";
38 compatible = "fsl,P1020RDB-PC";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@ffe05000 {
45 reg = <0 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
48 ranges = <0x0 0x0 0x0 0xef000000 0x01000000
49 0x1 0x0 0x0 0xff800000 0x00040000
50 0x2 0x0 0x0 0xffb00000 0x00020000
51 0x3 0x0 0x0 0xffa00000 0x00020000>;
52 };
53
54 soc: soc@ffe00000 {
55 ranges = <0x0 0x0 0xffe00000 0x100000>;
56 };
57
58 pci0: pcie@ffe09000 {
59 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
60 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
61 reg = <0 0xffe09000 0 0x1000>;
62 pcie@0 {
63 ranges = <0x2000000 0x0 0xa0000000
64 0x2000000 0x0 0xa0000000
65 0x0 0x20000000
66
67 0x1000000 0x0 0x0
68 0x1000000 0x0 0x0
69 0x0 0x100000>;
70 };
71 };
72
73 pci1: pcie@ffe0a000 {
74 reg = <0 0xffe0a000 0 0x1000>;
75 ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
76 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
77 pcie@0 {
78 ranges = <0x2000000 0x0 0x80000000
79 0x2000000 0x0 0x80000000
80 0x0 0x20000000
81
82 0x1000000 0x0 0x0
83 0x1000000 0x0 0x0
84 0x0 0x100000>;
85 };
86 };
87};
88
89/include/ "p1020rdb-pc.dtsi"
90/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts b/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts
new file mode 100644
index 000000000000..5237da7441bc
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_36b.dts
@@ -0,0 +1,90 @@
1/*
2 * P1020 RDB-PC Device Tree Source (36-bit address map)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1020si-pre.dtsi"
36/ {
37 model = "fsl,P1020RDB-PC";
38 compatible = "fsl,P1020RDB-PC";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@fffe05000 {
45 reg = <0xf 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
48 ranges = <0x0 0x0 0xf 0xef000000 0x01000000
49 0x1 0x0 0xf 0xff800000 0x00040000
50 0x2 0x0 0xf 0xffb00000 0x00040000
51 0x3 0x0 0xf 0xffa00000 0x00020000>;
52 };
53
54 soc: soc@fffe00000 {
55 ranges = <0x0 0xf 0xffe00000 0x100000>;
56 };
57
58 pci0: pcie@fffe09000 {
59 reg = <0xf 0xffe09000 0 0x1000>;
60 ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
61 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
62 pcie@0 {
63 ranges = <0x2000000 0x0 0xc0000000
64 0x2000000 0x0 0xc0000000
65 0x0 0x20000000
66
67 0x1000000 0x0 0x0
68 0x1000000 0x0 0x0
69 0x0 0x100000>;
70 };
71 };
72
73 pci1: pcie@fffe0a000 {
74 reg = <0xf 0xffe0a000 0 0x1000>;
75 ranges = <0x2000000 0x0 0x80000000 0xc 0x00000000 0x0 0x20000000
76 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
77 pcie@0 {
78 ranges = <0x2000000 0x0 0x80000000
79 0x2000000 0x0 0x80000000
80 0x0 0x20000000
81
82 0x1000000 0x0 0x0
83 0x1000000 0x0 0x0
84 0x0 0x100000>;
85 };
86 };
87};
88
89/include/ "p1020rdb-pc.dtsi"
90/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts
new file mode 100644
index 000000000000..f411515937ec
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core0.dts
@@ -0,0 +1,64 @@
1/*
2 * P1020 RDB-PC Core0 Device Tree Source in CAMP mode.
3 *
4 * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
5 * can be shared, all the other devices must be assigned to one core only.
6 * This dts file allows core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb,
7 * eth1, eth2, sdhc, crypto, global-util, message, pci0, pci1, msi.
8 *
9 * Please note to add "-b 0" for core0's dts compiling.
10 *
11 * Copyright 2012 Freescale Semiconductor Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19/include/ "p1020rdb-pc_32b.dts"
20
21/ {
22 model = "fsl,P1020RDB-PC";
23 compatible = "fsl,P1020RDB-PC";
24
25 aliases {
26 ethernet1 = &enet1;
27 ethernet2 = &enet2;
28 serial0 = &serial0;
29 pci0 = &pci0;
30 pci1 = &pci1;
31 };
32
33 cpus {
34 PowerPC,P1020@1 {
35 status = "disabled";
36 };
37 };
38
39 memory {
40 device_type = "memory";
41 };
42
43 localbus@ffe05000 {
44 status = "disabled";
45 };
46
47 soc@ffe00000 {
48 serial1: serial@4600 {
49 status = "disabled";
50 };
51
52 enet0: ethernet@b0000 {
53 status = "disabled";
54 };
55
56 mpic: pic@40000 {
57 protected-sources = <
58 42 29 30 34 /* serial1, enet0-queue-group0 */
59 17 18 24 45 /* enet0-queue-group1, crypto */
60 >;
61 pic-no-reset;
62 };
63 };
64};
diff --git a/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts
new file mode 100644
index 000000000000..a91335ad82c2
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb-pc_camp_core1.dts
@@ -0,0 +1,142 @@
1/*
2 * P1020 RDB-PC Core1 Device Tree Source in CAMP mode.
3 *
4 * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
5 * can be shared, all the other devices must be assigned to one core only.
6 * This dts allows core1 to have l2, eth0, crypto.
7 *
8 * Please note to add "-b 1" for core1's dts compiling.
9 *
10 * Copyright 2012 Freescale Semiconductor Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18/include/ "p1020rdb-pc_32b.dts"
19
20/ {
21 model = "fsl,P1020RDB-PC";
22 compatible = "fsl,P1020RDB-PC";
23
24 aliases {
25 ethernet0 = &enet0;
26 serial0 = &serial1;
27 };
28
29 cpus {
30 PowerPC,P1020@0 {
31 status = "disabled";
32 };
33 };
34
35 memory {
36 device_type = "memory";
37 };
38
39 localbus@ffe05000 {
40 status = "disabled";
41 };
42
43 soc@ffe00000 {
44 ecm-law@0 {
45 status = "disabled";
46 };
47
48 ecm@1000 {
49 status = "disabled";
50 };
51
52 memory-controller@2000 {
53 status = "disabled";
54 };
55
56 i2c@3000 {
57 status = "disabled";
58 };
59
60 i2c@3100 {
61 status = "disabled";
62 };
63
64 serial0: serial@4500 {
65 status = "disabled";
66 };
67
68 spi@7000 {
69 status = "disabled";
70 };
71
72 gpio: gpio-controller@f000 {
73 status = "disabled";
74 };
75
76 dma@21300 {
77 status = "disabled";
78 };
79
80 mdio@24000 {
81 status = "disabled";
82 };
83
84 mdio@25000 {
85 status = "disabled";
86 };
87
88 enet1: ethernet@b1000 {
89 status = "disabled";
90 };
91
92 enet2: ethernet@b2000 {
93 status = "disabled";
94 };
95
96 usb@22000 {
97 status = "disabled";
98 };
99
100 sdhci@2e000 {
101 status = "disabled";
102 };
103
104 mpic: pic@40000 {
105 protected-sources = <
106 16 /* ecm, mem, L2, pci0, pci1 */
107 43 42 59 /* i2c, serial0, spi */
108 47 63 62 /* gpio, tdm */
109 20 21 22 23 /* dma */
110 03 02 /* mdio */
111 35 36 40 /* enet1-queue-group0 */
112 51 52 67 /* enet1-queue-group1 */
113 31 32 33 /* enet2-queue-group0 */
114 25 26 27 /* enet2-queue-group1 */
115 28 72 58 /* usb, sdhci, crypto */
116 0xb0 0xb1 0xb2 /* message */
117 0xb3 0xb4 0xb5
118 0xb6 0xb7
119 0xe0 0xe1 0xe2 /* msi */
120 0xe3 0xe4 0xe5
121 0xe6 0xe7 /* sdhci, crypto , pci */
122 >;
123 pic-no-reset;
124 };
125
126 msi@41600 {
127 status = "disabled";
128 };
129
130 global-utilities@e0000 { //global utilities block
131 status = "disabled";
132 };
133 };
134
135 pci0: pcie@ffe09000 {
136 status = "disabled";
137 };
138
139 pci1: pcie@ffe0a000 {
140 status = "disabled";
141 };
142};
diff --git a/arch/powerpc/boot/dts/p1021rdb.dts b/arch/powerpc/boot/dts/p1021rdb.dts
new file mode 100644
index 000000000000..90b6b4caa273
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1021rdb.dts
@@ -0,0 +1,96 @@
1/*
2 * P1021 RDB Device Tree Source
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1021si-pre.dtsi"
36/ {
37 model = "fsl,P1021RDB";
38 compatible = "fsl,P1021RDB-PC";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@ffe05000 {
45 reg = <0 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
48 ranges = <0x0 0x0 0x0 0xef000000 0x01000000
49 0x1 0x0 0x0 0xff800000 0x00040000
50 0x2 0x0 0x0 0xffb00000 0x00020000>;
51 };
52
53 soc: soc@ffe00000 {
54 ranges = <0x0 0x0 0xffe00000 0x100000>;
55 };
56
57 pci0: pcie@ffe09000 {
58 ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
59 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
60 reg = <0 0xffe09000 0 0x1000>;
61 pcie@0 {
62 ranges = <0x2000000 0x0 0xa0000000
63 0x2000000 0x0 0xa0000000
64 0x0 0x20000000
65
66 0x1000000 0x0 0x0
67 0x1000000 0x0 0x0
68 0x0 0x100000>;
69 };
70 };
71
72 pci1: pcie@ffe0a000 {
73 reg = <0 0xffe0a000 0 0x1000>;
74 ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
75 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
76 pcie@0 {
77 ranges = <0x2000000 0x0 0x80000000
78 0x2000000 0x0 0x80000000
79 0x0 0x20000000
80
81 0x1000000 0x0 0x0
82 0x1000000 0x0 0x0
83 0x0 0x100000>;
84 };
85 };
86
87 qe: qe@ffe80000 {
88 ranges = <0x0 0x0 0xffe80000 0x40000>;
89 reg = <0 0xffe80000 0 0x480>;
90 brg-frequency = <0>;
91 bus-frequency = <0>;
92 };
93};
94
95/include/ "p1021rdb.dtsi"
96/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1021rdb.dtsi b/arch/powerpc/boot/dts/p1021rdb.dtsi
new file mode 100644
index 000000000000..b973461ab751
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1021rdb.dtsi
@@ -0,0 +1,236 @@
1/*
2 * P1021 RDB Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x1000000>;
41 bank-width = <2>;
42 device-width = <1>;
43
44 partition@0 {
45 /* This location must not be altered */
46 /* 256KB for Vitesse 7385 Switch firmware */
47 reg = <0x0 0x00040000>;
48 label = "NOR Vitesse-7385 Firmware";
49 read-only;
50 };
51
52 partition@40000 {
53 /* 256KB for DTB Image */
54 reg = <0x00040000 0x00040000>;
55 label = "NOR DTB Image";
56 };
57
58 partition@80000 {
59 /* 3.5 MB for Linux Kernel Image */
60 reg = <0x00080000 0x00380000>;
61 label = "NOR Linux Kernel Image";
62 };
63
64 partition@400000 {
65 /* 11MB for JFFS2 based Root file System */
66 reg = <0x00400000 0x00b00000>;
67 label = "NOR JFFS2 Root File System";
68 };
69
70 partition@f00000 {
71 /* This location must not be altered */
72 /* 512KB for u-boot Bootloader Image */
73 /* 512KB for u-boot Environment Variables */
74 reg = <0x00f00000 0x00100000>;
75 label = "NOR U-Boot Image";
76 };
77 };
78
79 nand@1,0 {
80 #address-cells = <1>;
81 #size-cells = <1>;
82 compatible = "fsl,p1021-fcm-nand",
83 "fsl,elbc-fcm-nand";
84 reg = <0x1 0x0 0x40000>;
85
86 partition@0 {
87 /* This location must not be altered */
88 /* 1MB for u-boot Bootloader Image */
89 reg = <0x0 0x00100000>;
90 label = "NAND U-Boot Image";
91 read-only;
92 };
93
94 partition@100000 {
95 /* 1MB for DTB Image */
96 reg = <0x00100000 0x00100000>;
97 label = "NAND DTB Image";
98 };
99
100 partition@200000 {
101 /* 4MB for Linux Kernel Image */
102 reg = <0x00200000 0x00400000>;
103 label = "NAND Linux Kernel Image";
104 };
105
106 partition@600000 {
107 /* 4MB for Compressed Root file System Image */
108 reg = <0x00600000 0x00400000>;
109 label = "NAND Compressed RFS Image";
110 };
111
112 partition@a00000 {
113 /* 7MB for JFFS2 based Root file System */
114 reg = <0x00a00000 0x00700000>;
115 label = "NAND JFFS2 Root File System";
116 };
117
118 partition@1100000 {
119 /* 15MB for User Writable Area */
120 reg = <0x01100000 0x00f00000>;
121 label = "NAND Writable User area";
122 };
123 };
124
125 L2switch@2,0 {
126 #address-cells = <1>;
127 #size-cells = <1>;
128 compatible = "vitesse-7385";
129 reg = <0x2 0x0 0x20000>;
130 };
131};
132
133&soc {
134 i2c@3000 {
135 rtc@68 {
136 compatible = "pericom,pt7c4338";
137 reg = <0x68>;
138 };
139 };
140
141 spi@7000 {
142 flash@0 {
143 #address-cells = <1>;
144 #size-cells = <1>;
145 compatible = "spansion,s25sl12801";
146 reg = <0>;
147 spi-max-frequency = <40000000>; /* input clock */
148
149 partition@u-boot {
150 /* 512KB for u-boot Bootloader Image */
151 reg = <0x0 0x00080000>;
152 label = "SPI Flash U-Boot Image";
153 read-only;
154 };
155
156 partition@dtb {
157 /* 512KB for DTB Image */
158 reg = <0x00080000 0x00080000>;
159 label = "SPI Flash DTB Image";
160 };
161
162 partition@kernel {
163 /* 4MB for Linux Kernel Image */
164 reg = <0x00100000 0x00400000>;
165 label = "SPI Flash Linux Kernel Image";
166 };
167
168 partition@fs {
169 /* 4MB for Compressed RFS Image */
170 reg = <0x00500000 0x00400000>;
171 label = "SPI Flash Compressed RFSImage";
172 };
173
174 partition@jffs-fs {
175 /* 7MB for JFFS2 based RFS */
176 reg = <0x00900000 0x00700000>;
177 label = "SPI Flash JFFS2 RFS";
178 };
179 };
180 };
181
182 usb@22000 {
183 phy_type = "ulpi";
184 };
185
186 mdio@24000 {
187 phy0: ethernet-phy@0 {
188 interrupt-parent = <&mpic>;
189 interrupts = <3 1 0 0>;
190 reg = <0x0>;
191 };
192
193 phy1: ethernet-phy@1 {
194 interrupt-parent = <&mpic>;
195 interrupts = <2 1 0 0>;
196 reg = <0x1>;
197 };
198
199 tbi0: tbi-phy@11 {
200 reg = <0x11>;
201 device_type = "tbi-phy";
202 };
203 };
204
205 mdio@25000 {
206 tbi1: tbi-phy@11 {
207 reg = <0x11>;
208 device_type = "tbi-phy";
209 };
210 };
211
212 mdio@26000 {
213 tbi2: tbi-phy@11 {
214 reg = <0x11>;
215 device_type = "tbi-phy";
216 };
217 };
218
219 enet0: ethernet@b0000 {
220 fixed-link = <1 1 1000 0 0>;
221 phy-connection-type = "rgmii-id";
222
223 };
224
225 enet1: ethernet@b1000 {
226 phy-handle = <&phy0>;
227 tbi-handle = <&tbi1>;
228 phy-connection-type = "sgmii";
229 };
230
231 enet2: ethernet@b2000 {
232 phy-handle = <&phy1>;
233 tbi-handle = <&tbi2>;
234 phy-connection-type = "rgmii-id";
235 };
236};
diff --git a/arch/powerpc/boot/dts/p1021rdb_36b.dts b/arch/powerpc/boot/dts/p1021rdb_36b.dts
new file mode 100644
index 000000000000..ea6d8b5fa10b
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1021rdb_36b.dts
@@ -0,0 +1,96 @@
1/*
2 * P1021 RDB Device Tree Source (36-bit address map)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1021si-pre.dtsi"
36/ {
37 model = "fsl,P1021RDB";
38 compatible = "fsl,P1021RDB-PC";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@fffe05000 {
45 reg = <0xf 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
48 ranges = <0x0 0x0 0xf 0xef000000 0x01000000
49 0x1 0x0 0xf 0xff800000 0x00040000
50 0x2 0x0 0xf 0xffb00000 0x00020000>;
51 };
52
53 soc: soc@fffe00000 {
54 ranges = <0x0 0xf 0xffe00000 0x100000>;
55 };
56
57 pci0: pcie@fffe09000 {
58 ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
59 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
60 reg = <0xf 0xffe09000 0 0x1000>;
61 pcie@0 {
62 ranges = <0x2000000 0x0 0xa0000000
63 0x2000000 0x0 0xa0000000
64 0x0 0x20000000
65
66 0x1000000 0x0 0x0
67 0x1000000 0x0 0x0
68 0x0 0x100000>;
69 };
70 };
71
72 pci1: pcie@fffe0a000 {
73 reg = <0xf 0xffe0a000 0 0x1000>;
74 ranges = <0x2000000 0x0 0x80000000 0xc 0x00000000 0x0 0x20000000
75 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
76 pcie@0 {
77 ranges = <0x2000000 0x0 0xc0000000
78 0x2000000 0x0 0xc0000000
79 0x0 0x20000000
80
81 0x1000000 0x0 0x0
82 0x1000000 0x0 0x0
83 0x0 0x100000>;
84 };
85 };
86
87 qe: qe@fffe80000 {
88 ranges = <0x0 0xf 0xffe80000 0x40000>;
89 reg = <0xf 0xffe80000 0 0x480>;
90 brg-frequency = <0>;
91 bus-frequency = <0>;
92 };
93};
94
95/include/ "p1021rdb.dtsi"
96/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
deleted file mode 100644
index ef95717db4bc..000000000000
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ /dev/null
@@ -1,274 +0,0 @@
1/*
2 * P1022 DS 36Bit Physical Address Map Device Tree Source
3 *
4 * Copyright 2010 Freescale Semiconductor, Inc.
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 */
10
11/include/ "fsl/p1022si-pre.dtsi"
12/ {
13 model = "fsl,P1022DS";
14 compatible = "fsl,P1022DS";
15
16 memory {
17 device_type = "memory";
18 };
19
20 lbc: localbus@fffe05000 {
21 reg = <0xf 0xffe05000 0 0x1000>;
22 ranges = <0x0 0x0 0xf 0xe8000000 0x08000000
23 0x1 0x0 0xf 0xe0000000 0x08000000
24 0x2 0x0 0xf 0xff800000 0x00040000
25 0x3 0x0 0xf 0xffdf0000 0x00008000>;
26
27 /*
28 * This node is used to access the pixis via "indirect" mode,
29 * which is done by writing the pixis register index to chip
30 * select 0 and the value to/from chip select 1. Indirect
31 * mode is the only way to access the pixis when DIU video
32 * is enabled. Note that this assumes that the first column
33 * of the 'ranges' property above is the chip select number.
34 */
35 board-control@0,0 {
36 compatible = "fsl,p1022ds-indirect-pixis";
37 reg = <0x0 0x0 1 /* CS0 */
38 0x1 0x0 1>; /* CS1 */
39 };
40
41 nor@0,0 {
42 #address-cells = <1>;
43 #size-cells = <1>;
44 compatible = "cfi-flash";
45 reg = <0x0 0x0 0x8000000>;
46 bank-width = <2>;
47 device-width = <1>;
48
49 partition@0 {
50 reg = <0x0 0x03000000>;
51 label = "ramdisk-nor";
52 read-only;
53 };
54
55 partition@3000000 {
56 reg = <0x03000000 0x00e00000>;
57 label = "diagnostic-nor";
58 read-only;
59 };
60
61 partition@3e00000 {
62 reg = <0x03e00000 0x00200000>;
63 label = "dink-nor";
64 read-only;
65 };
66
67 partition@4000000 {
68 reg = <0x04000000 0x00400000>;
69 label = "kernel-nor";
70 read-only;
71 };
72
73 partition@4400000 {
74 reg = <0x04400000 0x03b00000>;
75 label = "jffs2-nor";
76 };
77
78 partition@7f00000 {
79 reg = <0x07f00000 0x00080000>;
80 label = "dtb-nor";
81 read-only;
82 };
83
84 partition@7f80000 {
85 reg = <0x07f80000 0x00080000>;
86 label = "u-boot-nor";
87 read-only;
88 };
89 };
90
91 nand@2,0 {
92 #address-cells = <1>;
93 #size-cells = <1>;
94 compatible = "fsl,elbc-fcm-nand";
95 reg = <0x2 0x0 0x40000>;
96
97 partition@0 {
98 reg = <0x0 0x02000000>;
99 label = "u-boot-nand";
100 read-only;
101 };
102
103 partition@2000000 {
104 reg = <0x02000000 0x10000000>;
105 label = "jffs2-nand";
106 };
107
108 partition@12000000 {
109 reg = <0x12000000 0x10000000>;
110 label = "ramdisk-nand";
111 read-only;
112 };
113
114 partition@22000000 {
115 reg = <0x22000000 0x04000000>;
116 label = "kernel-nand";
117 };
118
119 partition@26000000 {
120 reg = <0x26000000 0x01000000>;
121 label = "dtb-nand";
122 read-only;
123 };
124
125 partition@27000000 {
126 reg = <0x27000000 0x19000000>;
127 label = "reserved-nand";
128 };
129 };
130
131 board-control@3,0 {
132 compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
133 reg = <3 0 0x30>;
134 interrupt-parent = <&mpic>;
135 /*
136 * IRQ8 is generated if the "EVENT" switch is pressed
137 * and PX_CTL[EVESEL] is set to 00.
138 */
139 interrupts = <8 8 0 0>;
140 };
141 };
142
143 soc: soc@fffe00000 {
144 ranges = <0x0 0xf 0xffe00000 0x100000>;
145
146 i2c@3100 {
147 wm8776:codec@1a {
148 compatible = "wlf,wm8776";
149 reg = <0x1a>;
150 /*
151 * clock-frequency will be set by U-Boot if
152 * the clock is enabled.
153 */
154 };
155 };
156
157 spi@7000 {
158 flash@0 {
159 #address-cells = <1>;
160 #size-cells = <1>;
161 compatible = "spansion,s25sl12801";
162 reg = <0>;
163 spi-max-frequency = <40000000>; /* input clock */
164
165 partition@0 {
166 label = "u-boot-spi";
167 reg = <0x00000000 0x00100000>;
168 read-only;
169 };
170 partition@100000 {
171 label = "kernel-spi";
172 reg = <0x00100000 0x00500000>;
173 read-only;
174 };
175 partition@600000 {
176 label = "dtb-spi";
177 reg = <0x00600000 0x00100000>;
178 read-only;
179 };
180 partition@700000 {
181 label = "file system-spi";
182 reg = <0x00700000 0x00900000>;
183 };
184 };
185 };
186
187 ssi@15000 {
188 fsl,mode = "i2s-slave";
189 codec-handle = <&wm8776>;
190 fsl,ssi-asynchronous;
191 };
192
193 usb@22000 {
194 phy_type = "ulpi";
195 };
196
197 usb@23000 {
198 status = "disabled";
199 };
200
201 mdio@24000 {
202 phy0: ethernet-phy@0 {
203 interrupts = <3 1 0 0>;
204 reg = <0x1>;
205 };
206 phy1: ethernet-phy@1 {
207 interrupts = <9 1 0 0>;
208 reg = <0x2>;
209 };
210 tbi-phy@2 {
211 device_type = "tbi-phy";
212 reg = <0x2>;
213 };
214 };
215
216 ethernet@b0000 {
217 phy-handle = <&phy0>;
218 phy-connection-type = "rgmii-id";
219 };
220
221 ethernet@b1000 {
222 phy-handle = <&phy1>;
223 phy-connection-type = "rgmii-id";
224 };
225 };
226
227 pci0: pcie@fffe09000 {
228 reg = <0xf 0xffe09000 0 0x1000>;
229 ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
230 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
231 pcie@0 {
232 ranges = <0x2000000 0x0 0xe0000000
233 0x2000000 0x0 0xe0000000
234 0x0 0x20000000
235
236 0x1000000 0x0 0x0
237 0x1000000 0x0 0x0
238 0x0 0x100000>;
239 };
240 };
241
242 pci1: pcie@fffe0a000 {
243 reg = <0xf 0xffe0a000 0 0x1000>;
244 ranges = <0x2000000 0x0 0xe0000000 0xc 0x40000000 0x0 0x20000000
245 0x1000000 0x0 0x00000000 0xf 0xffc20000 0x0 0x10000>;
246 pcie@0 {
247 reg = <0x0 0x0 0x0 0x0 0x0>;
248 ranges = <0x2000000 0x0 0xe0000000
249 0x2000000 0x0 0xe0000000
250 0x0 0x20000000
251
252 0x1000000 0x0 0x0
253 0x1000000 0x0 0x0
254 0x0 0x100000>;
255 };
256 };
257
258 pci2: pcie@fffe0b000 {
259 reg = <0xf 0xffe0b000 0 0x1000>;
260 ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
261 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
262 pcie@0 {
263 ranges = <0x2000000 0x0 0xe0000000
264 0x2000000 0x0 0xe0000000
265 0x0 0x20000000
266
267 0x1000000 0x0 0x0
268 0x1000000 0x0 0x0
269 0x0 0x100000>;
270 };
271 };
272};
273
274/include/ "fsl/p1022si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1022ds.dtsi b/arch/powerpc/boot/dts/p1022ds.dtsi
new file mode 100644
index 000000000000..7cdb505036bb
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1022ds.dtsi
@@ -0,0 +1,234 @@
1/*
2 * P1022 DS Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&board_lbc {
36 /*
37 * This node is used to access the pixis via "indirect" mode,
38 * which is done by writing the pixis register index to chip
39 * select 0 and the value to/from chip select 1. Indirect
40 * mode is the only way to access the pixis when DIU video
41 * is enabled. Note that this assumes that the first column
42 * of the 'ranges' property above is the chip select number.
43 */
44 board-control@0,0 {
45 compatible = "fsl,p1022ds-indirect-pixis";
46 reg = <0x0 0x0 1 /* CS0 */
47 0x1 0x0 1>; /* CS1 */
48 interrupt-parent = <&mpic>;
49 interrupts = <8 0 0 0>;
50 };
51
52 nor@0,0 {
53 #address-cells = <1>;
54 #size-cells = <1>;
55 compatible = "cfi-flash";
56 reg = <0x0 0x0 0x8000000>;
57 bank-width = <2>;
58 device-width = <1>;
59
60 partition@0 {
61 reg = <0x0 0x03000000>;
62 label = "ramdisk-nor";
63 read-only;
64 };
65
66 partition@3000000 {
67 reg = <0x03000000 0x00e00000>;
68 label = "diagnostic-nor";
69 read-only;
70 };
71
72 partition@3e00000 {
73 reg = <0x03e00000 0x00200000>;
74 label = "dink-nor";
75 read-only;
76 };
77
78 partition@4000000 {
79 reg = <0x04000000 0x00400000>;
80 label = "kernel-nor";
81 read-only;
82 };
83
84 partition@4400000 {
85 reg = <0x04400000 0x03b00000>;
86 label = "jffs2-nor";
87 };
88
89 partition@7f00000 {
90 reg = <0x07f00000 0x00080000>;
91 label = "dtb-nor";
92 read-only;
93 };
94
95 partition@7f80000 {
96 reg = <0x07f80000 0x00080000>;
97 label = "u-boot-nor";
98 read-only;
99 };
100 };
101
102 nand@2,0 {
103 #address-cells = <1>;
104 #size-cells = <1>;
105 compatible = "fsl,elbc-fcm-nand";
106 reg = <0x2 0x0 0x40000>;
107
108 partition@0 {
109 reg = <0x0 0x02000000>;
110 label = "u-boot-nand";
111 read-only;
112 };
113
114 partition@2000000 {
115 reg = <0x02000000 0x10000000>;
116 label = "jffs2-nand";
117 };
118
119 partition@12000000 {
120 reg = <0x12000000 0x10000000>;
121 label = "ramdisk-nand";
122 read-only;
123 };
124
125 partition@22000000 {
126 reg = <0x22000000 0x04000000>;
127 label = "kernel-nand";
128 };
129
130 partition@26000000 {
131 reg = <0x26000000 0x01000000>;
132 label = "dtb-nand";
133 read-only;
134 };
135
136 partition@27000000 {
137 reg = <0x27000000 0x19000000>;
138 label = "reserved-nand";
139 };
140 };
141
142 board-control@3,0 {
143 compatible = "fsl,p1022ds-fpga", "fsl,fpga-ngpixis";
144 reg = <3 0 0x30>;
145 interrupt-parent = <&mpic>;
146 /*
147 * IRQ8 is generated if the "EVENT" switch is pressed
148 * and PX_CTL[EVESEL] is set to 00.
149 */
150 interrupts = <8 0 0 0>;
151 };
152};
153
154&board_soc {
155 i2c@3100 {
156 wm8776:codec@1a {
157 compatible = "wlf,wm8776";
158 reg = <0x1a>;
159 /*
160 * clock-frequency will be set by U-Boot if
161 * the clock is enabled.
162 */
163 };
164 };
165
166 spi@7000 {
167 flash@0 {
168 #address-cells = <1>;
169 #size-cells = <1>;
170 compatible = "spansion,s25sl12801";
171 reg = <0>;
172 spi-max-frequency = <40000000>; /* input clock */
173
174 partition@0 {
175 label = "u-boot-spi";
176 reg = <0x00000000 0x00100000>;
177 read-only;
178 };
179 partition@100000 {
180 label = "kernel-spi";
181 reg = <0x00100000 0x00500000>;
182 read-only;
183 };
184 partition@600000 {
185 label = "dtb-spi";
186 reg = <0x00600000 0x00100000>;
187 read-only;
188 };
189 partition@700000 {
190 label = "file system-spi";
191 reg = <0x00700000 0x00900000>;
192 };
193 };
194 };
195
196 ssi@15000 {
197 fsl,mode = "i2s-slave";
198 codec-handle = <&wm8776>;
199 fsl,ssi-asynchronous;
200 };
201
202 usb@22000 {
203 phy_type = "ulpi";
204 };
205
206 usb@23000 {
207 status = "disabled";
208 };
209
210 mdio@24000 {
211 phy0: ethernet-phy@0 {
212 interrupts = <3 1 0 0>;
213 reg = <0x1>;
214 };
215 phy1: ethernet-phy@1 {
216 interrupts = <9 1 0 0>;
217 reg = <0x2>;
218 };
219 tbi-phy@2 {
220 device_type = "tbi-phy";
221 reg = <0x2>;
222 };
223 };
224
225 ethernet@b0000 {
226 phy-handle = <&phy0>;
227 phy-connection-type = "rgmii-id";
228 };
229
230 ethernet@b1000 {
231 phy-handle = <&phy1>;
232 phy-connection-type = "rgmii-id";
233 };
234};
diff --git a/arch/powerpc/boot/dts/p1022ds_32b.dts b/arch/powerpc/boot/dts/p1022ds_32b.dts
new file mode 100644
index 000000000000..d96cae00a9e3
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1022ds_32b.dts
@@ -0,0 +1,103 @@
1/*
2 * P1022 DS 32-bit Physical Address Map Device Tree Source
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1022si-pre.dtsi"
36/ {
37 model = "fsl,P1022DS";
38 compatible = "fsl,P1022DS";
39
40 memory {
41 device_type = "memory";
42 };
43
44 board_lbc: lbc: localbus@ffe05000 {
45 ranges = <0x0 0x0 0x0 0xe8000000 0x08000000
46 0x1 0x0 0x0 0xe0000000 0x08000000
47 0x2 0x0 0x0 0xff800000 0x00040000
48 0x3 0x0 0x0 0xffdf0000 0x00008000>;
49 reg = <0x0 0xffe05000 0 0x1000>;
50 };
51
52 board_soc: soc: soc@ffe00000 {
53 ranges = <0x0 0x0 0xffe00000 0x100000>;
54 };
55
56 pci0: pcie@ffe09000 {
57 ranges = <0x2000000 0x0 0xe0000000 0 0xa0000000 0x0 0x20000000
58 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
59 reg = <0x0 0xffe09000 0 0x1000>;
60 pcie@0 {
61 ranges = <0x2000000 0x0 0xe0000000
62 0x2000000 0x0 0xe0000000
63 0x0 0x20000000
64
65 0x1000000 0x0 0x0
66 0x1000000 0x0 0x0
67 0x0 0x100000>;
68 };
69 };
70
71 pci1: pcie@ffe0a000 {
72 ranges = <0x2000000 0x0 0xe0000000 0 0xc0000000 0x0 0x20000000
73 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
74 reg = <0 0xffe0a000 0 0x1000>;
75 pcie@0 {
76 ranges = <0x2000000 0x0 0xe0000000
77 0x2000000 0x0 0xe0000000
78 0x0 0x20000000
79
80 0x1000000 0x0 0x0
81 0x1000000 0x0 0x0
82 0x0 0x100000>;
83 };
84 };
85
86 pci2: pcie@ffe0b000 {
87 ranges = <0x2000000 0x0 0xe0000000 0 0x80000000 0x0 0x20000000
88 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
89 reg = <0 0xffe0b000 0 0x1000>;
90 pcie@0 {
91 ranges = <0x2000000 0x0 0xe0000000
92 0x2000000 0x0 0xe0000000
93 0x0 0x20000000
94
95 0x1000000 0x0 0x0
96 0x1000000 0x0 0x0
97 0x0 0x100000>;
98 };
99 };
100};
101
102/include/ "fsl/p1022si-post.dtsi"
103/include/ "p1022ds.dtsi"
diff --git a/arch/powerpc/boot/dts/p1022ds_36b.dts b/arch/powerpc/boot/dts/p1022ds_36b.dts
new file mode 100644
index 000000000000..f7aacce40bf6
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1022ds_36b.dts
@@ -0,0 +1,103 @@
1/*
2 * P1022 DS 36-bit Physical Address Map Device Tree Source
3 *
4 * Copyright 2012 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1022si-pre.dtsi"
36/ {
37 model = "fsl,P1022DS";
38 compatible = "fsl,P1022DS";
39
40 memory {
41 device_type = "memory";
42 };
43
44 board_lbc: lbc: localbus@fffe05000 {
45 ranges = <0x0 0x0 0xf 0xe8000000 0x08000000
46 0x1 0x0 0xf 0xe0000000 0x08000000
47 0x2 0x0 0xf 0xff800000 0x00040000
48 0x3 0x0 0xf 0xffdf0000 0x00008000>;
49 reg = <0xf 0xffe05000 0 0x1000>;
50 };
51
52 board_soc: soc: soc@fffe00000 {
53 ranges = <0x0 0xf 0xffe00000 0x100000>;
54 };
55
56 pci0: pcie@fffe09000 {
57 ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
58 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
59 reg = <0xf 0xffe09000 0 0x1000>;
60 pcie@0 {
61 ranges = <0x2000000 0x0 0xe0000000
62 0x2000000 0x0 0xe0000000
63 0x0 0x20000000
64
65 0x1000000 0x0 0x0
66 0x1000000 0x0 0x0
67 0x0 0x100000>;
68 };
69 };
70
71 pci1: pcie@fffe0a000 {
72 ranges = <0x2000000 0x0 0xe0000000 0xc 0x40000000 0x0 0x20000000
73 0x1000000 0x0 0x00000000 0xf 0xffc20000 0x0 0x10000>;
74 reg = <0xf 0xffe0a000 0 0x1000>;
75 pcie@0 {
76 ranges = <0x2000000 0x0 0xe0000000
77 0x2000000 0x0 0xe0000000
78 0x0 0x20000000
79
80 0x1000000 0x0 0x0
81 0x1000000 0x0 0x0
82 0x0 0x100000>;
83 };
84 };
85
86 pci2: pcie@fffe0b000 {
87 ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
88 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
89 reg = <0xf 0xffe0b000 0 0x1000>;
90 pcie@0 {
91 ranges = <0x2000000 0x0 0xe0000000
92 0x2000000 0x0 0xe0000000
93 0x0 0x20000000
94
95 0x1000000 0x0 0x0
96 0x1000000 0x0 0x0
97 0x0 0x100000>;
98 };
99 };
100};
101
102/include/ "fsl/p1022si-post.dtsi"
103/include/ "p1022ds.dtsi"
diff --git a/arch/powerpc/boot/dts/p1025rdb.dtsi b/arch/powerpc/boot/dts/p1025rdb.dtsi
new file mode 100644
index 000000000000..cf3676fc714b
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1025rdb.dtsi
@@ -0,0 +1,286 @@
1/*
2 * P1025 RDB Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x1000000>;
41 bank-width = <2>;
42 device-width = <1>;
43
44 partition@0 {
45 /* This location must not be altered */
46 /* 256KB for Vitesse 7385 Switch firmware */
47 reg = <0x0 0x00040000>;
48 label = "NOR Vitesse-7385 Firmware";
49 read-only;
50 };
51
52 partition@40000 {
53 /* 256KB for DTB Image */
54 reg = <0x00040000 0x00040000>;
55 label = "NOR DTB Image";
56 };
57
58 partition@80000 {
59 /* 3.5 MB for Linux Kernel Image */
60 reg = <0x00080000 0x00380000>;
61 label = "NOR Linux Kernel Image";
62 };
63
64 partition@400000 {
65 /* 11MB for JFFS2 based Root file System */
66 reg = <0x00400000 0x00b00000>;
67 label = "NOR JFFS2 Root File System";
68 };
69
70 partition@f00000 {
71 /* This location must not be altered */
72 /* 512KB for u-boot Bootloader Image */
73 /* 512KB for u-boot Environment Variables */
74 reg = <0x00f00000 0x00100000>;
75 label = "NOR U-Boot Image";
76 read-only;
77 };
78 };
79
80 nand@1,0 {
81 #address-cells = <1>;
82 #size-cells = <1>;
83 compatible = "fsl,p1025-fcm-nand",
84 "fsl,elbc-fcm-nand";
85 reg = <0x1 0x0 0x40000>;
86
87 partition@0 {
88 /* This location must not be altered */
89 /* 1MB for u-boot Bootloader Image */
90 reg = <0x0 0x00100000>;
91 label = "NAND U-Boot Image";
92 read-only;
93 };
94
95 partition@100000 {
96 /* 1MB for DTB Image */
97 reg = <0x00100000 0x00100000>;
98 label = "NAND DTB Image";
99 };
100
101 partition@200000 {
102 /* 4MB for Linux Kernel Image */
103 reg = <0x00200000 0x00400000>;
104 label = "NAND Linux Kernel Image";
105 };
106
107 partition@600000 {
108 /* 4MB for Compressed Root file System Image */
109 reg = <0x00600000 0x00400000>;
110 label = "NAND Compressed RFS Image";
111 };
112
113 partition@a00000 {
114 /* 7MB for JFFS2 based Root file System */
115 reg = <0x00a00000 0x00700000>;
116 label = "NAND JFFS2 Root File System";
117 };
118
119 partition@1100000 {
120 /* 15MB for JFFS2 based Root file System */
121 reg = <0x01100000 0x00f00000>;
122 label = "NAND Writable User area";
123 };
124 };
125
126};
127
128&soc {
129 i2c@3000 {
130 rtc@68 {
131 compatible = "dallas,ds1339";
132 reg = <0x68>;
133 };
134 };
135
136 spi@7000 {
137 flash@0 {
138 #address-cells = <1>;
139 #size-cells = <1>;
140 compatible = "spansion,s25sl12801";
141 reg = <0>;
142 spi-max-frequency = <40000000>; /* input clock */
143
144 partition@u-boot {
145 /* 512KB for u-boot Bootloader Image */
146 reg = <0x0 0x00080000>;
147 label = "u-boot";
148 read-only;
149 };
150
151 partition@dtb {
152 /* 512KB for DTB Image */
153 reg = <0x00080000 0x00080000>;
154 label = "dtb";
155 };
156
157 partition@kernel {
158 /* 4MB for Linux Kernel Image */
159 reg = <0x00100000 0x00400000>;
160 label = "kernel";
161 };
162
163 partition@fs {
164 /* 4MB for Compressed RFS Image */
165 reg = <0x00500000 0x00400000>;
166 label = "file system";
167 };
168
169 partition@jffs-fs {
170 /* 7MB for JFFS2 based RFS */
171 reg = <0x00900000 0x00700000>;
172 label = "file system jffs2";
173 };
174 };
175 };
176
177 usb@22000 {
178 phy_type = "ulpi";
179 };
180
181 /* USB2 is shared with localbus, so it must be disabled
182 by default. We can't put 'status = "disabled";' here
183 since U-Boot doesn't clear the status property when
184 it enables USB2. OTOH, U-Boot does create a new node
185 when there isn't any. So, just comment it out.
186 usb@23000 {
187 phy_type = "ulpi";
188 };
189 */
190
191 mdio@24000 {
192 phy0: ethernet-phy@0 {
193 interrupt-parent = <&mpic>;
194 interrupts = <3 1>;
195 reg = <0x0>;
196 };
197
198 phy1: ethernet-phy@1 {
199 interrupt-parent = <&mpic>;
200 interrupts = <2 1>;
201 reg = <0x1>;
202 };
203
204 tbi0: tbi-phy@11 {
205 reg = <0x11>;
206 device_type = "tbi-phy";
207 };
208 };
209
210 mdio@25000 {
211 tbi1: tbi-phy@11 {
212 reg = <0x11>;
213 device_type = "tbi-phy";
214 };
215 };
216
217 mdio@26000 {
218 tbi2: tbi-phy@11 {
219 reg = <0x11>;
220 device_type = "tbi-phy";
221 };
222 };
223
224 enet0: ethernet@b0000 {
225 fixed-link = <1 1 1000 0 0>;
226 phy-connection-type = "rgmii-id";
227
228 };
229
230 enet1: ethernet@b1000 {
231 phy-handle = <&phy0>;
232 tbi-handle = <&tbi1>;
233 phy-connection-type = "sgmii";
234 };
235
236 enet2: ethernet@b2000 {
237 phy-handle = <&phy1>;
238 phy-connection-type = "rgmii-id";
239 };
240
241 par_io@e0100 {
242 #address-cells = <1>;
243 #size-cells = <1>;
244 reg = <0xe0100 0x60>;
245 ranges = <0x0 0xe0100 0x60>;
246 device_type = "par_io";
247 num-ports = <3>;
248 pio1: ucc_pin@01 {
249 pio-map = <
250 /* port pin dir open_drain assignment has_irq */
251 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
252 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
253 0x0 0x17 0x2 0x0 0x2 0x0 /* CLK12 */
254 0x0 0x18 0x2 0x0 0x1 0x0 /* CLK9 */
255 0x0 0x7 0x1 0x0 0x2 0x0 /* ENET1_TXD0_SER1_TXD0 */
256 0x0 0x9 0x1 0x0 0x2 0x0 /* ENET1_TXD1_SER1_TXD1 */
257 0x0 0xb 0x1 0x0 0x2 0x0 /* ENET1_TXD2_SER1_TXD2 */
258 0x0 0xc 0x1 0x0 0x2 0x0 /* ENET1_TXD3_SER1_TXD3 */
259 0x0 0x6 0x2 0x0 0x2 0x0 /* ENET1_RXD0_SER1_RXD0 */
260 0x0 0xa 0x2 0x0 0x2 0x0 /* ENET1_RXD1_SER1_RXD1 */
261 0x0 0xe 0x2 0x0 0x2 0x0 /* ENET1_RXD2_SER1_RXD2 */
262 0x0 0xf 0x2 0x0 0x2 0x0 /* ENET1_RXD3_SER1_RXD3 */
263 0x0 0x5 0x1 0x0 0x2 0x0 /* ENET1_TX_EN_SER1_RTS_B */
264 0x0 0xd 0x1 0x0 0x2 0x0 /* ENET1_TX_ER */
265 0x0 0x4 0x2 0x0 0x2 0x0 /* ENET1_RX_DV_SER1_CTS_B */
266 0x0 0x8 0x2 0x0 0x2 0x0 /* ENET1_RX_ER_SER1_CD_B */
267 0x0 0x11 0x2 0x0 0x2 0x0 /* ENET1_CRS */
268 0x0 0x10 0x2 0x0 0x2 0x0>; /* ENET1_COL */
269 };
270
271 pio2: ucc_pin@02 {
272 pio-map = <
273 /* port pin dir open_drain assignment has_irq */
274 0x1 0x13 0x1 0x0 0x1 0x0 /* QE_MUX_MDC */
275 0x1 0x14 0x3 0x0 0x1 0x0 /* QE_MUX_MDIO */
276 0x1 0xb 0x2 0x0 0x1 0x0 /* CLK13 */
277 0x1 0x7 0x1 0x0 0x2 0x0 /* ENET5_TXD0_SER5_TXD0 */
278 0x1 0xa 0x1 0x0 0x2 0x0 /* ENET5_TXD1_SER5_TXD1 */
279 0x1 0x6 0x2 0x0 0x2 0x0 /* ENET5_RXD0_SER5_RXD0 */
280 0x1 0x9 0x2 0x0 0x2 0x0 /* ENET5_RXD1_SER5_RXD1 */
281 0x1 0x5 0x1 0x0 0x2 0x0 /* ENET5_TX_EN_SER5_RTS_B */
282 0x1 0x4 0x2 0x0 0x2 0x0 /* ENET5_RX_DV_SER5_CTS_B */
283 0x1 0x8 0x2 0x0 0x2 0x0>; /* ENET5_RX_ER_SER5_CD_B */
284 };
285 };
286};
diff --git a/arch/powerpc/boot/dts/p1025rdb_32b.dts b/arch/powerpc/boot/dts/p1025rdb_32b.dts
new file mode 100644
index 000000000000..ac5729c14eda
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1025rdb_32b.dts
@@ -0,0 +1,135 @@
1/*
2 * P1025 RDB Device Tree Source (32-bit address map)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1021si-pre.dtsi"
36/ {
37 model = "fsl,P1025RDB";
38 compatible = "fsl,P1025RDB";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@ffe05000 {
45 reg = <0 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes */
48 ranges = <0x0 0x0 0x0 0xef000000 0x01000000
49 0x1 0x0 0x0 0xff800000 0x00040000>;
50 };
51
52 soc: soc@ffe00000 {
53 ranges = <0x0 0x0 0xffe00000 0x100000>;
54 };
55
56 pci0: pcie@ffe09000 {
57 ranges = <0x2000000 0x0 0xe0000000 0 0xe0000000 0x0 0x20000000
58 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
59 reg = <0 0xffe09000 0 0x1000>;
60 pcie@0 {
61 ranges = <0x2000000 0x0 0xe0000000
62 0x2000000 0x0 0xe0000000
63 0x0 0x20000000
64
65 0x1000000 0x0 0x0
66 0x1000000 0x0 0x0
67 0x0 0x100000>;
68 };
69 };
70
71 pci1: pcie@ffe0a000 {
72 reg = <0 0xffe0a000 0 0x1000>;
73 ranges = <0x2000000 0x0 0xe0000000 0 0xe0000000 0x0 0x20000000
74 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
75 pcie@0 {
76 ranges = <0x2000000 0x0 0xe0000000
77 0x2000000 0x0 0xe0000000
78 0x0 0x20000000
79
80 0x1000000 0x0 0x0
81 0x1000000 0x0 0x0
82 0x0 0x100000>;
83 };
84 };
85
86 qe: qe@ffe80000 {
87 ranges = <0x0 0x0 0xffe80000 0x40000>;
88 reg = <0 0xffe80000 0 0x480>;
89 brg-frequency = <0>;
90 bus-frequency = <0>;
91 status = "disabled"; /* no firmware loaded */
92
93 enet3: ucc@2000 {
94 device_type = "network";
95 compatible = "ucc_geth";
96 rx-clock-name = "clk12";
97 tx-clock-name = "clk9";
98 pio-handle = <&pio1>;
99 phy-handle = <&qe_phy0>;
100 phy-connection-type = "mii";
101 };
102
103 mdio@2120 {
104 qe_phy0: ethernet-phy@0 {
105 interrupt-parent = <&mpic>;
106 interrupts = <4 1 0 0>;
107 reg = <0x6>;
108 device_type = "ethernet-phy";
109 };
110 qe_phy1: ethernet-phy@03 {
111 interrupt-parent = <&mpic>;
112 interrupts = <5 1 0 0>;
113 reg = <0x3>;
114 device_type = "ethernet-phy";
115 };
116 tbi-phy@11 {
117 reg = <0x11>;
118 device_type = "tbi-phy";
119 };
120 };
121
122 enet4: ucc@2400 {
123 device_type = "network";
124 compatible = "ucc_geth";
125 rx-clock-name = "none";
126 tx-clock-name = "clk13";
127 pio-handle = <&pio2>;
128 phy-handle = <&qe_phy1>;
129 phy-connection-type = "rmii";
130 };
131 };
132};
133
134/include/ "p1025rdb.dtsi"
135/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1025rdb_36b.dts b/arch/powerpc/boot/dts/p1025rdb_36b.dts
new file mode 100644
index 000000000000..4ce4bfa0eda4
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1025rdb_36b.dts
@@ -0,0 +1,88 @@
1/*
2 * P1025 RDB Device Tree Source (36-bit address map)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p1021si-pre.dtsi"
36/ {
37 model = "fsl,P1025RDB";
38 compatible = "fsl,P1025RDB";
39
40 memory {
41 device_type = "memory";
42 };
43
44 lbc: localbus@fffe05000 {
45 reg = <0xf 0xffe05000 0 0x1000>;
46
47 /* NOR, NAND Flashes */
48 ranges = <0x0 0x0 0xf 0xef000000 0x01000000
49 0x1 0x0 0xf 0xff800000 0x00040000>;
50 };
51
52 soc: soc@fffe00000 {
53 ranges = <0x0 0xf 0xffe00000 0x100000>;
54 };
55
56 pci0: pcie@fffe09000 {
57 reg = <0xf 0xffe09000 0 0x1000>;
58 ranges = <0x2000000 0x0 0xe0000000 0xe 0x20000000 0x0 0x20000000
59 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
60 pcie@0 {
61 ranges = <0x2000000 0x0 0xe0000000
62 0x2000000 0x0 0xe0000000
63 0x0 0x20000000
64
65 0x1000000 0x0 0x0
66 0x1000000 0x0 0x0
67 0x0 0x100000>;
68 };
69 };
70
71 pci1: pcie@fffe0a000 {
72 reg = <0xf 0xffe0a000 0 0x1000>;
73 ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
74 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
75 pcie@0 {
76 ranges = <0x2000000 0x0 0xe0000000
77 0x2000000 0x0 0xe0000000
78 0x0 0x20000000
79
80 0x1000000 0x0 0x0
81 0x1000000 0x0 0x0
82 0x0 0x100000>;
83 };
84 };
85};
86
87/include/ "p1025rdb.dtsi"
88/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2020rdb-pc.dtsi b/arch/powerpc/boot/dts/p2020rdb-pc.dtsi
new file mode 100644
index 000000000000..c21d1c7d16cd
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2020rdb-pc.dtsi
@@ -0,0 +1,241 @@
1/*
2 * P2020 RDB-PC Device Tree Source stub (no addresses or top-level ranges)
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35&lbc {
36 nor@0,0 {
37 #address-cells = <1>;
38 #size-cells = <1>;
39 compatible = "cfi-flash";
40 reg = <0x0 0x0 0x1000000>;
41 bank-width = <2>;
42 device-width = <1>;
43
44 partition@0 {
45 /* This location must not be altered */
46 /* 256KB for Vitesse 7385 Switch firmware */
47 reg = <0x0 0x00040000>;
48 label = "NOR Vitesse-7385 Firmware";
49 read-only;
50 };
51
52 partition@40000 {
53 /* 256KB for DTB Image */
54 reg = <0x00040000 0x00040000>;
55 label = "NOR DTB Image";
56 };
57
58 partition@80000 {
59 /* 3.5 MB for Linux Kernel Image */
60 reg = <0x00080000 0x00380000>;
61 label = "NOR Linux Kernel Image";
62 };
63
64 partition@400000 {
65 /* 11MB for JFFS2 based Root file System */
66 reg = <0x00400000 0x00b00000>;
67 label = "NOR JFFS2 Root File System";
68 };
69
70 partition@f00000 {
71 /* This location must not be altered */
72 /* 512KB for u-boot Bootloader Image */
73 /* 512KB for u-boot Environment Variables */
74 reg = <0x00f00000 0x00100000>;
75 label = "NOR U-Boot Image";
76 read-only;
77 };
78 };
79
80 nand@1,0 {
81 #address-cells = <1>;
82 #size-cells = <1>;
83 compatible = "fsl,p2020-fcm-nand",
84 "fsl,elbc-fcm-nand";
85 reg = <0x1 0x0 0x40000>;
86
87 partition@0 {
88 /* This location must not be altered */
89 /* 1MB for u-boot Bootloader Image */
90 reg = <0x0 0x00100000>;
91 label = "NAND U-Boot Image";
92 read-only;
93 };
94
95 partition@100000 {
96 /* 1MB for DTB Image */
97 reg = <0x00100000 0x00100000>;
98 label = "NAND DTB Image";
99 };
100
101 partition@200000 {
102 /* 4MB for Linux Kernel Image */
103 reg = <0x00200000 0x00400000>;
104 label = "NAND Linux Kernel Image";
105 };
106
107 partition@600000 {
108 /* 4MB for Compressed Root file System Image */
109 reg = <0x00600000 0x00400000>;
110 label = "NAND Compressed RFS Image";
111 };
112
113 partition@a00000 {
114 /* 7MB for JFFS2 based Root file System */
115 reg = <0x00a00000 0x00700000>;
116 label = "NAND JFFS2 Root File System";
117 };
118
119 partition@1100000 {
120 /* 15MB for JFFS2 based Root file System */
121 reg = <0x01100000 0x00f00000>;
122 label = "NAND Writable User area";
123 };
124 };
125
126 L2switch@2,0 {
127 #address-cells = <1>;
128 #size-cells = <1>;
129 compatible = "vitesse-7385";
130 reg = <0x2 0x0 0x20000>;
131 };
132
133 cpld@3,0 {
134 #address-cells = <1>;
135 #size-cells = <1>;
136 compatible = "cpld";
137 reg = <0x3 0x0 0x20000>;
138 read-only;
139 };
140};
141
142&soc {
143 i2c@3000 {
144 rtc@68 {
145 compatible = "pericom,pt7c4338";
146 reg = <0x68>;
147 };
148 };
149
150 spi@7000 {
151 flash@0 {
152 #address-cells = <1>;
153 #size-cells = <1>;
154 compatible = "spansion,m25p80";
155 reg = <0>;
156 spi-max-frequency = <40000000>;
157
158 partition@0 {
159 /* 512KB for u-boot Bootloader Image */
160 reg = <0x0 0x00080000>;
161 label = "SPI U-Boot Image";
162 read-only;
163 };
164
165 partition@80000 {
166 /* 512KB for DTB Image */
167 reg = <0x00080000 0x00080000>;
168 label = "SPI DTB Image";
169 };
170
171 partition@100000 {
172 /* 4MB for Linux Kernel Image */
173 reg = <0x00100000 0x00400000>;
174 label = "SPI Linux Kernel Image";
175 };
176
177 partition@500000 {
178 /* 4MB for Compressed RFS Image */
179 reg = <0x00500000 0x00400000>;
180 label = "SPI Compressed RFS Image";
181 };
182
183 partition@900000 {
184 /* 7MB for JFFS2 based RFS */
185 reg = <0x00900000 0x00700000>;
186 label = "SPI JFFS2 RFS";
187 };
188 };
189 };
190
191 usb@22000 {
192 phy_type = "ulpi";
193 };
194
195 mdio@24520 {
196 phy0: ethernet-phy@0 {
197 interrupts = <3 1 0 0>;
198 reg = <0x0>;
199 };
200 phy1: ethernet-phy@1 {
201 interrupts = <2 1 0 0>;
202 reg = <0x1>;
203 };
204 };
205
206 mdio@25520 {
207 tbi0: tbi-phy@11 {
208 reg = <0x11>;
209 device_type = "tbi-phy";
210 };
211 };
212
213 mdio@26520 {
214 status = "disabled";
215 };
216
217 ptp_clock@24e00 {
218 fsl,tclk-period = <5>;
219 fsl,tmr-prsc = <200>;
220 fsl,tmr-add = <0xCCCCCCCD>;
221 fsl,tmr-fiper1 = <0x3B9AC9FB>;
222 fsl,tmr-fiper2 = <0x0001869B>;
223 fsl,max-adj = <249999999>;
224 };
225
226 enet0: ethernet@24000 {
227 fixed-link = <1 1 1000 0 0>;
228 phy-connection-type = "rgmii-id";
229 };
230
231 enet1: ethernet@25000 {
232 tbi-handle = <&tbi0>;
233 phy-handle = <&phy0>;
234 phy-connection-type = "sgmii";
235 };
236
237 enet2: ethernet@26000 {
238 phy-handle = <&phy1>;
239 phy-connection-type = "rgmii-id";
240 };
241};
diff --git a/arch/powerpc/boot/dts/p2020rdb-pc_32b.dts b/arch/powerpc/boot/dts/p2020rdb-pc_32b.dts
new file mode 100644
index 000000000000..852e5b27485d
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2020rdb-pc_32b.dts
@@ -0,0 +1,96 @@
1/*
2 * P2020 RDB-PC 32Bit Physical Address Map Device Tree Source
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p2020si-pre.dtsi"
36
37/ {
38 model = "fsl,P2020RDB";
39 compatible = "fsl,P2020RDB-PC";
40
41 memory {
42 device_type = "memory";
43 };
44
45 lbc: localbus@ffe05000 {
46 reg = <0 0xffe05000 0 0x1000>;
47
48 /* NOR and NAND Flashes */
49 ranges = <0x0 0x0 0x0 0xef000000 0x01000000
50 0x1 0x0 0x0 0xff800000 0x00040000
51 0x2 0x0 0x0 0xffb00000 0x00020000
52 0x3 0x0 0x0 0xffa00000 0x00020000>;
53 };
54
55 soc: soc@ffe00000 {
56 ranges = <0x0 0x0 0xffe00000 0x100000>;
57 };
58
59 pci0: pcie@ffe08000 {
60 reg = <0 0xffe08000 0 0x1000>;
61 status = "disabled";
62 };
63
64 pci1: pcie@ffe09000 {
65 reg = <0 0xffe09000 0 0x1000>;
66 ranges = <0x2000000 0x0 0xe0000000 0 0xa0000000 0x0 0x20000000
67 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
68 pcie@0 {
69 ranges = <0x2000000 0x0 0xe0000000
70 0x2000000 0x0 0xe0000000
71 0x0 0x20000000
72
73 0x1000000 0x0 0x0
74 0x1000000 0x0 0x0
75 0x0 0x100000>;
76 };
77 };
78
79 pci2: pcie@ffe0a000 {
80 reg = <0 0xffe0a000 0 0x1000>;
81 ranges = <0x2000000 0x0 0xe0000000 0 0x80000000 0x0 0x20000000
82 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
83 pcie@0 {
84 ranges = <0x2000000 0x0 0xe0000000
85 0x2000000 0x0 0xe0000000
86 0x0 0x20000000
87
88 0x1000000 0x0 0x0
89 0x1000000 0x0 0x0
90 0x0 0x100000>;
91 };
92 };
93};
94
95/include/ "p2020rdb-pc.dtsi"
96/include/ "fsl/p2020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2020rdb-pc_36b.dts b/arch/powerpc/boot/dts/p2020rdb-pc_36b.dts
new file mode 100644
index 000000000000..b5a56ca51cf7
--- /dev/null
+++ b/arch/powerpc/boot/dts/p2020rdb-pc_36b.dts
@@ -0,0 +1,96 @@
1/*
2 * P2020 RDB-PC 36Bit Physical Address Map Device Tree Source
3 *
4 * Copyright 2011 Freescale Semiconductor Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Freescale Semiconductor nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/include/ "fsl/p2020si-pre.dtsi"
36
37/ {
38 model = "fsl,P2020RDB";
39 compatible = "fsl,P2020RDB-PC";
40
41 memory {
42 device_type = "memory";
43 };
44
45 lbc: localbus@fffe05000 {
46 reg = <0xf 0xffe05000 0 0x1000>;
47
48 /* NOR and NAND Flashes */
49 ranges = <0x0 0x0 0xf 0xef000000 0x01000000
50 0x1 0x0 0xf 0xff800000 0x00040000
51 0x2 0x0 0xf 0xffb00000 0x00020000
52 0x3 0x0 0xf 0xffa00000 0x00020000>;
53 };
54
55 soc: soc@fffe00000 {
56 ranges = <0x0 0xf 0xffe00000 0x100000>;
57 };
58
59 pci0: pcie@fffe08000 {
60 reg = <0xf 0xffe08000 0 0x1000>;
61 status = "disabled";
62 };
63
64 pci1: pcie@fffe09000 {
65 reg = <0xf 0xffe09000 0 0x1000>;
66 ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
67 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
68 pcie@0 {
69 ranges = <0x2000000 0x0 0xe0000000
70 0x2000000 0x0 0xe0000000
71 0x0 0x20000000
72
73 0x1000000 0x0 0x0
74 0x1000000 0x0 0x0
75 0x0 0x100000>;
76 };
77 };
78
79 pci2: pcie@fffe0a000 {
80 reg = <0xf 0xffe0a000 0 0x1000>;
81 ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
82 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
83 pcie@0 {
84 ranges = <0x2000000 0x0 0xe0000000
85 0x2000000 0x0 0xe0000000
86 0x0 0x20000000
87
88 0x1000000 0x0 0x0
89 0x1000000 0x0 0x0
90 0x0 0x100000>;
91 };
92 };
93};
94
95/include/ "p2020rdb-pc.dtsi"
96/include/ "fsl/p2020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2020rdb.dts b/arch/powerpc/boot/dts/p2020rdb.dts
index eb8a6aa2bda5..153bc76bb48e 100644
--- a/arch/powerpc/boot/dts/p2020rdb.dts
+++ b/arch/powerpc/boot/dts/p2020rdb.dts
@@ -34,7 +34,7 @@
34 34
35 /* NOR and NAND Flashes */ 35 /* NOR and NAND Flashes */
36 ranges = <0x0 0x0 0x0 0xef000000 0x01000000 36 ranges = <0x0 0x0 0x0 0xef000000 0x01000000
37 0x1 0x0 0x0 0xffa00000 0x00040000 37 0x1 0x0 0x0 0xff800000 0x00040000
38 0x2 0x0 0x0 0xffb00000 0x00020000>; 38 0x2 0x0 0x0 0xffb00000 0x00020000>;
39 39
40 nor@0,0 { 40 nor@0,0 {
@@ -157,7 +157,7 @@
157 #size-cells = <1>; 157 #size-cells = <1>;
158 compatible = "spansion,s25sl12801"; 158 compatible = "spansion,s25sl12801";
159 reg = <0>; 159 reg = <0>;
160 spi-max-frequency = <50000000>; 160 spi-max-frequency = <40000000>;
161 161
162 partition@0 { 162 partition@0 {
163 /* 512KB for u-boot Bootloader Image */ 163 /* 512KB for u-boot Bootloader Image */
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index f090e6d2907e..6761c746048d 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -144,6 +144,7 @@ tmp=$tmpdir/zImage.$$.o
144ksection=.kernel:vmlinux.strip 144ksection=.kernel:vmlinux.strip
145isection=.kernel:initrd 145isection=.kernel:initrd
146link_address='0x400000' 146link_address='0x400000'
147make_space=y
147 148
148case "$platform" in 149case "$platform" in
149pseries) 150pseries)
@@ -210,6 +211,7 @@ ps3)
210 ksection=.kernel:vmlinux.bin 211 ksection=.kernel:vmlinux.bin
211 isection=.kernel:initrd 212 isection=.kernel:initrd
212 link_address='' 213 link_address=''
214 make_space=n
213 pie= 215 pie=
214 ;; 216 ;;
215ep88xc|ep405|ep8248e) 217ep88xc|ep405|ep8248e)
@@ -278,17 +280,19 @@ else
278 rm -f $vmz.$$ 280 rm -f $vmz.$$
279fi 281fi
280 282
281# Round the size to next higher MB limit 283if [ "$make_space" = "y" ]; then
282round_size=$(((strip_size + 0xfffff) & 0xfff00000)) 284 # Round the size to next higher MB limit
285 round_size=$(((strip_size + 0xfffff) & 0xfff00000))
283 286
284round_size=0x$(printf "%x" $round_size) 287 round_size=0x$(printf "%x" $round_size)
285link_addr=$(printf "%d" $link_address) 288 link_addr=$(printf "%d" $link_address)
286 289
287if [ $link_addr -lt $strip_size ]; then 290 if [ $link_addr -lt $strip_size ]; then
288 echo "INFO: Uncompressed kernel (size 0x$(printf "%x\n" $strip_size))" \ 291 echo "INFO: Uncompressed kernel (size 0x$(printf "%x\n" $strip_size))" \
289 "overlaps the address of the wrapper($link_address)" 292 "overlaps the address of the wrapper($link_address)"
290 echo "INFO: Fixing the link_address of wrapper to ($round_size)" 293 echo "INFO: Fixing the link_address of wrapper to ($round_size)"
291 link_address=$round_size 294 link_address=$round_size
295 fi
292fi 296fi
293 297
294vmz="$vmz$gzip" 298vmz="$vmz$gzip"
diff --git a/arch/powerpc/configs/85xx/ge_imp3a_defconfig b/arch/powerpc/configs/85xx/ge_imp3a_defconfig
new file mode 100644
index 000000000000..f8c51a4ab995
--- /dev/null
+++ b/arch/powerpc/configs/85xx/ge_imp3a_defconfig
@@ -0,0 +1,257 @@
1CONFIG_PPC_85xx=y
2CONFIG_SMP=y
3CONFIG_NR_CPUS=2
4CONFIG_EXPERIMENTAL=y
5CONFIG_SYSVIPC=y
6CONFIG_POSIX_MQUEUE=y
7CONFIG_BSD_PROCESS_ACCT=y
8CONFIG_BSD_PROCESS_ACCT_V3=y
9CONFIG_SPARSE_IRQ=y
10CONFIG_IKCONFIG=y
11CONFIG_IKCONFIG_PROC=y
12# CONFIG_UTS_NS is not set
13# CONFIG_IPC_NS is not set
14# CONFIG_USER_NS is not set
15# CONFIG_PID_NS is not set
16# CONFIG_NET_NS is not set
17CONFIG_SYSFS_DEPRECATED=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_RELAY=y
20CONFIG_BLK_DEV_INITRD=y
21CONFIG_PERF_EVENTS=y
22CONFIG_SLAB=y
23CONFIG_MODULES=y
24CONFIG_MODULE_UNLOAD=y
25# CONFIG_BLK_DEV_BSG is not set
26CONFIG_GE_IMP3A=y
27CONFIG_QUICC_ENGINE=y
28CONFIG_QE_GPIO=y
29CONFIG_CPM2=y
30CONFIG_HIGHMEM=y
31CONFIG_HIGH_RES_TIMERS=y
32CONFIG_HZ_1000=y
33CONFIG_PREEMPT=y
34# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
35CONFIG_BINFMT_MISC=m
36CONFIG_MATH_EMULATION=y
37CONFIG_IRQ_ALL_CPUS=y
38CONFIG_FORCE_MAX_ZONEORDER=17
39CONFIG_PCI=y
40CONFIG_PCIEPORTBUS=y
41CONFIG_PCI_MSI=y
42CONFIG_PCCARD=y
43# CONFIG_PCMCIA_LOAD_CIS is not set
44CONFIG_YENTA=y
45CONFIG_NET=y
46CONFIG_PACKET=y
47CONFIG_UNIX=y
48CONFIG_XFRM_USER=m
49CONFIG_NET_KEY=y
50CONFIG_INET=y
51CONFIG_IP_MULTICAST=y
52CONFIG_IP_ADVANCED_ROUTER=y
53CONFIG_IP_MULTIPLE_TABLES=y
54CONFIG_IP_ROUTE_MULTIPATH=y
55CONFIG_IP_ROUTE_VERBOSE=y
56CONFIG_IP_PNP=y
57CONFIG_IP_PNP_DHCP=y
58CONFIG_IP_PNP_BOOTP=y
59CONFIG_IP_PNP_RARP=y
60CONFIG_NET_IPIP=m
61CONFIG_IP_MROUTE=y
62CONFIG_IP_PIMSM_V1=y
63CONFIG_IP_PIMSM_V2=y
64CONFIG_SYN_COOKIES=y
65CONFIG_INET_AH=m
66CONFIG_INET_ESP=m
67CONFIG_INET_IPCOMP=m
68# CONFIG_INET_XFRM_MODE_BEET is not set
69CONFIG_INET6_AH=m
70CONFIG_INET6_IPCOMP=m
71CONFIG_IPV6_TUNNEL=m
72CONFIG_NET_PKTGEN=m
73CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
74CONFIG_MTD=y
75CONFIG_MTD_OF_PARTS=y
76CONFIG_MTD_CHAR=y
77CONFIG_MTD_BLOCK=y
78CONFIG_MTD_CFI=y
79CONFIG_MTD_JEDECPROBE=y
80CONFIG_MTD_CFI_INTELEXT=y
81CONFIG_MTD_CFI_AMDSTD=y
82CONFIG_MTD_PHYSMAP_OF=y
83CONFIG_MTD_NAND=y
84CONFIG_MTD_NAND_FSL_ELBC=y
85CONFIG_PROC_DEVICETREE=y
86CONFIG_BLK_DEV_LOOP=m
87CONFIG_BLK_DEV_CRYPTOLOOP=m
88CONFIG_BLK_DEV_NBD=m
89CONFIG_BLK_DEV_RAM=y
90CONFIG_BLK_DEV_RAM_SIZE=131072
91CONFIG_MISC_DEVICES=y
92CONFIG_DS1682=y
93CONFIG_BLK_DEV_SD=y
94CONFIG_CHR_DEV_ST=y
95CONFIG_BLK_DEV_SR=y
96CONFIG_ATA=y
97CONFIG_SATA_AHCI=y
98CONFIG_SATA_SIL24=y
99# CONFIG_ATA_SFF is not set
100CONFIG_NETDEVICES=y
101CONFIG_BONDING=m
102CONFIG_DUMMY=m
103CONFIG_NETCONSOLE=y
104CONFIG_NETPOLL_TRAP=y
105CONFIG_TUN=m
106# CONFIG_NET_VENDOR_3COM is not set
107CONFIG_FS_ENET=y
108CONFIG_UCC_GETH=y
109CONFIG_GIANFAR=y
110CONFIG_PPP=m
111CONFIG_PPP_BSDCOMP=m
112CONFIG_PPP_DEFLATE=m
113CONFIG_PPP_FILTER=y
114CONFIG_PPP_MULTILINK=y
115CONFIG_PPPOE=m
116CONFIG_PPP_ASYNC=m
117CONFIG_PPP_SYNC_TTY=m
118CONFIG_SLIP=m
119CONFIG_SLIP_COMPRESSED=y
120CONFIG_SLIP_SMART=y
121CONFIG_SLIP_MODE_SLIP6=y
122# CONFIG_INPUT_KEYBOARD is not set
123# CONFIG_INPUT_MOUSE is not set
124# CONFIG_SERIO is not set
125# CONFIG_LEGACY_PTYS is not set
126CONFIG_SERIAL_8250=y
127CONFIG_SERIAL_8250_CONSOLE=y
128CONFIG_SERIAL_8250_NR_UARTS=2
129CONFIG_SERIAL_8250_RUNTIME_UARTS=2
130CONFIG_SERIAL_8250_EXTENDED=y
131CONFIG_SERIAL_8250_MANY_PORTS=y
132CONFIG_SERIAL_8250_DETECT_IRQ=y
133CONFIG_SERIAL_8250_RSA=y
134CONFIG_SERIAL_QE=m
135CONFIG_NVRAM=y
136CONFIG_I2C=y
137CONFIG_I2C_CHARDEV=y
138CONFIG_I2C_CPM=m
139CONFIG_I2C_MPC=y
140CONFIG_GPIO_SYSFS=y
141CONFIG_GPIO_GE_FPGA=y
142CONFIG_SENSORS_LM90=y
143CONFIG_SENSORS_LM92=y
144CONFIG_WATCHDOG=y
145CONFIG_GEF_WDT=y
146CONFIG_VIDEO_OUTPUT_CONTROL=m
147CONFIG_HID_DRAGONRISE=y
148CONFIG_HID_GYRATION=y
149CONFIG_HID_TWINHAN=y
150CONFIG_HID_ORTEK=y
151CONFIG_HID_PANTHERLORD=y
152CONFIG_HID_PETALYNX=y
153CONFIG_HID_SAMSUNG=y
154CONFIG_HID_SONY=y
155CONFIG_HID_SUNPLUS=y
156CONFIG_HID_GREENASIA=y
157CONFIG_HID_SMARTJOYPLUS=y
158CONFIG_HID_TOPSEED=y
159CONFIG_HID_THRUSTMASTER=y
160CONFIG_HID_ZEROPLUS=y
161CONFIG_USB=y
162CONFIG_USB_DEVICEFS=y
163CONFIG_USB_EHCI_HCD=y
164# CONFIG_USB_EHCI_TT_NEWSCHED is not set
165CONFIG_USB_EHCI_FSL=y
166CONFIG_USB_OHCI_HCD=y
167CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
168CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
169CONFIG_USB_STORAGE=y
170CONFIG_EDAC=y
171CONFIG_EDAC_MM_EDAC=y
172CONFIG_EDAC_MPC85XX=y
173CONFIG_RTC_CLASS=y
174# CONFIG_RTC_INTF_PROC is not set
175CONFIG_RTC_DRV_RX8581=y
176CONFIG_DMADEVICES=y
177CONFIG_FSL_DMA=y
178# CONFIG_NET_DMA is not set
179CONFIG_EXT2_FS=y
180CONFIG_EXT2_FS_XATTR=y
181CONFIG_EXT2_FS_POSIX_ACL=y
182CONFIG_EXT3_FS=y
183# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
184CONFIG_EXT3_FS_POSIX_ACL=y
185CONFIG_EXT4_FS=y
186CONFIG_FUSE_FS=y
187CONFIG_ISO9660_FS=y
188CONFIG_JOLIET=y
189CONFIG_ZISOFS=y
190CONFIG_UDF_FS=y
191CONFIG_MSDOS_FS=y
192CONFIG_VFAT_FS=y
193CONFIG_FAT_DEFAULT_CODEPAGE=850
194CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
195CONFIG_NTFS_FS=y
196CONFIG_PROC_KCORE=y
197CONFIG_TMPFS=y
198CONFIG_JFFS2_FS=y
199CONFIG_NFS_FS=y
200CONFIG_NFS_V3=y
201CONFIG_NFS_V4=y
202CONFIG_ROOT_NFS=y
203CONFIG_NFSD=y
204CONFIG_NFSD_V4=y
205CONFIG_CIFS=m
206CONFIG_CIFS_XATTR=y
207CONFIG_CIFS_POSIX=y
208CONFIG_NLS_CODEPAGE_437=y
209CONFIG_NLS_CODEPAGE_737=m
210CONFIG_NLS_CODEPAGE_775=m
211CONFIG_NLS_CODEPAGE_850=y
212CONFIG_NLS_CODEPAGE_852=m
213CONFIG_NLS_CODEPAGE_855=m
214CONFIG_NLS_CODEPAGE_857=m
215CONFIG_NLS_CODEPAGE_860=m
216CONFIG_NLS_CODEPAGE_861=m
217CONFIG_NLS_CODEPAGE_862=m
218CONFIG_NLS_CODEPAGE_863=m
219CONFIG_NLS_CODEPAGE_864=m
220CONFIG_NLS_CODEPAGE_865=m
221CONFIG_NLS_CODEPAGE_866=m
222CONFIG_NLS_CODEPAGE_869=m
223CONFIG_NLS_CODEPAGE_936=m
224CONFIG_NLS_CODEPAGE_950=m
225CONFIG_NLS_CODEPAGE_932=m
226CONFIG_NLS_CODEPAGE_949=m
227CONFIG_NLS_CODEPAGE_874=m
228CONFIG_NLS_ISO8859_8=m
229CONFIG_NLS_CODEPAGE_1250=m
230CONFIG_NLS_CODEPAGE_1251=m
231CONFIG_NLS_ASCII=y
232CONFIG_NLS_ISO8859_1=y
233CONFIG_NLS_ISO8859_2=m
234CONFIG_NLS_ISO8859_3=m
235CONFIG_NLS_ISO8859_4=m
236CONFIG_NLS_ISO8859_5=m
237CONFIG_NLS_ISO8859_6=m
238CONFIG_NLS_ISO8859_7=m
239CONFIG_NLS_ISO8859_9=m
240CONFIG_NLS_ISO8859_13=m
241CONFIG_NLS_ISO8859_14=m
242CONFIG_NLS_ISO8859_15=y
243CONFIG_NLS_KOI8_R=m
244CONFIG_NLS_KOI8_U=m
245CONFIG_NLS_UTF8=y
246CONFIG_CRC_CCITT=y
247CONFIG_CRC_T10DIF=y
248CONFIG_LIBCRC32C=y
249CONFIG_MAGIC_SYSRQ=y
250CONFIG_SYSCTL_SYSCALL_CHECK=y
251CONFIG_CRYPTO_CBC=y
252CONFIG_CRYPTO_MD5=y
253CONFIG_CRYPTO_SHA256=m
254CONFIG_CRYPTO_SHA512=m
255CONFIG_CRYPTO_DES=y
256# CONFIG_CRYPTO_ANSI_CPRNG is not set
257CONFIG_CRYPTO_DEV_TALITOS=y
diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
index d41857a5152d..da731c2fe984 100644
--- a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
+++ b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
@@ -131,6 +131,7 @@ CONFIG_I2C=y
131CONFIG_I2C_CHARDEV=y 131CONFIG_I2C_CHARDEV=y
132CONFIG_I2C_MPC=y 132CONFIG_I2C_MPC=y
133CONFIG_GPIO_SYSFS=y 133CONFIG_GPIO_SYSFS=y
134CONFIG_GPIO_GE_FPGA=y
134CONFIG_SENSORS_LM90=y 135CONFIG_SENSORS_LM90=y
135CONFIG_SENSORS_LM92=y 136CONFIG_SENSORS_LM92=y
136CONFIG_WATCHDOG=y 137CONFIG_WATCHDOG=y
diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
index 38303ec11bcd..2149360a1e62 100644
--- a/arch/powerpc/configs/86xx/gef_sbc310_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
@@ -132,6 +132,7 @@ CONFIG_I2C=y
132CONFIG_I2C_CHARDEV=y 132CONFIG_I2C_CHARDEV=y
133CONFIG_I2C_MPC=y 133CONFIG_I2C_MPC=y
134CONFIG_GPIO_SYSFS=y 134CONFIG_GPIO_SYSFS=y
135CONFIG_GPIO_GE_FPGA=y
135CONFIG_SENSORS_LM90=y 136CONFIG_SENSORS_LM90=y
136CONFIG_SENSORS_LM92=y 137CONFIG_SENSORS_LM92=y
137CONFIG_WATCHDOG=y 138CONFIG_WATCHDOG=y
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
index 98533973d20f..af2e8e1edba6 100644
--- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
@@ -183,6 +183,8 @@ CONFIG_NVRAM=y
183CONFIG_I2C=y 183CONFIG_I2C=y
184CONFIG_I2C_CHARDEV=y 184CONFIG_I2C_CHARDEV=y
185CONFIG_I2C_MPC=y 185CONFIG_I2C_MPC=y
186CONFIG_GPIO_SYSFS=y
187CONFIG_GPIO_GE_FPGA=y
186CONFIG_SENSORS_LM90=y 188CONFIG_SENSORS_LM90=y
187CONFIG_SENSORS_LM92=y 189CONFIG_SENSORS_LM92=y
188CONFIG_WATCHDOG=y 190CONFIG_WATCHDOG=y
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
deleted file mode 100644
index 27c46d679968..000000000000
--- a/arch/powerpc/configs/iseries_defconfig
+++ /dev/null
@@ -1,236 +0,0 @@
1CONFIG_PPC64=y
2CONFIG_SMP=y
3CONFIG_EXPERIMENTAL=y
4CONFIG_SYSVIPC=y
5CONFIG_POSIX_MQUEUE=y
6CONFIG_AUDIT=y
7CONFIG_AUDITSYSCALL=y
8CONFIG_IKCONFIG=y
9CONFIG_IKCONFIG_PROC=y
10CONFIG_BLK_DEV_INITRD=y
11# CONFIG_COMPAT_BRK is not set
12CONFIG_MODULES=y
13CONFIG_MODULE_UNLOAD=y
14CONFIG_MODVERSIONS=y
15CONFIG_MODULE_SRCVERSION_ALL=y
16# CONFIG_PPC_PSERIES is not set
17CONFIG_LPARCFG=y
18CONFIG_PPC_ISERIES=y
19CONFIG_VIODASD=y
20CONFIG_VIOCD=m
21CONFIG_VIOTAPE=m
22# CONFIG_PPC_PMAC is not set
23CONFIG_NO_HZ=y
24CONFIG_HIGH_RES_TIMERS=y
25CONFIG_IRQ_ALL_CPUS=y
26# CONFIG_MIGRATION is not set
27CONFIG_PACKET=y
28CONFIG_UNIX=y
29CONFIG_XFRM_USER=m
30CONFIG_XFRM_SUB_POLICY=y
31CONFIG_NET_KEY=m
32CONFIG_INET=y
33CONFIG_IP_MULTICAST=y
34CONFIG_NET_IPIP=y
35CONFIG_SYN_COOKIES=y
36CONFIG_INET_AH=m
37CONFIG_INET_ESP=m
38CONFIG_INET_IPCOMP=m
39CONFIG_INET_XFRM_MODE_BEET=m
40# CONFIG_INET_LRO is not set
41# CONFIG_IPV6 is not set
42CONFIG_NETFILTER=y
43CONFIG_NETFILTER_NETLINK_QUEUE=m
44CONFIG_NETFILTER_NETLINK_LOG=m
45CONFIG_NF_CONNTRACK=m
46CONFIG_NF_CONNTRACK_EVENTS=y
47# CONFIG_NF_CT_PROTO_SCTP is not set
48CONFIG_NF_CONNTRACK_FTP=m
49CONFIG_NF_CONNTRACK_IRC=m
50CONFIG_NF_CONNTRACK_TFTP=m
51CONFIG_NF_CT_NETLINK=m
52CONFIG_NETFILTER_TPROXY=m
53CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
54CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
55CONFIG_NETFILTER_XT_TARGET_DSCP=m
56CONFIG_NETFILTER_XT_TARGET_MARK=m
57CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
58CONFIG_NETFILTER_XT_TARGET_TPROXY=m
59CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
60CONFIG_NETFILTER_XT_MATCH_COMMENT=m
61CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
62CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
63CONFIG_NETFILTER_XT_MATCH_DSCP=m
64CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
65CONFIG_NETFILTER_XT_MATCH_LENGTH=m
66CONFIG_NETFILTER_XT_MATCH_LIMIT=m
67CONFIG_NETFILTER_XT_MATCH_MAC=m
68CONFIG_NETFILTER_XT_MATCH_MARK=m
69CONFIG_NETFILTER_XT_MATCH_OWNER=m
70CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
71CONFIG_NETFILTER_XT_MATCH_RATEEST=m
72CONFIG_NETFILTER_XT_MATCH_REALM=m
73CONFIG_NETFILTER_XT_MATCH_RECENT=m
74CONFIG_NETFILTER_XT_MATCH_STRING=m
75CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
76CONFIG_NETFILTER_XT_MATCH_TIME=m
77CONFIG_NF_CONNTRACK_IPV4=m
78CONFIG_IP_NF_QUEUE=m
79CONFIG_IP_NF_IPTABLES=m
80CONFIG_IP_NF_MATCH_ADDRTYPE=m
81CONFIG_IP_NF_MATCH_ECN=m
82CONFIG_IP_NF_MATCH_TTL=m
83CONFIG_IP_NF_FILTER=m
84CONFIG_IP_NF_TARGET_REJECT=m
85CONFIG_IP_NF_TARGET_LOG=m
86CONFIG_IP_NF_TARGET_ULOG=m
87CONFIG_NF_NAT=m
88CONFIG_IP_NF_TARGET_MASQUERADE=m
89CONFIG_IP_NF_TARGET_NETMAP=m
90CONFIG_IP_NF_TARGET_REDIRECT=m
91CONFIG_IP_NF_MANGLE=m
92CONFIG_IP_NF_TARGET_CLUSTERIP=m
93CONFIG_IP_NF_TARGET_ECN=m
94CONFIG_IP_NF_TARGET_TTL=m
95CONFIG_IP_NF_RAW=m
96CONFIG_IP_NF_ARPTABLES=m
97CONFIG_IP_NF_ARPFILTER=m
98CONFIG_IP_NF_ARP_MANGLE=m
99CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
100CONFIG_PROC_DEVICETREE=y
101CONFIG_BLK_DEV_LOOP=y
102CONFIG_BLK_DEV_NBD=m
103CONFIG_BLK_DEV_RAM=y
104CONFIG_BLK_DEV_RAM_SIZE=65536
105CONFIG_SCSI=y
106CONFIG_BLK_DEV_SD=y
107CONFIG_CHR_DEV_ST=y
108CONFIG_BLK_DEV_SR=y
109CONFIG_BLK_DEV_SR_VENDOR=y
110CONFIG_CHR_DEV_SG=y
111CONFIG_SCSI_MULTI_LUN=y
112CONFIG_SCSI_CONSTANTS=y
113CONFIG_SCSI_SPI_ATTRS=y
114CONFIG_SCSI_FC_ATTRS=y
115CONFIG_SCSI_SAS_LIBSAS=m
116CONFIG_SCSI_IBMVSCSI=m
117CONFIG_MD=y
118CONFIG_BLK_DEV_MD=y
119CONFIG_MD_LINEAR=y
120CONFIG_MD_RAID0=y
121CONFIG_MD_RAID1=y
122CONFIG_MD_RAID10=m
123CONFIG_MD_MULTIPATH=m
124CONFIG_MD_FAULTY=m
125CONFIG_BLK_DEV_DM=y
126CONFIG_DM_CRYPT=m
127CONFIG_DM_SNAPSHOT=m
128CONFIG_DM_MIRROR=m
129CONFIG_DM_ZERO=m
130CONFIG_NETDEVICES=y
131CONFIG_DUMMY=m
132CONFIG_BONDING=m
133CONFIG_TUN=m
134CONFIG_NET_ETHERNET=y
135CONFIG_NET_PCI=y
136CONFIG_PCNET32=y
137CONFIG_E100=y
138CONFIG_ACENIC=m
139CONFIG_E1000=m
140CONFIG_ISERIES_VETH=y
141CONFIG_PPP=m
142CONFIG_PPP_ASYNC=m
143CONFIG_PPP_SYNC_TTY=m
144CONFIG_PPP_DEFLATE=m
145CONFIG_PPP_BSDCOMP=m
146CONFIG_PPPOE=m
147CONFIG_NETCONSOLE=y
148CONFIG_NETPOLL_TRAP=y
149# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
150# CONFIG_INPUT_KEYBOARD is not set
151# CONFIG_INPUT_MOUSE is not set
152# CONFIG_SERIO is not set
153CONFIG_SERIAL_ICOM=m
154# CONFIG_HW_RANDOM is not set
155CONFIG_GEN_RTC=y
156CONFIG_RAW_DRIVER=y
157# CONFIG_HWMON is not set
158# CONFIG_HID_SUPPORT is not set
159# CONFIG_USB_SUPPORT is not set
160CONFIG_EXT2_FS=y
161CONFIG_EXT2_FS_XATTR=y
162CONFIG_EXT2_FS_POSIX_ACL=y
163CONFIG_EXT2_FS_SECURITY=y
164CONFIG_EXT2_FS_XIP=y
165CONFIG_EXT3_FS=y
166CONFIG_EXT3_FS_POSIX_ACL=y
167CONFIG_EXT3_FS_SECURITY=y
168CONFIG_EXT4_FS=y
169CONFIG_REISERFS_FS=y
170CONFIG_REISERFS_FS_XATTR=y
171CONFIG_REISERFS_FS_POSIX_ACL=y
172CONFIG_REISERFS_FS_SECURITY=y
173CONFIG_JFS_FS=m
174CONFIG_JFS_POSIX_ACL=y
175CONFIG_JFS_SECURITY=y
176CONFIG_XFS_FS=m
177CONFIG_XFS_POSIX_ACL=y
178CONFIG_GFS2_FS=m
179CONFIG_AUTOFS_FS=m
180CONFIG_ISO9660_FS=y
181CONFIG_JOLIET=y
182CONFIG_ZISOFS=y
183CONFIG_UDF_FS=m
184CONFIG_MSDOS_FS=y
185CONFIG_VFAT_FS=y
186CONFIG_PROC_KCORE=y
187CONFIG_TMPFS=y
188CONFIG_TMPFS_POSIX_ACL=y
189CONFIG_CRAMFS=y
190CONFIG_NFS_FS=y
191CONFIG_NFS_V3=y
192CONFIG_NFS_V3_ACL=y
193CONFIG_NFS_V4=y
194CONFIG_NFSD=m
195CONFIG_NFSD_V3_ACL=y
196CONFIG_NFSD_V4=y
197CONFIG_RPCSEC_GSS_SPKM3=m
198CONFIG_CIFS=m
199CONFIG_CIFS_XATTR=y
200CONFIG_CIFS_POSIX=y
201CONFIG_NLS_CODEPAGE_437=y
202CONFIG_NLS_ASCII=y
203CONFIG_NLS_ISO8859_1=y
204CONFIG_DLM=m
205CONFIG_CRC_T10DIF=y
206CONFIG_MAGIC_SYSRQ=y
207CONFIG_DEBUG_FS=y
208CONFIG_DEBUG_KERNEL=y
209# CONFIG_RCU_CPU_STALL_DETECTOR is not set
210CONFIG_LATENCYTOP=y
211CONFIG_SYSCTL_SYSCALL_CHECK=y
212CONFIG_DEBUG_STACKOVERFLOW=y
213CONFIG_DEBUG_STACK_USAGE=y
214CONFIG_CRYPTO_NULL=m
215CONFIG_CRYPTO_TEST=m
216CONFIG_CRYPTO_ECB=m
217CONFIG_CRYPTO_PCBC=m
218CONFIG_CRYPTO_HMAC=y
219CONFIG_CRYPTO_MD4=m
220CONFIG_CRYPTO_MICHAEL_MIC=m
221CONFIG_CRYPTO_SHA256=m
222CONFIG_CRYPTO_SHA512=m
223CONFIG_CRYPTO_TGR192=m
224CONFIG_CRYPTO_WP512=m
225CONFIG_CRYPTO_AES=m
226CONFIG_CRYPTO_ANUBIS=m
227CONFIG_CRYPTO_ARC4=m
228CONFIG_CRYPTO_BLOWFISH=m
229CONFIG_CRYPTO_CAST6=m
230CONFIG_CRYPTO_KHAZAD=m
231CONFIG_CRYPTO_SEED=m
232CONFIG_CRYPTO_SERPENT=m
233CONFIG_CRYPTO_TEA=m
234CONFIG_CRYPTO_TWOFISH=m
235# CONFIG_CRYPTO_ANSI_CPRNG is not set
236# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 2a1320fb2723..6640a35bebb7 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,8 +1,8 @@
1CONFIG_EXPERIMENTAL=y 1CONFIG_EXPERIMENTAL=y
2CONFIG_SYSVIPC=y 2CONFIG_SYSVIPC=y
3CONFIG_SPARSE_IRQ=y
3CONFIG_LOG_BUF_SHIFT=14 4CONFIG_LOG_BUF_SHIFT=14
4CONFIG_BLK_DEV_INITRD=y 5CONFIG_BLK_DEV_INITRD=y
5# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
6CONFIG_MODULES=y 6CONFIG_MODULES=y
7CONFIG_MODULE_UNLOAD=y 7CONFIG_MODULE_UNLOAD=y
8# CONFIG_BLK_DEV_BSG is not set 8# CONFIG_BLK_DEV_BSG is not set
@@ -13,15 +13,12 @@ CONFIG_PPC_EFIKA=y
13CONFIG_PPC_LITE5200=y 13CONFIG_PPC_LITE5200=y
14CONFIG_PPC_MEDIA5200=y 14CONFIG_PPC_MEDIA5200=y
15CONFIG_PPC_MPC5200_BUGFIX=y 15CONFIG_PPC_MPC5200_BUGFIX=y
16CONFIG_PPC_MPC5200_GPIO=y
17CONFIG_PPC_MPC5200_LPBFIFO=m 16CONFIG_PPC_MPC5200_LPBFIFO=m
18# CONFIG_PPC_PMAC is not set 17# CONFIG_PPC_PMAC is not set
19CONFIG_PPC_BESTCOMM=y 18CONFIG_PPC_BESTCOMM=y
20CONFIG_SIMPLE_GPIO=y 19CONFIG_SIMPLE_GPIO=y
21CONFIG_NO_HZ=y 20CONFIG_NO_HZ=y
22CONFIG_HIGH_RES_TIMERS=y 21CONFIG_HIGH_RES_TIMERS=y
23CONFIG_SPARSE_IRQ=y
24CONFIG_PM=y
25CONFIG_NET=y 22CONFIG_NET=y
26CONFIG_PACKET=y 23CONFIG_PACKET=y
27CONFIG_UNIX=y 24CONFIG_UNIX=y
@@ -36,23 +33,20 @@ CONFIG_SYN_COOKIES=y
36# CONFIG_IPV6 is not set 33# CONFIG_IPV6 is not set
37CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" 34CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
38CONFIG_MTD=y 35CONFIG_MTD=y
39CONFIG_MTD_CONCAT=y
40CONFIG_MTD_PARTITIONS=y
41CONFIG_MTD_CMDLINE_PARTS=y 36CONFIG_MTD_CMDLINE_PARTS=y
42CONFIG_MTD_OF_PARTS=y 37CONFIG_MTD_OF_PARTS=y
43CONFIG_MTD_CHAR=y 38CONFIG_MTD_CHAR=y
44CONFIG_MTD_BLOCK=y 39CONFIG_MTD_BLOCK=y
45CONFIG_MTD_CFI=y 40CONFIG_MTD_CFI=y
46CONFIG_MTD_CFI_AMDSTD=y 41CONFIG_MTD_CFI_AMDSTD=y
47CONFIG_MTD_RAM=y
48CONFIG_MTD_ROM=y 42CONFIG_MTD_ROM=y
49CONFIG_MTD_PHYSMAP_OF=y 43CONFIG_MTD_PHYSMAP_OF=y
44CONFIG_MTD_PLATRAM=y
50CONFIG_MTD_UBI=m 45CONFIG_MTD_UBI=m
51CONFIG_PROC_DEVICETREE=y 46CONFIG_PROC_DEVICETREE=y
52CONFIG_BLK_DEV_LOOP=y 47CONFIG_BLK_DEV_LOOP=y
53CONFIG_BLK_DEV_RAM=y 48CONFIG_BLK_DEV_RAM=y
54CONFIG_BLK_DEV_RAM_SIZE=32768 49CONFIG_BLK_DEV_RAM_SIZE=32768
55CONFIG_MISC_DEVICES=y
56CONFIG_EEPROM_AT24=y 50CONFIG_EEPROM_AT24=y
57CONFIG_SCSI_TGT=y 51CONFIG_SCSI_TGT=y
58CONFIG_BLK_DEV_SD=y 52CONFIG_BLK_DEV_SD=y
@@ -61,11 +55,10 @@ CONFIG_ATA=y
61CONFIG_PATA_MPC52xx=y 55CONFIG_PATA_MPC52xx=y
62CONFIG_PATA_PLATFORM=y 56CONFIG_PATA_PLATFORM=y
63CONFIG_NETDEVICES=y 57CONFIG_NETDEVICES=y
64CONFIG_LXT_PHY=y
65CONFIG_NET_ETHERNET=y
66CONFIG_FEC_MPC52xx=y 58CONFIG_FEC_MPC52xx=y
67# CONFIG_NETDEV_1000 is not set 59CONFIG_AMD_PHY=y
68# CONFIG_NETDEV_10000 is not set 60CONFIG_LXT_PHY=y
61CONFIG_FIXED_PHY=y
69# CONFIG_INPUT_KEYBOARD is not set 62# CONFIG_INPUT_KEYBOARD is not set
70# CONFIG_INPUT_MOUSE is not set 63# CONFIG_INPUT_MOUSE is not set
71# CONFIG_SERIO is not set 64# CONFIG_SERIO is not set
@@ -80,11 +73,17 @@ CONFIG_SPI_GPIO=m
80CONFIG_SPI_MPC52xx=m 73CONFIG_SPI_MPC52xx=m
81CONFIG_SPI_MPC52xx_PSC=m 74CONFIG_SPI_MPC52xx_PSC=m
82CONFIG_SPI_SPIDEV=m 75CONFIG_SPI_SPIDEV=m
76CONFIG_GPIO_SYSFS=y
77CONFIG_SENSORS_LM80=y
78CONFIG_SENSORS_LM87=m
83CONFIG_WATCHDOG=y 79CONFIG_WATCHDOG=y
80CONFIG_MFD_SM501=m
84CONFIG_DRM=y 81CONFIG_DRM=y
85CONFIG_VIDEO_OUTPUT_CONTROL=y 82CONFIG_VIDEO_OUTPUT_CONTROL=y
86CONFIG_FB=y 83CONFIG_FB=y
84CONFIG_FB_FOREIGN_ENDIAN=y
87CONFIG_FB_RADEON=y 85CONFIG_FB_RADEON=y
86CONFIG_FB_SM501=m
88# CONFIG_VGA_CONSOLE is not set 87# CONFIG_VGA_CONSOLE is not set
89CONFIG_FRAMEBUFFER_CONSOLE=y 88CONFIG_FRAMEBUFFER_CONSOLE=y
90CONFIG_LOGO=y 89CONFIG_LOGO=y
@@ -124,10 +123,11 @@ CONFIG_USB_STORAGE=y
124CONFIG_NEW_LEDS=y 123CONFIG_NEW_LEDS=y
125CONFIG_RTC_CLASS=y 124CONFIG_RTC_CLASS=y
126CONFIG_RTC_DRV_DS1307=y 125CONFIG_RTC_DRV_DS1307=y
126CONFIG_RTC_DRV_DS1374=y
127CONFIG_RTC_DRV_PCF8563=m
127CONFIG_EXT2_FS=y 128CONFIG_EXT2_FS=y
128CONFIG_EXT3_FS=y 129CONFIG_EXT3_FS=y
129# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 130# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
130CONFIG_INOTIFY=y
131CONFIG_MSDOS_FS=y 131CONFIG_MSDOS_FS=y
132CONFIG_VFAT_FS=y 132CONFIG_VFAT_FS=y
133CONFIG_PROC_KCORE=y 133CONFIG_PROC_KCORE=y
@@ -145,5 +145,4 @@ CONFIG_PRINTK_TIME=y
145CONFIG_DEBUG_KERNEL=y 145CONFIG_DEBUG_KERNEL=y
146CONFIG_DETECT_HUNG_TASK=y 146CONFIG_DETECT_HUNG_TASK=y
147CONFIG_DEBUG_INFO=y 147CONFIG_DEBUG_INFO=y
148# CONFIG_RCU_CPU_STALL_DETECTOR is not set
149# CONFIG_CRYPTO_ANSI_CPRNG is not set 148# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index f37a2ab48881..5fb0c8a94811 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1,4 +1,5 @@
1CONFIG_PPC_85xx=y 1CONFIG_PPC_85xx=y
2CONFIG_PHYS_64BIT=y
2CONFIG_EXPERIMENTAL=y 3CONFIG_EXPERIMENTAL=y
3CONFIG_SYSVIPC=y 4CONFIG_SYSVIPC=y
4CONFIG_POSIX_MQUEUE=y 5CONFIG_POSIX_MQUEUE=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index abdcd317cda7..fb51bc90edd2 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -1,4 +1,5 @@
1CONFIG_PPC_85xx=y 1CONFIG_PPC_85xx=y
2CONFIG_PHYS_64BIT=y
2CONFIG_SMP=y 3CONFIG_SMP=y
3CONFIG_NR_CPUS=8 4CONFIG_NR_CPUS=8
4CONFIG_EXPERIMENTAL=y 5CONFIG_EXPERIMENTAL=y
diff --git a/arch/powerpc/include/asm/abs_addr.h b/arch/powerpc/include/asm/abs_addr.h
index 5ab0b71531be..9d92ba04b033 100644
--- a/arch/powerpc/include/asm/abs_addr.h
+++ b/arch/powerpc/include/asm/abs_addr.h
@@ -17,7 +17,6 @@
17#include <asm/types.h> 17#include <asm/types.h>
18#include <asm/page.h> 18#include <asm/page.h>
19#include <asm/prom.h> 19#include <asm/prom.h>
20#include <asm/firmware.h>
21 20
22struct mschunks_map { 21struct mschunks_map {
23 unsigned long num_chunks; 22 unsigned long num_chunks;
@@ -46,30 +45,12 @@ static inline unsigned long addr_to_chunk(unsigned long addr)
46 45
47static inline unsigned long phys_to_abs(unsigned long pa) 46static inline unsigned long phys_to_abs(unsigned long pa)
48{ 47{
49 unsigned long chunk; 48 return pa;
50
51 /* This is a no-op on non-iSeries */
52 if (!firmware_has_feature(FW_FEATURE_ISERIES))
53 return pa;
54
55 chunk = addr_to_chunk(pa);
56
57 if (chunk < mschunks_map.num_chunks)
58 chunk = mschunks_map.mapping[chunk];
59
60 return chunk_to_addr(chunk) + (pa & MSCHUNKS_OFFSET_MASK);
61} 49}
62 50
63/* Convenience macros */ 51/* Convenience macros */
64#define virt_to_abs(va) phys_to_abs(__pa(va)) 52#define virt_to_abs(va) phys_to_abs(__pa(va))
65#define abs_to_virt(aa) __va(aa) 53#define abs_to_virt(aa) __va(aa)
66 54
67/*
68 * Converts Virtual Address to Real Address for
69 * Legacy iSeries Hypervisor calls
70 */
71#define iseries_hv_addr(virtaddr) \
72 (0x8000000000000000UL | virt_to_abs(virtaddr))
73
74#endif /* __KERNEL__ */ 55#endif /* __KERNEL__ */
75#endif /* _ASM_POWERPC_ABS_ADDR_H */ 56#endif /* _ASM_POWERPC_ABS_ADDR_H */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 02e41b53488d..14174e838ad9 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -212,6 +212,36 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
212 return t; 212 return t;
213} 213}
214 214
215/**
216 * atomic_inc_not_zero - increment unless the number is zero
217 * @v: pointer of type atomic_t
218 *
219 * Atomically increments @v by 1, so long as @v is non-zero.
220 * Returns non-zero if @v was non-zero, and zero otherwise.
221 */
222static __inline__ int atomic_inc_not_zero(atomic_t *v)
223{
224 int t1, t2;
225
226 __asm__ __volatile__ (
227 PPC_ATOMIC_ENTRY_BARRIER
228"1: lwarx %0,0,%2 # atomic_inc_not_zero\n\
229 cmpwi 0,%0,0\n\
230 beq- 2f\n\
231 addic %1,%0,1\n"
232 PPC405_ERR77(0,%2)
233" stwcx. %1,0,%2\n\
234 bne- 1b\n"
235 PPC_ATOMIC_EXIT_BARRIER
236 "\n\
2372:"
238 : "=&r" (t1), "=&r" (t2)
239 : "r" (&v->counter)
240 : "cc", "xer", "memory");
241
242 return t1;
243}
244#define atomic_inc_not_zero(v) atomic_inc_not_zero((v))
215 245
216#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) 246#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
217#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) 247#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
@@ -467,7 +497,34 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
467 return t != u; 497 return t != u;
468} 498}
469 499
470#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) 500/**
501 * atomic_inc64_not_zero - increment unless the number is zero
502 * @v: pointer of type atomic64_t
503 *
504 * Atomically increments @v by 1, so long as @v is non-zero.
505 * Returns non-zero if @v was non-zero, and zero otherwise.
506 */
507static __inline__ long atomic64_inc_not_zero(atomic64_t *v)
508{
509 long t1, t2;
510
511 __asm__ __volatile__ (
512 PPC_ATOMIC_ENTRY_BARRIER
513"1: ldarx %0,0,%2 # atomic64_inc_not_zero\n\
514 cmpdi 0,%0,0\n\
515 beq- 2f\n\
516 addic %1,%0,1\n\
517 stdcx. %1,0,%2\n\
518 bne- 1b\n"
519 PPC_ATOMIC_EXIT_BARRIER
520 "\n\
5212:"
522 : "=&r" (t1), "=&r" (t2)
523 : "r" (&v->counter)
524 : "cc", "xer", "memory");
525
526 return t1;
527}
471 528
472#endif /* __powerpc64__ */ 529#endif /* __powerpc64__ */
473 530
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index ad55a1ccb9fb..b9219e99bd2a 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -390,6 +390,10 @@ extern const char *powerpc_base_platform;
390 CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ 390 CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
391 CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ 391 CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
392 CPU_FTR_DEBUG_LVL_EXC) 392 CPU_FTR_DEBUG_LVL_EXC)
393#define CPU_FTRS_E6500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
394 CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
395 CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
396 CPU_FTR_DEBUG_LVL_EXC)
393#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) 397#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
394 398
395/* 64-bit CPUs */ 399/* 64-bit CPUs */
@@ -442,7 +446,7 @@ extern const char *powerpc_base_platform;
442 446
443#ifdef __powerpc64__ 447#ifdef __powerpc64__
444#ifdef CONFIG_PPC_BOOK3E 448#ifdef CONFIG_PPC_BOOK3E
445#define CPU_FTRS_POSSIBLE (CPU_FTRS_E5500 | CPU_FTRS_A2) 449#define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2)
446#else 450#else
447#define CPU_FTRS_POSSIBLE \ 451#define CPU_FTRS_POSSIBLE \
448 (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ 452 (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
@@ -483,7 +487,7 @@ enum {
483#endif 487#endif
484#ifdef CONFIG_E500 488#ifdef CONFIG_E500
485 CPU_FTRS_E500 | CPU_FTRS_E500_2 | CPU_FTRS_E500MC | 489 CPU_FTRS_E500 | CPU_FTRS_E500_2 | CPU_FTRS_E500MC |
486 CPU_FTRS_E5500 | 490 CPU_FTRS_E5500 | CPU_FTRS_E6500 |
487#endif 491#endif
488 0, 492 0,
489}; 493};
@@ -491,7 +495,7 @@ enum {
491 495
492#ifdef __powerpc64__ 496#ifdef __powerpc64__
493#ifdef CONFIG_PPC_BOOK3E 497#ifdef CONFIG_PPC_BOOK3E
494#define CPU_FTRS_ALWAYS (CPU_FTRS_E5500 & CPU_FTRS_A2) 498#define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2)
495#else 499#else
496#define CPU_FTRS_ALWAYS \ 500#define CPU_FTRS_ALWAYS \
497 (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \ 501 (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
@@ -528,7 +532,7 @@ enum {
528#endif 532#endif
529#ifdef CONFIG_E500 533#ifdef CONFIG_E500
530 CPU_FTRS_E500 & CPU_FTRS_E500_2 & CPU_FTRS_E500MC & 534 CPU_FTRS_E500 & CPU_FTRS_E500_2 & CPU_FTRS_E500MC &
531 CPU_FTRS_E5500 & 535 CPU_FTRS_E5500 & CPU_FTRS_E6500 &
532#endif 536#endif
533 CPU_FTRS_POSSIBLE, 537 CPU_FTRS_POSSIBLE,
534}; 538};
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
index d57c08acedfc..63d5ca49cece 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -31,6 +31,9 @@ struct dev_archdata {
31#ifdef CONFIG_SWIOTLB 31#ifdef CONFIG_SWIOTLB
32 dma_addr_t max_direct_dma_addr; 32 dma_addr_t max_direct_dma_addr;
33#endif 33#endif
34#ifdef CONFIG_EEH
35 struct eeh_dev *edev;
36#endif
34}; 37};
35 38
36struct pdev_archdata { 39struct pdev_archdata {
diff --git a/arch/powerpc/include/asm/dma.h b/arch/powerpc/include/asm/dma.h
index a7e06e25c708..adadb9943610 100644
--- a/arch/powerpc/include/asm/dma.h
+++ b/arch/powerpc/include/asm/dma.h
@@ -34,8 +34,6 @@
34/* Doesn't really apply... */ 34/* Doesn't really apply... */
35#define MAX_DMA_ADDRESS (~0UL) 35#define MAX_DMA_ADDRESS (~0UL)
36 36
37#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
38
39#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER 37#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
40#define dma_outb outb_p 38#define dma_outb outb_p
41#else 39#else
@@ -354,7 +352,5 @@ extern int isa_dma_bridge_buggy;
354#define isa_dma_bridge_buggy (0) 352#define isa_dma_bridge_buggy (0)
355#endif 353#endif
356 354
357#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
358
359#endif /* __KERNEL__ */ 355#endif /* __KERNEL__ */
360#endif /* _ASM_POWERPC_DMA_H */ 356#endif /* _ASM_POWERPC_DMA_H */
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 66ea9b8b95c5..d60f99814ffb 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * eeh.h
3 * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. 2 * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation.
3 * Copyright 2001-2012 IBM Corporation.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -31,44 +31,105 @@ struct device_node;
31 31
32#ifdef CONFIG_EEH 32#ifdef CONFIG_EEH
33 33
34extern int eeh_subsystem_enabled; 34/*
35 * The struct is used to trace EEH state for the associated
36 * PCI device node or PCI device. In future, it might
37 * represent PE as well so that the EEH device to form
38 * another tree except the currently existing tree of PCI
39 * buses and PCI devices
40 */
41#define EEH_MODE_SUPPORTED (1<<0) /* EEH supported on the device */
42#define EEH_MODE_NOCHECK (1<<1) /* EEH check should be skipped */
43#define EEH_MODE_ISOLATED (1<<2) /* The device has been isolated */
44#define EEH_MODE_RECOVERING (1<<3) /* Recovering the device */
45#define EEH_MODE_IRQ_DISABLED (1<<4) /* Interrupt disabled */
46
47struct eeh_dev {
48 int mode; /* EEH mode */
49 int class_code; /* Class code of the device */
50 int config_addr; /* Config address */
51 int pe_config_addr; /* PE config address */
52 int check_count; /* Times of ignored error */
53 int freeze_count; /* Times of froze up */
54 int false_positives; /* Times of reported #ff's */
55 u32 config_space[16]; /* Saved PCI config space */
56 struct pci_controller *phb; /* Associated PHB */
57 struct device_node *dn; /* Associated device node */
58 struct pci_dev *pdev; /* Associated PCI device */
59};
60
61static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev)
62{
63 return edev->dn;
64}
65
66static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
67{
68 return edev->pdev;
69}
35 70
36/* Values for eeh_mode bits in device_node */ 71/*
37#define EEH_MODE_SUPPORTED (1<<0) 72 * The struct is used to trace the registered EEH operation
38#define EEH_MODE_NOCHECK (1<<1) 73 * callback functions. Actually, those operation callback
39#define EEH_MODE_ISOLATED (1<<2) 74 * functions are heavily platform dependent. That means the
40#define EEH_MODE_RECOVERING (1<<3) 75 * platform should register its own EEH operation callback
41#define EEH_MODE_IRQ_DISABLED (1<<4) 76 * functions before any EEH further operations.
77 */
78#define EEH_OPT_DISABLE 0 /* EEH disable */
79#define EEH_OPT_ENABLE 1 /* EEH enable */
80#define EEH_OPT_THAW_MMIO 2 /* MMIO enable */
81#define EEH_OPT_THAW_DMA 3 /* DMA enable */
82#define EEH_STATE_UNAVAILABLE (1 << 0) /* State unavailable */
83#define EEH_STATE_NOT_SUPPORT (1 << 1) /* EEH not supported */
84#define EEH_STATE_RESET_ACTIVE (1 << 2) /* Active reset */
85#define EEH_STATE_MMIO_ACTIVE (1 << 3) /* Active MMIO */
86#define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */
87#define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */
88#define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */
89#define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */
90#define EEH_RESET_HOT 1 /* Hot reset */
91#define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */
92#define EEH_LOG_TEMP 1 /* EEH temporary error log */
93#define EEH_LOG_PERM 2 /* EEH permanent error log */
94
95struct eeh_ops {
96 char *name;
97 int (*init)(void);
98 int (*set_option)(struct device_node *dn, int option);
99 int (*get_pe_addr)(struct device_node *dn);
100 int (*get_state)(struct device_node *dn, int *state);
101 int (*reset)(struct device_node *dn, int option);
102 int (*wait_state)(struct device_node *dn, int max_wait);
103 int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len);
104 int (*configure_bridge)(struct device_node *dn);
105 int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
106 int (*write_config)(struct device_node *dn, int where, int size, u32 val);
107};
108
109extern struct eeh_ops *eeh_ops;
110extern int eeh_subsystem_enabled;
42 111
43/* Max number of EEH freezes allowed before we consider the device 112/*
44 * to be permanently disabled. */ 113 * Max number of EEH freezes allowed before we consider the device
114 * to be permanently disabled.
115 */
45#define EEH_MAX_ALLOWED_FREEZES 5 116#define EEH_MAX_ALLOWED_FREEZES 5
46 117
118void * __devinit eeh_dev_init(struct device_node *dn, void *data);
119void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);
120void __init eeh_dev_phb_init(void);
47void __init eeh_init(void); 121void __init eeh_init(void);
122#ifdef CONFIG_PPC_PSERIES
123int __init eeh_pseries_init(void);
124#endif
125int __init eeh_ops_register(struct eeh_ops *ops);
126int __exit eeh_ops_unregister(const char *name);
48unsigned long eeh_check_failure(const volatile void __iomem *token, 127unsigned long eeh_check_failure(const volatile void __iomem *token,
49 unsigned long val); 128 unsigned long val);
50int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); 129int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);
51void __init pci_addr_cache_build(void); 130void __init pci_addr_cache_build(void);
52
53/**
54 * eeh_add_device_early
55 * eeh_add_device_late
56 *
57 * Perform eeh initialization for devices added after boot.
58 * Call eeh_add_device_early before doing any i/o to the
59 * device (including config space i/o). Call eeh_add_device_late
60 * to finish the eeh setup for this device.
61 */
62void eeh_add_device_tree_early(struct device_node *); 131void eeh_add_device_tree_early(struct device_node *);
63void eeh_add_device_tree_late(struct pci_bus *); 132void eeh_add_device_tree_late(struct pci_bus *);
64
65/**
66 * eeh_remove_device_recursive - undo EEH for device & children.
67 * @dev: pci device to be removed
68 *
69 * As above, this removes the device; it also removes child
70 * pci devices as well.
71 */
72void eeh_remove_bus_device(struct pci_dev *); 133void eeh_remove_bus_device(struct pci_dev *);
73 134
74/** 135/**
@@ -87,8 +148,25 @@ void eeh_remove_bus_device(struct pci_dev *);
87#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8)) 148#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8))
88 149
89#else /* !CONFIG_EEH */ 150#else /* !CONFIG_EEH */
151
152static inline void *eeh_dev_init(struct device_node *dn, void *data)
153{
154 return NULL;
155}
156
157static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
158
159static inline void eeh_dev_phb_init(void) { }
160
90static inline void eeh_init(void) { } 161static inline void eeh_init(void) { }
91 162
163#ifdef CONFIG_PPC_PSERIES
164static inline int eeh_pseries_init(void)
165{
166 return 0;
167}
168#endif /* CONFIG_PPC_PSERIES */
169
92static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) 170static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
93{ 171{
94 return val; 172 return val;
diff --git a/arch/powerpc/include/asm/eeh_event.h b/arch/powerpc/include/asm/eeh_event.h
index cc3cb04539ac..c68b012b7797 100644
--- a/arch/powerpc/include/asm/eeh_event.h
+++ b/arch/powerpc/include/asm/eeh_event.h
@@ -1,6 +1,4 @@
1/* 1/*
2 * eeh_event.h
3 *
4 * This program is free software; you can redistribute it and/or modify 2 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 3 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or 4 * the Free Software Foundation; either version 2 of the License, or
@@ -22,32 +20,19 @@
22#define ASM_POWERPC_EEH_EVENT_H 20#define ASM_POWERPC_EEH_EVENT_H
23#ifdef __KERNEL__ 21#ifdef __KERNEL__
24 22
25/** EEH event -- structure holding pci controller data that describes 23/*
26 * a change in the isolation status of a PCI slot. A pointer 24 * structure holding pci controller data that describes a
27 * to this struct is passed as the data pointer in a notify callback. 25 * change in the isolation status of a PCI slot. A pointer
26 * to this struct is passed as the data pointer in a notify
27 * callback.
28 */ 28 */
29struct eeh_event { 29struct eeh_event {
30 struct list_head list; 30 struct list_head list; /* to form event queue */
31 struct device_node *dn; /* struct device node */ 31 struct eeh_dev *edev; /* EEH device */
32 struct pci_dev *dev; /* affected device */
33}; 32};
34 33
35/** 34int eeh_send_failure_event(struct eeh_dev *edev);
36 * eeh_send_failure_event - generate a PCI error event 35struct eeh_dev *handle_eeh_events(struct eeh_event *);
37 * @dev pci device
38 *
39 * This routine builds a PCI error event which will be delivered
40 * to all listeners on the eeh_notifier_chain.
41 *
42 * This routine can be called within an interrupt context;
43 * the actual event will be delivered in a normal context
44 * (from a workqueue).
45 */
46int eeh_send_failure_event (struct device_node *dn,
47 struct pci_dev *dev);
48
49/* Main recovery function */
50struct pci_dn * handle_eeh_events (struct eeh_event *);
51 36
52#endif /* __KERNEL__ */ 37#endif /* __KERNEL__ */
53#endif /* ASM_POWERPC_EEH_EVENT_H */ 38#endif /* ASM_POWERPC_EEH_EVENT_H */
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 8057f4f6980f..548da3aa0a30 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -232,23 +232,30 @@ label##_hv: \
232 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ 232 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
233 EXC_HV, KVMTEST, vec) 233 EXC_HV, KVMTEST, vec)
234 234
235#define __SOFTEN_TEST(h) \ 235/* This associate vector numbers with bits in paca->irq_happened */
236#define SOFTEN_VALUE_0x500 PACA_IRQ_EE
237#define SOFTEN_VALUE_0x502 PACA_IRQ_EE
238#define SOFTEN_VALUE_0x900 PACA_IRQ_DEC
239#define SOFTEN_VALUE_0x982 PACA_IRQ_DEC
240
241#define __SOFTEN_TEST(h, vec) \
236 lbz r10,PACASOFTIRQEN(r13); \ 242 lbz r10,PACASOFTIRQEN(r13); \
237 cmpwi r10,0; \ 243 cmpwi r10,0; \
244 li r10,SOFTEN_VALUE_##vec; \
238 beq masked_##h##interrupt 245 beq masked_##h##interrupt
239#define _SOFTEN_TEST(h) __SOFTEN_TEST(h) 246#define _SOFTEN_TEST(h, vec) __SOFTEN_TEST(h, vec)
240 247
241#define SOFTEN_TEST_PR(vec) \ 248#define SOFTEN_TEST_PR(vec) \
242 KVMTEST_PR(vec); \ 249 KVMTEST_PR(vec); \
243 _SOFTEN_TEST(EXC_STD) 250 _SOFTEN_TEST(EXC_STD, vec)
244 251
245#define SOFTEN_TEST_HV(vec) \ 252#define SOFTEN_TEST_HV(vec) \
246 KVMTEST(vec); \ 253 KVMTEST(vec); \
247 _SOFTEN_TEST(EXC_HV) 254 _SOFTEN_TEST(EXC_HV, vec)
248 255
249#define SOFTEN_TEST_HV_201(vec) \ 256#define SOFTEN_TEST_HV_201(vec) \
250 KVMTEST(vec); \ 257 KVMTEST(vec); \
251 _SOFTEN_TEST(EXC_STD) 258 _SOFTEN_TEST(EXC_STD, vec)
252 259
253#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ 260#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \
254 HMT_MEDIUM; \ 261 HMT_MEDIUM; \
@@ -272,73 +279,55 @@ label##_hv: \
272 _MASKABLE_EXCEPTION_PSERIES(vec, label, \ 279 _MASKABLE_EXCEPTION_PSERIES(vec, label, \
273 EXC_HV, SOFTEN_TEST_HV) 280 EXC_HV, SOFTEN_TEST_HV)
274 281
275#ifdef CONFIG_PPC_ISERIES 282/*
276#define DISABLE_INTS \ 283 * Our exception common code can be passed various "additions"
277 li r11,0; \ 284 * to specify the behaviour of interrupts, whether to kick the
278 stb r11,PACASOFTIRQEN(r13); \ 285 * runlatch, etc...
279BEGIN_FW_FTR_SECTION; \ 286 */
280 stb r11,PACAHARDIRQEN(r13); \ 287
281END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ 288/* Exception addition: Hard disable interrupts */
282 TRACE_DISABLE_INTS; \ 289#define DISABLE_INTS SOFT_DISABLE_INTS(r10,r11)
283BEGIN_FW_FTR_SECTION; \
284 mfmsr r10; \
285 ori r10,r10,MSR_EE; \
286 mtmsrd r10,1; \
287END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
288#else
289#define DISABLE_INTS \
290 li r11,0; \
291 stb r11,PACASOFTIRQEN(r13); \
292 stb r11,PACAHARDIRQEN(r13); \
293 TRACE_DISABLE_INTS
294#endif /* CONFIG_PPC_ISERIES */
295 290
291/* Exception addition: Keep interrupt state */
296#define ENABLE_INTS \ 292#define ENABLE_INTS \
293 ld r11,PACAKMSR(r13); \
297 ld r12,_MSR(r1); \ 294 ld r12,_MSR(r1); \
298 mfmsr r11; \
299 rlwimi r11,r12,0,MSR_EE; \ 295 rlwimi r11,r12,0,MSR_EE; \
300 mtmsrd r11,1 296 mtmsrd r11,1
301 297
302#define STD_EXCEPTION_COMMON(trap, label, hdlr) \ 298#define ADD_NVGPRS \
303 .align 7; \ 299 bl .save_nvgprs
304 .globl label##_common; \ 300
305label##_common: \ 301#define RUNLATCH_ON \
306 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ 302BEGIN_FTR_SECTION \
307 DISABLE_INTS; \ 303 clrrdi r3,r1,THREAD_SHIFT; \
308 bl .save_nvgprs; \ 304 ld r4,TI_LOCAL_FLAGS(r3); \
309 addi r3,r1,STACK_FRAME_OVERHEAD; \ 305 andi. r0,r4,_TLF_RUNLATCH; \
310 bl hdlr; \ 306 beql ppc64_runlatch_on_trampoline; \
311 b .ret_from_except 307END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
308
309#define EXCEPTION_COMMON(trap, label, hdlr, ret, additions) \
310 .align 7; \
311 .globl label##_common; \
312label##_common: \
313 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
314 additions; \
315 addi r3,r1,STACK_FRAME_OVERHEAD; \
316 bl hdlr; \
317 b ret
318
319#define STD_EXCEPTION_COMMON(trap, label, hdlr) \
320 EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \
321 ADD_NVGPRS;DISABLE_INTS)
312 322
313/* 323/*
314 * Like STD_EXCEPTION_COMMON, but for exceptions that can occur 324 * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
315 * in the idle task and therefore need the special idle handling. 325 * in the idle task and therefore need the special idle handling
326 * (finish nap and runlatch)
316 */ 327 */
317#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr) \ 328#define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \
318 .align 7; \ 329 EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
319 .globl label##_common; \ 330 FINISH_NAP;RUNLATCH_ON;DISABLE_INTS)
320label##_common: \
321 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
322 FINISH_NAP; \
323 DISABLE_INTS; \
324 bl .save_nvgprs; \
325 addi r3,r1,STACK_FRAME_OVERHEAD; \
326 bl hdlr; \
327 b .ret_from_except
328
329#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \
330 .align 7; \
331 .globl label##_common; \
332label##_common: \
333 EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \
334 FINISH_NAP; \
335 DISABLE_INTS; \
336BEGIN_FTR_SECTION \
337 bl .ppc64_runlatch_on; \
338END_FTR_SECTION_IFSET(CPU_FTR_CTRL) \
339 addi r3,r1,STACK_FRAME_OVERHEAD; \
340 bl hdlr; \
341 b .ret_from_except_lite
342 331
343/* 332/*
344 * When the idle code in power4_idle puts the CPU into NAP mode, 333 * When the idle code in power4_idle puts the CPU into NAP mode,
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
new file mode 100644
index 000000000000..88dbf9659185
--- /dev/null
+++ b/arch/powerpc/include/asm/fadump.h
@@ -0,0 +1,218 @@
1/*
2 * Firmware Assisted dump header file.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright 2011 IBM Corporation
19 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
20 */
21
22#ifndef __PPC64_FA_DUMP_H__
23#define __PPC64_FA_DUMP_H__
24
25#ifdef CONFIG_FA_DUMP
26
27/*
28 * The RMA region will be saved for later dumping when kernel crashes.
29 * RMA is Real Mode Area, the first block of logical memory address owned
30 * by logical partition, containing the storage that may be accessed with
31 * translate off.
32 */
33#define RMA_START 0x0
34#define RMA_END (ppc64_rma_size)
35
36/*
37 * On some Power systems where RMO is 128MB, it still requires minimum of
38 * 256MB for kernel to boot successfully. When kdump infrastructure is
39 * configured to save vmcore over network, we run into OOM issue while
40 * loading modules related to network setup. Hence we need aditional 64M
41 * of memory to avoid OOM issue.
42 */
43#define MIN_BOOT_MEM (((RMA_END < (0x1UL << 28)) ? (0x1UL << 28) : RMA_END) \
44 + (0x1UL << 26))
45
46#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
47
48#ifndef ELF_CORE_EFLAGS
49#define ELF_CORE_EFLAGS 0
50#endif
51
52/* Firmware provided dump sections */
53#define FADUMP_CPU_STATE_DATA 0x0001
54#define FADUMP_HPTE_REGION 0x0002
55#define FADUMP_REAL_MODE_REGION 0x0011
56
57/* Dump request flag */
58#define FADUMP_REQUEST_FLAG 0x00000001
59
60/* FAD commands */
61#define FADUMP_REGISTER 1
62#define FADUMP_UNREGISTER 2
63#define FADUMP_INVALIDATE 3
64
65/* Dump status flag */
66#define FADUMP_ERROR_FLAG 0x2000
67
68#define FADUMP_CPU_ID_MASK ((1UL << 32) - 1)
69
70#define CPU_UNKNOWN (~((u32)0))
71
72/* Utility macros */
73#define SKIP_TO_NEXT_CPU(reg_entry) \
74({ \
75 while (reg_entry->reg_id != REG_ID("CPUEND")) \
76 reg_entry++; \
77 reg_entry++; \
78})
79
80/* Kernel Dump section info */
81struct fadump_section {
82 u32 request_flag;
83 u16 source_data_type;
84 u16 error_flags;
85 u64 source_address;
86 u64 source_len;
87 u64 bytes_dumped;
88 u64 destination_address;
89};
90
91/* ibm,configure-kernel-dump header. */
92struct fadump_section_header {
93 u32 dump_format_version;
94 u16 dump_num_sections;
95 u16 dump_status_flag;
96 u32 offset_first_dump_section;
97
98 /* Fields for disk dump option. */
99 u32 dd_block_size;
100 u64 dd_block_offset;
101 u64 dd_num_blocks;
102 u32 dd_offset_disk_path;
103
104 /* Maximum time allowed to prevent an automatic dump-reboot. */
105 u32 max_time_auto;
106};
107
108/*
109 * Firmware Assisted dump memory structure. This structure is required for
110 * registering future kernel dump with power firmware through rtas call.
111 *
112 * No disk dump option. Hence disk dump path string section is not included.
113 */
114struct fadump_mem_struct {
115 struct fadump_section_header header;
116
117 /* Kernel dump sections */
118 struct fadump_section cpu_state_data;
119 struct fadump_section hpte_region;
120 struct fadump_section rmr_region;
121};
122
123/* Firmware-assisted dump configuration details. */
124struct fw_dump {
125 unsigned long cpu_state_data_size;
126 unsigned long hpte_region_size;
127 unsigned long boot_memory_size;
128 unsigned long reserve_dump_area_start;
129 unsigned long reserve_dump_area_size;
130 /* cmd line option during boot */
131 unsigned long reserve_bootvar;
132
133 unsigned long fadumphdr_addr;
134 unsigned long cpu_notes_buf;
135 unsigned long cpu_notes_buf_size;
136
137 int ibm_configure_kernel_dump;
138
139 unsigned long fadump_enabled:1;
140 unsigned long fadump_supported:1;
141 unsigned long dump_active:1;
142 unsigned long dump_registered:1;
143};
144
145/*
146 * Copy the ascii values for first 8 characters from a string into u64
147 * variable at their respective indexes.
148 * e.g.
149 * The string "FADMPINF" will be converted into 0x4641444d50494e46
150 */
151static inline u64 str_to_u64(const char *str)
152{
153 u64 val = 0;
154 int i;
155
156 for (i = 0; i < sizeof(val); i++)
157 val = (*str) ? (val << 8) | *str++ : val << 8;
158 return val;
159}
160#define STR_TO_HEX(x) str_to_u64(x)
161#define REG_ID(x) str_to_u64(x)
162
163#define FADUMP_CRASH_INFO_MAGIC STR_TO_HEX("FADMPINF")
164#define REGSAVE_AREA_MAGIC STR_TO_HEX("REGSAVE")
165
166/* The firmware-assisted dump format.
167 *
168 * The register save area is an area in the partition's memory used to preserve
169 * the register contents (CPU state data) for the active CPUs during a firmware
170 * assisted dump. The dump format contains register save area header followed
171 * by register entries. Each list of registers for a CPU starts with
172 * "CPUSTRT" and ends with "CPUEND".
173 */
174
175/* Register save area header. */
176struct fadump_reg_save_area_header {
177 u64 magic_number;
178 u32 version;
179 u32 num_cpu_offset;
180};
181
182/* Register entry. */
183struct fadump_reg_entry {
184 u64 reg_id;
185 u64 reg_value;
186};
187
188/* fadump crash info structure */
189struct fadump_crash_info_header {
190 u64 magic_number;
191 u64 elfcorehdr_addr;
192 u32 crashing_cpu;
193 struct pt_regs regs;
194 struct cpumask cpu_online_mask;
195};
196
197/* Crash memory ranges */
198#define INIT_CRASHMEM_RANGES (INIT_MEMBLOCK_REGIONS + 2)
199
200struct fad_crash_memory_ranges {
201 unsigned long long base;
202 unsigned long long size;
203};
204
205extern int early_init_dt_scan_fw_dump(unsigned long node,
206 const char *uname, int depth, void *data);
207extern int fadump_reserve_mem(void);
208extern int setup_fadump(void);
209extern int is_fadump_active(void);
210extern void crash_fadump(struct pt_regs *, const char *);
211extern void fadump_cleanup(void);
212
213extern void vmcore_cleanup(void);
214#else /* CONFIG_FA_DUMP */
215static inline int is_fadump_active(void) { return 0; }
216static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
217#endif
218#endif
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 14db29b18d0e..ad0b751b0d78 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -41,7 +41,6 @@
41#define FW_FEATURE_XDABR ASM_CONST(0x0000000000040000) 41#define FW_FEATURE_XDABR ASM_CONST(0x0000000000040000)
42#define FW_FEATURE_MULTITCE ASM_CONST(0x0000000000080000) 42#define FW_FEATURE_MULTITCE ASM_CONST(0x0000000000080000)
43#define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000) 43#define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000)
44#define FW_FEATURE_ISERIES ASM_CONST(0x0000000000200000)
45#define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000) 44#define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000)
46#define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000) 45#define FW_FEATURE_PS3_LV1 ASM_CONST(0x0000000000800000)
47#define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000) 46#define FW_FEATURE_BEAT ASM_CONST(0x0000000001000000)
@@ -65,8 +64,6 @@ enum {
65 FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | 64 FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
66 FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO, 65 FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO,
67 FW_FEATURE_PSERIES_ALWAYS = 0, 66 FW_FEATURE_PSERIES_ALWAYS = 0,
68 FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
69 FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
70 FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2, 67 FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2,
71 FW_FEATURE_POWERNV_ALWAYS = 0, 68 FW_FEATURE_POWERNV_ALWAYS = 0,
72 FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, 69 FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
@@ -79,9 +76,6 @@ enum {
79#ifdef CONFIG_PPC_PSERIES 76#ifdef CONFIG_PPC_PSERIES
80 FW_FEATURE_PSERIES_POSSIBLE | 77 FW_FEATURE_PSERIES_POSSIBLE |
81#endif 78#endif
82#ifdef CONFIG_PPC_ISERIES
83 FW_FEATURE_ISERIES_POSSIBLE |
84#endif
85#ifdef CONFIG_PPC_POWERNV 79#ifdef CONFIG_PPC_POWERNV
86 FW_FEATURE_POWERNV_POSSIBLE | 80 FW_FEATURE_POWERNV_POSSIBLE |
87#endif 81#endif
@@ -99,9 +93,6 @@ enum {
99#ifdef CONFIG_PPC_PSERIES 93#ifdef CONFIG_PPC_PSERIES
100 FW_FEATURE_PSERIES_ALWAYS & 94 FW_FEATURE_PSERIES_ALWAYS &
101#endif 95#endif
102#ifdef CONFIG_PPC_ISERIES
103 FW_FEATURE_ISERIES_ALWAYS &
104#endif
105#ifdef CONFIG_PPC_POWERNV 96#ifdef CONFIG_PPC_POWERNV
106 FW_FEATURE_POWERNV_ALWAYS & 97 FW_FEATURE_POWERNV_ALWAYS &
107#endif 98#endif
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index bebd12463ec9..ce04530d2000 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -4,7 +4,7 @@
4 * Authors: Jeff Brown 4 * Authors: Jeff Brown
5 * Timur Tabi <timur@freescale.com> 5 * Timur Tabi <timur@freescale.com>
6 * 6 *
7 * Copyright 2004,2007 Freescale Semiconductor, Inc 7 * Copyright 2004,2007,2012 Freescale Semiconductor, Inc
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify it 9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
@@ -114,6 +114,10 @@ struct ccsr_guts_86xx {
114 __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ 114 __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
115} __attribute__ ((packed)); 115} __attribute__ ((packed));
116 116
117
118/* Alternate function signal multiplex control */
119#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
120
117#ifdef CONFIG_PPC_86xx 121#ifdef CONFIG_PPC_86xx
118 122
119#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ 123#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index bb712c9488b3..51010bfc792e 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -11,6 +11,27 @@
11#include <asm/ptrace.h> 11#include <asm/ptrace.h>
12#include <asm/processor.h> 12#include <asm/processor.h>
13 13
14#ifdef CONFIG_PPC64
15
16/*
17 * PACA flags in paca->irq_happened.
18 *
19 * This bits are set when interrupts occur while soft-disabled
20 * and allow a proper replay. Additionally, PACA_IRQ_HARD_DIS
21 * is set whenever we manually hard disable.
22 */
23#define PACA_IRQ_HARD_DIS 0x01
24#define PACA_IRQ_DBELL 0x02
25#define PACA_IRQ_EE 0x04
26#define PACA_IRQ_DEC 0x08 /* Or FIT */
27#define PACA_IRQ_EE_EDGE 0x10 /* BookE only */
28
29#endif /* CONFIG_PPC64 */
30
31#ifndef __ASSEMBLY__
32
33extern void __replay_interrupt(unsigned int vector);
34
14extern void timer_interrupt(struct pt_regs *); 35extern void timer_interrupt(struct pt_regs *);
15 36
16#ifdef CONFIG_PPC64 37#ifdef CONFIG_PPC64
@@ -42,7 +63,6 @@ static inline unsigned long arch_local_irq_disable(void)
42} 63}
43 64
44extern void arch_local_irq_restore(unsigned long); 65extern void arch_local_irq_restore(unsigned long);
45extern void iseries_handle_interrupts(void);
46 66
47static inline void arch_local_irq_enable(void) 67static inline void arch_local_irq_enable(void)
48{ 68{
@@ -68,16 +88,33 @@ static inline bool arch_irqs_disabled(void)
68#define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory"); 88#define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory");
69#define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory"); 89#define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory");
70#else 90#else
71#define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) 91#define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1)
72#define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) 92#define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1)
73#endif 93#endif
74 94
75#define hard_irq_disable() \ 95static inline void hard_irq_disable(void)
76 do { \ 96{
77 __hard_irq_disable(); \ 97 __hard_irq_disable();
78 get_paca()->soft_enabled = 0; \ 98 get_paca()->soft_enabled = 0;
79 get_paca()->hard_enabled = 0; \ 99 get_paca()->irq_happened |= PACA_IRQ_HARD_DIS;
80 } while(0) 100}
101
102/*
103 * This is called by asynchronous interrupts to conditionally
104 * re-enable hard interrupts when soft-disabled after having
105 * cleared the source of the interrupt
106 */
107static inline void may_hard_irq_enable(void)
108{
109 get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
110 if (!(get_paca()->irq_happened & PACA_IRQ_EE))
111 __hard_irq_enable();
112}
113
114static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
115{
116 return !regs->softe;
117}
81 118
82#else /* CONFIG_PPC64 */ 119#else /* CONFIG_PPC64 */
83 120
@@ -139,6 +176,13 @@ static inline bool arch_irqs_disabled(void)
139 176
140#define hard_irq_disable() arch_local_irq_disable() 177#define hard_irq_disable() arch_local_irq_disable()
141 178
179static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
180{
181 return !(regs->msr & MSR_EE);
182}
183
184static inline void may_hard_irq_enable(void) { }
185
142#endif /* CONFIG_PPC64 */ 186#endif /* CONFIG_PPC64 */
143 187
144#define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST 188#define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST
@@ -149,5 +193,6 @@ static inline bool arch_irqs_disabled(void)
149 */ 193 */
150struct irq_chip; 194struct irq_chip;
151 195
196#endif /* __ASSEMBLY__ */
152#endif /* __KERNEL__ */ 197#endif /* __KERNEL__ */
153#endif /* _ASM_POWERPC_HW_IRQ_H */ 198#endif /* _ASM_POWERPC_HW_IRQ_H */
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h
index b0b06d85788d..6f9b6e23dc5a 100644
--- a/arch/powerpc/include/asm/irqflags.h
+++ b/arch/powerpc/include/asm/irqflags.h
@@ -39,24 +39,31 @@
39#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on) 39#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
40#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off) 40#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
41 41
42#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip) \ 42/*
43 cmpdi en,0; \ 43 * This is used by assembly code to soft-disable interrupts
44 bne 95f; \ 44 */
45 stb en,PACASOFTIRQEN(r13); \ 45#define SOFT_DISABLE_INTS(__rA, __rB) \
46 TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off) \ 46 lbz __rA,PACASOFTIRQEN(r13); \
47 b skip; \ 47 lbz __rB,PACAIRQHAPPENED(r13); \
4895: TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on) \ 48 cmpwi cr0,__rA,0; \
49 li en,1; 49 li __rA,0; \
50#define TRACE_AND_RESTORE_IRQ(en) \ 50 ori __rB,__rB,PACA_IRQ_HARD_DIS; \
51 TRACE_AND_RESTORE_IRQ_PARTIAL(en,96f); \ 51 stb __rB,PACAIRQHAPPENED(r13); \
52 stb en,PACASOFTIRQEN(r13); \ 52 beq 44f; \
5396: 53 stb __rA,PACASOFTIRQEN(r13); \
54 TRACE_DISABLE_INTS; \
5544:
56
54#else 57#else
55#define TRACE_ENABLE_INTS 58#define TRACE_ENABLE_INTS
56#define TRACE_DISABLE_INTS 59#define TRACE_DISABLE_INTS
57#define TRACE_AND_RESTORE_IRQ_PARTIAL(en,skip) 60
58#define TRACE_AND_RESTORE_IRQ(en) \ 61#define SOFT_DISABLE_INTS(__rA, __rB) \
59 stb en,PACASOFTIRQEN(r13) 62 lbz __rA,PACAIRQHAPPENED(r13); \
63 li __rB,0; \
64 ori __rA,__rA,PACA_IRQ_HARD_DIS; \
65 stb __rB,PACASOFTIRQEN(r13); \
66 stb __rA,PACAIRQHAPPENED(r13)
60#endif 67#endif
61#endif 68#endif
62 69
diff --git a/arch/powerpc/include/asm/iseries/alpaca.h b/arch/powerpc/include/asm/iseries/alpaca.h
deleted file mode 100644
index c0cce6727a69..000000000000
--- a/arch/powerpc/include/asm/iseries/alpaca.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/*
2 * Copyright © 2008 Stephen Rothwell IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_ALPACA_H
19#define _ASM_POWERPC_ISERIES_ALPACA_H
20
21/*
22 * This is the part of the paca that the iSeries hypervisor
23 * needs to be statically initialised. Immediately after boot
24 * we switch to the normal Linux paca.
25 */
26struct alpaca {
27 struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
28 const void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
29};
30
31#endif /* _ASM_POWERPC_ISERIES_ALPACA_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_call.h b/arch/powerpc/include/asm/iseries/hv_call.h
deleted file mode 100644
index 162d653ad51f..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_call.h
+++ /dev/null
@@ -1,111 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * This file contains the "hypervisor call" interface which is used to
19 * drive the hypervisor from the OS.
20 */
21#ifndef _ASM_POWERPC_ISERIES_HV_CALL_H
22#define _ASM_POWERPC_ISERIES_HV_CALL_H
23
24#include <asm/iseries/hv_call_sc.h>
25#include <asm/iseries/hv_types.h>
26#include <asm/paca.h>
27
28/* Type of yield for HvCallBaseYieldProcessor */
29#define HvCall_YieldTimed 0 /* Yield until specified time (tb) */
30#define HvCall_YieldToActive 1 /* Yield until all active procs have run */
31#define HvCall_YieldToProc 2 /* Yield until the specified processor has run */
32
33/* interrupt masks for setEnabledInterrupts */
34#define HvCall_MaskIPI 0x00000001
35#define HvCall_MaskLpEvent 0x00000002
36#define HvCall_MaskLpProd 0x00000004
37#define HvCall_MaskTimeout 0x00000008
38
39/* Log buffer formats */
40#define HvCall_LogBuffer_ASCII 0
41#define HvCall_LogBuffer_EBCDIC 1
42
43#define HvCallBaseAckDeferredInts HvCallBase + 0
44#define HvCallBaseCpmPowerOff HvCallBase + 1
45#define HvCallBaseGetHwPatch HvCallBase + 2
46#define HvCallBaseReIplSpAttn HvCallBase + 3
47#define HvCallBaseSetASR HvCallBase + 4
48#define HvCallBaseSetASRAndRfi HvCallBase + 5
49#define HvCallBaseSetIMR HvCallBase + 6
50#define HvCallBaseSendIPI HvCallBase + 7
51#define HvCallBaseTerminateMachine HvCallBase + 8
52#define HvCallBaseTerminateMachineSrc HvCallBase + 9
53#define HvCallBaseProcessPlicInterrupts HvCallBase + 10
54#define HvCallBaseIsPrimaryCpmOrMsdIpl HvCallBase + 11
55#define HvCallBaseSetVirtualSIT HvCallBase + 12
56#define HvCallBaseVaryOffThisProcessor HvCallBase + 13
57#define HvCallBaseVaryOffMemoryChunk HvCallBase + 14
58#define HvCallBaseVaryOffInteractivePercentage HvCallBase + 15
59#define HvCallBaseSendLpProd HvCallBase + 16
60#define HvCallBaseSetEnabledInterrupts HvCallBase + 17
61#define HvCallBaseYieldProcessor HvCallBase + 18
62#define HvCallBaseVaryOffSharedProcUnits HvCallBase + 19
63#define HvCallBaseSetVirtualDecr HvCallBase + 20
64#define HvCallBaseClearLogBuffer HvCallBase + 21
65#define HvCallBaseGetLogBufferCodePage HvCallBase + 22
66#define HvCallBaseGetLogBufferFormat HvCallBase + 23
67#define HvCallBaseGetLogBufferLength HvCallBase + 24
68#define HvCallBaseReadLogBuffer HvCallBase + 25
69#define HvCallBaseSetLogBufferFormatAndCodePage HvCallBase + 26
70#define HvCallBaseWriteLogBuffer HvCallBase + 27
71#define HvCallBaseRouter28 HvCallBase + 28
72#define HvCallBaseRouter29 HvCallBase + 29
73#define HvCallBaseRouter30 HvCallBase + 30
74#define HvCallBaseSetDebugBus HvCallBase + 31
75
76#define HvCallCcSetDABR HvCallCc + 7
77
78static inline void HvCall_setVirtualDecr(void)
79{
80 /*
81 * Ignore any error return codes - most likely means that the
82 * target value for the LP has been increased and this vary off
83 * would bring us below the new target.
84 */
85 HvCall0(HvCallBaseSetVirtualDecr);
86}
87
88static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
89{
90 HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm);
91}
92
93static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts)
94{
95 HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts);
96}
97
98static inline void HvCall_setLogBufferFormatAndCodepage(int format,
99 u32 codePage)
100{
101 HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage);
102}
103
104extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
105
106static inline void HvCall_sendIPI(struct paca_struct *targetPaca)
107{
108 HvCall1(HvCallBaseSendIPI, targetPaca->paca_index);
109}
110
111#endif /* _ASM_POWERPC_ISERIES_HV_CALL_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_call_event.h b/arch/powerpc/include/asm/iseries/hv_call_event.h
deleted file mode 100644
index cc029d388e11..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_call_event.h
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * This file contains the "hypervisor call" interface which is used to
19 * drive the hypervisor from the OS.
20 */
21#ifndef _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
22#define _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
23
24#include <linux/types.h>
25#include <linux/dma-mapping.h>
26
27#include <asm/iseries/hv_call_sc.h>
28#include <asm/iseries/hv_types.h>
29#include <asm/abs_addr.h>
30
31struct HvLpEvent;
32
33typedef u8 HvLpEvent_Type;
34typedef u8 HvLpEvent_AckInd;
35typedef u8 HvLpEvent_AckType;
36
37typedef u8 HvLpDma_Direction;
38typedef u8 HvLpDma_AddressType;
39
40typedef u64 HvLpEvent_Rc;
41typedef u64 HvLpDma_Rc;
42
43#define HvCallEventAckLpEvent HvCallEvent + 0
44#define HvCallEventCancelLpEvent HvCallEvent + 1
45#define HvCallEventCloseLpEventPath HvCallEvent + 2
46#define HvCallEventDmaBufList HvCallEvent + 3
47#define HvCallEventDmaSingle HvCallEvent + 4
48#define HvCallEventDmaToSp HvCallEvent + 5
49#define HvCallEventGetOverflowLpEvents HvCallEvent + 6
50#define HvCallEventGetSourceLpInstanceId HvCallEvent + 7
51#define HvCallEventGetTargetLpInstanceId HvCallEvent + 8
52#define HvCallEventOpenLpEventPath HvCallEvent + 9
53#define HvCallEventSetLpEventStack HvCallEvent + 10
54#define HvCallEventSignalLpEvent HvCallEvent + 11
55#define HvCallEventSignalLpEventParms HvCallEvent + 12
56#define HvCallEventSetInterLpQueueIndex HvCallEvent + 13
57#define HvCallEventSetLpEventQueueInterruptProc HvCallEvent + 14
58#define HvCallEventRouter15 HvCallEvent + 15
59
60static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex)
61{
62 HvCall1(HvCallEventGetOverflowLpEvents, queueIndex);
63}
64
65static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex)
66{
67 HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex);
68}
69
70static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
71 char *eventStackAddr, u32 eventStackSize)
72{
73 HvCall3(HvCallEventSetLpEventStack, queueIndex,
74 virt_to_abs(eventStackAddr), eventStackSize);
75}
76
77static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
78 u16 lpLogicalProcIndex)
79{
80 HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex,
81 lpLogicalProcIndex);
82}
83
84static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event)
85{
86 return HvCall1(HvCallEventSignalLpEvent, virt_to_abs(event));
87}
88
89static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
90 HvLpEvent_Type type, u16 subtype, HvLpEvent_AckInd ackInd,
91 HvLpEvent_AckType ackType, HvLpInstanceId sourceInstanceId,
92 HvLpInstanceId targetInstanceId, u64 correlationToken,
93 u64 eventData1, u64 eventData2, u64 eventData3,
94 u64 eventData4, u64 eventData5)
95{
96 /* Pack the misc bits into a single Dword to pass to PLIC */
97 union {
98 struct {
99 u8 ack_and_target;
100 u8 type;
101 u16 subtype;
102 HvLpInstanceId src_inst;
103 HvLpInstanceId target_inst;
104 } parms;
105 u64 dword;
106 } packed;
107
108 packed.parms.ack_and_target = (ackType << 7) | (ackInd << 6) | targetLp;
109 packed.parms.type = type;
110 packed.parms.subtype = subtype;
111 packed.parms.src_inst = sourceInstanceId;
112 packed.parms.target_inst = targetInstanceId;
113
114 return HvCall7(HvCallEventSignalLpEventParms, packed.dword,
115 correlationToken, eventData1, eventData2,
116 eventData3, eventData4, eventData5);
117}
118
119extern void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag);
120extern void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle);
121extern dma_addr_t iseries_hv_map(void *vaddr, size_t size,
122 enum dma_data_direction direction);
123extern void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
124 enum dma_data_direction direction);
125
126static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
127{
128 return HvCall1(HvCallEventAckLpEvent, virt_to_abs(event));
129}
130
131static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event)
132{
133 return HvCall1(HvCallEventCancelLpEvent, virt_to_abs(event));
134}
135
136static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId(
137 HvLpIndex targetLp, HvLpEvent_Type type)
138{
139 return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
140}
141
142static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId(
143 HvLpIndex targetLp, HvLpEvent_Type type)
144{
145 return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
146}
147
148static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp,
149 HvLpEvent_Type type)
150{
151 HvCall2(HvCallEventOpenLpEventPath, targetLp, type);
152}
153
154static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp,
155 HvLpEvent_Type type)
156{
157 HvCall2(HvCallEventCloseLpEventPath, targetLp, type);
158}
159
160static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
161 HvLpIndex remoteLp, HvLpDma_Direction direction,
162 HvLpInstanceId localInstanceId,
163 HvLpInstanceId remoteInstanceId,
164 HvLpDma_AddressType localAddressType,
165 HvLpDma_AddressType remoteAddressType,
166 /* Do these need to be converted to absolute addresses? */
167 u64 localBufList, u64 remoteBufList, u32 transferLength)
168{
169 /* Pack the misc bits into a single Dword to pass to PLIC */
170 union {
171 struct {
172 u8 flags;
173 HvLpIndex remote;
174 u8 type;
175 u8 reserved;
176 HvLpInstanceId local_inst;
177 HvLpInstanceId remote_inst;
178 } parms;
179 u64 dword;
180 } packed;
181
182 packed.parms.flags = (direction << 7) |
183 (localAddressType << 6) | (remoteAddressType << 5);
184 packed.parms.remote = remoteLp;
185 packed.parms.type = type;
186 packed.parms.reserved = 0;
187 packed.parms.local_inst = localInstanceId;
188 packed.parms.remote_inst = remoteInstanceId;
189
190 return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList,
191 remoteBufList, transferLength);
192}
193
194static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote,
195 u32 length, HvLpDma_Direction dir)
196{
197 return HvCall4(HvCallEventDmaToSp, virt_to_abs(local), remote,
198 length, dir);
199}
200
201#endif /* _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_call_sc.h b/arch/powerpc/include/asm/iseries/hv_call_sc.h
deleted file mode 100644
index f5d210959250..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_call_sc.h
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_HV_CALL_SC_H
19#define _ASM_POWERPC_ISERIES_HV_CALL_SC_H
20
21#include <linux/types.h>
22
23#define HvCallBase 0x8000000000000000ul
24#define HvCallCc 0x8001000000000000ul
25#define HvCallCfg 0x8002000000000000ul
26#define HvCallEvent 0x8003000000000000ul
27#define HvCallHpt 0x8004000000000000ul
28#define HvCallPci 0x8005000000000000ul
29#define HvCallSm 0x8007000000000000ul
30#define HvCallXm 0x8009000000000000ul
31
32extern u64 HvCall0(u64);
33extern u64 HvCall1(u64, u64);
34extern u64 HvCall2(u64, u64, u64);
35extern u64 HvCall3(u64, u64, u64, u64);
36extern u64 HvCall4(u64, u64, u64, u64, u64);
37extern u64 HvCall5(u64, u64, u64, u64, u64, u64);
38extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64);
39extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64);
40
41extern u64 HvCall0Ret16(u64, void *);
42extern u64 HvCall1Ret16(u64, void *, u64);
43extern u64 HvCall2Ret16(u64, void *, u64, u64);
44extern u64 HvCall3Ret16(u64, void *, u64, u64, u64);
45extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64);
46extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64);
47extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64);
48extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64);
49
50#endif /* _ASM_POWERPC_ISERIES_HV_CALL_SC_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_call_xm.h b/arch/powerpc/include/asm/iseries/hv_call_xm.h
deleted file mode 100644
index 392ac3f54df0..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_call_xm.h
+++ /dev/null
@@ -1,61 +0,0 @@
1/*
2 * This file contains the "hypervisor call" interface which is used to
3 * drive the hypervisor from SLIC.
4 */
5#ifndef _ASM_POWERPC_ISERIES_HV_CALL_XM_H
6#define _ASM_POWERPC_ISERIES_HV_CALL_XM_H
7
8#include <asm/iseries/hv_call_sc.h>
9#include <asm/iseries/hv_types.h>
10
11#define HvCallXmGetTceTableParms HvCallXm + 0
12#define HvCallXmTestBus HvCallXm + 1
13#define HvCallXmConnectBusUnit HvCallXm + 2
14#define HvCallXmLoadTod HvCallXm + 8
15#define HvCallXmTestBusUnit HvCallXm + 9
16#define HvCallXmSetTce HvCallXm + 11
17#define HvCallXmSetTces HvCallXm + 13
18
19static inline void HvCallXm_getTceTableParms(u64 cb)
20{
21 HvCall1(HvCallXmGetTceTableParms, cb);
22}
23
24static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
25{
26 return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce);
27}
28
29static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset,
30 u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
31{
32 return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
33 tce1, tce2, tce3, tce4);
34}
35
36static inline u64 HvCallXm_testBus(u16 busNumber)
37{
38 return HvCall1(HvCallXmTestBus, busNumber);
39}
40
41static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber,
42 u8 deviceId)
43{
44 return HvCall2(HvCallXmTestBusUnit, busNumber,
45 (subBusNumber << 8) | deviceId);
46}
47
48static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber,
49 u8 deviceId, u64 interruptToken)
50{
51 return HvCall5(HvCallXmConnectBusUnit, busNumber,
52 (subBusNumber << 8) | deviceId, interruptToken, 0,
53 0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */);
54}
55
56static inline u64 HvCallXm_loadTod(void)
57{
58 return HvCall0(HvCallXmLoadTod);
59}
60
61#endif /* _ASM_POWERPC_ISERIES_HV_CALL_XM_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_lp_config.h b/arch/powerpc/include/asm/iseries/hv_lp_config.h
deleted file mode 100644
index a006fd1e4a2c..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_lp_config.h
+++ /dev/null
@@ -1,128 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H
19#define _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H
20
21/*
22 * This file contains the interface to the LPAR configuration data
23 * to determine which resources should be allocated to each partition.
24 */
25
26#include <asm/iseries/hv_call_sc.h>
27#include <asm/iseries/hv_types.h>
28
29enum {
30 HvCallCfg_Cur = 0,
31 HvCallCfg_Init = 1,
32 HvCallCfg_Max = 2,
33 HvCallCfg_Min = 3
34};
35
36#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6
37#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7
38#define HvCallCfgGetMsChunks HvCallCfg + 9
39#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20
40#define HvCallCfgGetSharedProcUnits HvCallCfg + 21
41#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22
42#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30
43#define HvCallCfgGetHostingLpIndex HvCallCfg + 32
44
45extern HvLpIndex HvLpConfig_getLpIndex_outline(void);
46extern HvLpIndex HvLpConfig_getLpIndex(void);
47extern HvLpIndex HvLpConfig_getPrimaryLpIndex(void);
48
49static inline u64 HvLpConfig_getMsChunks(void)
50{
51 return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(),
52 HvCallCfg_Cur);
53}
54
55static inline u64 HvLpConfig_getSystemPhysicalProcessors(void)
56{
57 return HvCall0(HvCallCfgGetSystemPhysicalProcessors);
58}
59
60static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
61{
62 return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI);
63}
64
65static inline u64 HvLpConfig_getPhysicalProcessors(void)
66{
67 return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
68 HvCallCfg_Cur);
69}
70
71static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void)
72{
73 return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex());
74}
75
76static inline u64 HvLpConfig_getSharedProcUnits(void)
77{
78 return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
79 HvCallCfg_Cur);
80}
81
82static inline u64 HvLpConfig_getMaxSharedProcUnits(void)
83{
84 return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
85 HvCallCfg_Max);
86}
87
88static inline u64 HvLpConfig_getMaxPhysicalProcessors(void)
89{
90 return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
91 HvCallCfg_Max);
92}
93
94static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(
95 HvLpIndex lp)
96{
97 /*
98 * This is a new function in V5R1 so calls to this on older
99 * hypervisors will return -1
100 */
101 u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
102 if (retVal == -1)
103 retVal = 0;
104 return retVal;
105}
106
107static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void)
108{
109 return HvLpConfig_getVirtualLanIndexMapForLp(
110 HvLpConfig_getLpIndex_outline());
111}
112
113static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1,
114 HvLpIndex lp2)
115{
116 HvLpVirtualLanIndexMap virtualLanIndexMap1 =
117 HvLpConfig_getVirtualLanIndexMapForLp(lp1);
118 HvLpVirtualLanIndexMap virtualLanIndexMap2 =
119 HvLpConfig_getVirtualLanIndexMapForLp(lp2);
120 return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0);
121}
122
123static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp)
124{
125 return HvCall1(HvCallCfgGetHostingLpIndex, lp);
126}
127
128#endif /* _ASM_POWERPC_ISERIES_HV_LP_CONFIG_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_lp_event.h b/arch/powerpc/include/asm/iseries/hv_lp_event.h
deleted file mode 100644
index 8f5da7d77202..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_lp_event.h
+++ /dev/null
@@ -1,162 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19/* This file contains the class for HV events in the system. */
20
21#ifndef _ASM_POWERPC_ISERIES_HV_LP_EVENT_H
22#define _ASM_POWERPC_ISERIES_HV_LP_EVENT_H
23
24#include <asm/types.h>
25#include <asm/ptrace.h>
26#include <asm/iseries/hv_types.h>
27#include <asm/iseries/hv_call_event.h>
28
29/*
30 * HvLpEvent is the structure for Lp Event messages passed between
31 * partitions through PLIC.
32 */
33
34struct HvLpEvent {
35 u8 flags; /* Event flags x00-x00 */
36 u8 xType; /* Type of message x01-x01 */
37 u16 xSubtype; /* Subtype for event x02-x03 */
38 u8 xSourceLp; /* Source LP x04-x04 */
39 u8 xTargetLp; /* Target LP x05-x05 */
40 u8 xSizeMinus1; /* Size of Derived class - 1 x06-x06 */
41 u8 xRc; /* RC for Ack flows x07-x07 */
42 u16 xSourceInstanceId; /* Source sides instance id x08-x09 */
43 u16 xTargetInstanceId; /* Target sides instance id x0A-x0B */
44 union {
45 u32 xSubtypeData; /* Data usable by the subtype x0C-x0F */
46 u16 xSubtypeDataShort[2]; /* Data as 2 shorts */
47 u8 xSubtypeDataChar[4]; /* Data as 4 chars */
48 } x;
49
50 u64 xCorrelationToken; /* Unique value for source/type x10-x17 */
51};
52
53typedef void (*LpEventHandler)(struct HvLpEvent *);
54
55/* Register a handler for an event type - returns 0 on success */
56extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType,
57 LpEventHandler hdlr);
58
59/*
60 * Unregister a handler for an event type
61 *
62 * This call will sleep until the handler being removed is guaranteed to
63 * be no longer executing on any CPU. Do not call with locks held.
64 *
65 * returns 0 on success
66 * Unregister will fail if there are any paths open for the type
67 */
68extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType);
69
70/*
71 * Open an Lp Event Path for an event type
72 * returns 0 on success
73 * openPath will fail if there is no handler registered for the event type.
74 * The lpIndex specified is the partition index for the target partition
75 * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero)
76 */
77extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
78
79/*
80 * Close an Lp Event Path for a type and partition
81 * returns 0 on success
82 */
83extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
84
85#define HvLpEvent_Type_Hypervisor 0
86#define HvLpEvent_Type_MachineFac 1
87#define HvLpEvent_Type_SessionMgr 2
88#define HvLpEvent_Type_SpdIo 3
89#define HvLpEvent_Type_VirtualBus 4
90#define HvLpEvent_Type_PciIo 5
91#define HvLpEvent_Type_RioIo 6
92#define HvLpEvent_Type_VirtualLan 7
93#define HvLpEvent_Type_VirtualIo 8
94#define HvLpEvent_Type_NumTypes 9
95
96#define HvLpEvent_Rc_Good 0
97#define HvLpEvent_Rc_BufferNotAvailable 1
98#define HvLpEvent_Rc_Cancelled 2
99#define HvLpEvent_Rc_GenericError 3
100#define HvLpEvent_Rc_InvalidAddress 4
101#define HvLpEvent_Rc_InvalidPartition 5
102#define HvLpEvent_Rc_InvalidSize 6
103#define HvLpEvent_Rc_InvalidSubtype 7
104#define HvLpEvent_Rc_InvalidSubtypeData 8
105#define HvLpEvent_Rc_InvalidType 9
106#define HvLpEvent_Rc_PartitionDead 10
107#define HvLpEvent_Rc_PathClosed 11
108#define HvLpEvent_Rc_SubtypeError 12
109
110#define HvLpEvent_Function_Ack 0
111#define HvLpEvent_Function_Int 1
112
113#define HvLpEvent_AckInd_NoAck 0
114#define HvLpEvent_AckInd_DoAck 1
115
116#define HvLpEvent_AckType_ImmediateAck 0
117#define HvLpEvent_AckType_DeferredAck 1
118
119#define HV_LP_EVENT_INT 0x01
120#define HV_LP_EVENT_DO_ACK 0x02
121#define HV_LP_EVENT_DEFERRED_ACK 0x04
122#define HV_LP_EVENT_VALID 0x80
123
124#define HvLpDma_Direction_LocalToRemote 0
125#define HvLpDma_Direction_RemoteToLocal 1
126
127#define HvLpDma_AddressType_TceIndex 0
128#define HvLpDma_AddressType_RealAddress 1
129
130#define HvLpDma_Rc_Good 0
131#define HvLpDma_Rc_Error 1
132#define HvLpDma_Rc_PartitionDead 2
133#define HvLpDma_Rc_PathClosed 3
134#define HvLpDma_Rc_InvalidAddress 4
135#define HvLpDma_Rc_InvalidLength 5
136
137static inline int hvlpevent_is_valid(struct HvLpEvent *h)
138{
139 return h->flags & HV_LP_EVENT_VALID;
140}
141
142static inline void hvlpevent_invalidate(struct HvLpEvent *h)
143{
144 h->flags &= ~ HV_LP_EVENT_VALID;
145}
146
147static inline int hvlpevent_is_int(struct HvLpEvent *h)
148{
149 return h->flags & HV_LP_EVENT_INT;
150}
151
152static inline int hvlpevent_is_ack(struct HvLpEvent *h)
153{
154 return !hvlpevent_is_int(h);
155}
156
157static inline int hvlpevent_need_ack(struct HvLpEvent *h)
158{
159 return h->flags & HV_LP_EVENT_DO_ACK;
160}
161
162#endif /* _ASM_POWERPC_ISERIES_HV_LP_EVENT_H */
diff --git a/arch/powerpc/include/asm/iseries/hv_types.h b/arch/powerpc/include/asm/iseries/hv_types.h
deleted file mode 100644
index c3e6d2a1d1c3..000000000000
--- a/arch/powerpc/include/asm/iseries/hv_types.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_HV_TYPES_H
19#define _ASM_POWERPC_ISERIES_HV_TYPES_H
20
21/*
22 * General typedefs for the hypervisor.
23 */
24
25#include <asm/types.h>
26
27typedef u8 HvLpIndex;
28typedef u16 HvLpInstanceId;
29typedef u64 HvLpTOD;
30typedef u64 HvLpSystemSerialNum;
31typedef u8 HvLpDeviceSerialNum[12];
32typedef u16 HvLpSanHwSet;
33typedef u16 HvLpBus;
34typedef u16 HvLpBoard;
35typedef u16 HvLpCard;
36typedef u8 HvLpDeviceType[4];
37typedef u8 HvLpDeviceModel[3];
38typedef u64 HvIoToken;
39typedef u8 HvLpName[8];
40typedef u32 HvIoId;
41typedef u64 HvRealMemoryIndex;
42typedef u32 HvLpIndexMap; /* Must hold HVMAXARCHITECTEDLPS bits!!! */
43typedef u16 HvLpVrmIndex;
44typedef u32 HvXmGenerationId;
45typedef u8 HvLpBusPool;
46typedef u8 HvLpSharedPoolIndex;
47typedef u16 HvLpSharedProcUnitsX100;
48typedef u8 HvLpVirtualLanIndex;
49typedef u16 HvLpVirtualLanIndexMap; /* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */
50typedef u16 HvBusNumber; /* Hypervisor Bus Number */
51typedef u8 HvSubBusNumber; /* Hypervisor SubBus Number */
52typedef u8 HvAgentId; /* Hypervisor DevFn */
53
54
55#define HVMAXARCHITECTEDLPS 32
56#define HVMAXARCHITECTEDVIRTUALLANS 16
57#define HVMAXARCHITECTEDVIRTUALDISKS 32
58#define HVMAXARCHITECTEDVIRTUALCDROMS 8
59#define HVMAXARCHITECTEDVIRTUALTAPES 8
60#define HVCHUNKSIZE (256 * 1024)
61#define HVPAGESIZE (4 * 1024)
62#define HVLPMINMEGSPRIMARY 256
63#define HVLPMINMEGSSECONDARY 64
64#define HVCHUNKSPERMEG 4
65#define HVPAGESPERMEG 256
66#define HVPAGESPERCHUNK 64
67
68#define HvLpIndexInvalid ((HvLpIndex)0xff)
69
70/*
71 * Enums for the sub-components under PLIC
72 * Used in HvCall and HvPrimaryCall
73 */
74enum {
75 HvCallCompId = 0,
76 HvCallCpuCtlsCompId = 1,
77 HvCallCfgCompId = 2,
78 HvCallEventCompId = 3,
79 HvCallHptCompId = 4,
80 HvCallPciCompId = 5,
81 HvCallSlmCompId = 6,
82 HvCallSmCompId = 7,
83 HvCallSpdCompId = 8,
84 HvCallXmCompId = 9,
85 HvCallRioCompId = 10,
86 HvCallRsvd3CompId = 11,
87 HvCallRsvd2CompId = 12,
88 HvCallRsvd1CompId = 13,
89 HvCallMaxCompId = 14,
90 HvPrimaryCallCompId = 0,
91 HvPrimaryCallCfgCompId = 1,
92 HvPrimaryCallPciCompId = 2,
93 HvPrimaryCallSmCompId = 3,
94 HvPrimaryCallSpdCompId = 4,
95 HvPrimaryCallXmCompId = 5,
96 HvPrimaryCallRioCompId = 6,
97 HvPrimaryCallRsvd7CompId = 7,
98 HvPrimaryCallRsvd6CompId = 8,
99 HvPrimaryCallRsvd5CompId = 9,
100 HvPrimaryCallRsvd4CompId = 10,
101 HvPrimaryCallRsvd3CompId = 11,
102 HvPrimaryCallRsvd2CompId = 12,
103 HvPrimaryCallRsvd1CompId = 13,
104 HvPrimaryCallMaxCompId = HvCallMaxCompId
105};
106
107struct HvLpBufferList {
108 u64 addr;
109 u64 len;
110};
111
112#endif /* _ASM_POWERPC_ISERIES_HV_TYPES_H */
diff --git a/arch/powerpc/include/asm/iseries/iommu.h b/arch/powerpc/include/asm/iseries/iommu.h
deleted file mode 100644
index 1b9692c60899..000000000000
--- a/arch/powerpc/include/asm/iseries/iommu.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#ifndef _ASM_POWERPC_ISERIES_IOMMU_H
2#define _ASM_POWERPC_ISERIES_IOMMU_H
3
4/*
5 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the:
19 * Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 */
23
24struct pci_dev;
25struct vio_dev;
26struct device_node;
27struct iommu_table;
28
29/* Get table parameters from HV */
30extern void iommu_table_getparms_iSeries(unsigned long busno,
31 unsigned char slotno, unsigned char virtbus,
32 struct iommu_table *tbl);
33
34extern struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev);
35extern void iommu_vio_init(void);
36
37#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/include/asm/iseries/it_lp_queue.h b/arch/powerpc/include/asm/iseries/it_lp_queue.h
deleted file mode 100644
index 428278838821..000000000000
--- a/arch/powerpc/include/asm/iseries/it_lp_queue.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H
19#define _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H
20
21/*
22 * This control block defines the simple LP queue structure that is
23 * shared between the hypervisor (PLIC) and the OS in order to send
24 * events to an LP.
25 */
26
27#include <asm/types.h>
28#include <asm/ptrace.h>
29
30#define IT_LP_MAX_QUEUES 8
31
32#define IT_LP_NOT_USED 0 /* Queue will not be used by PLIC */
33#define IT_LP_DEDICATED_IO 1 /* Queue dedicated to IO processor specified */
34#define IT_LP_DEDICATED_LP 2 /* Queue dedicated to LP specified */
35#define IT_LP_SHARED 3 /* Queue shared for both IO and LP */
36
37#define IT_LP_EVENT_STACK_SIZE 4096
38#define IT_LP_EVENT_MAX_SIZE 256
39#define IT_LP_EVENT_ALIGN 64
40
41struct hvlpevent_queue {
42/*
43 * The hq_current_event is the pointer to the next event stack entry
44 * that will become valid. The OS must peek at this entry to determine
45 * if it is valid. PLIC will set the valid indicator as the very last
46 * store into that entry.
47 *
48 * When the OS has completed processing of the event then it will mark
49 * the event as invalid so that PLIC knows it can store into that event
50 * location again.
51 *
52 * If the event stack fills and there are overflow events, then PLIC
53 * will set the hq_overflow_pending flag in which case the OS will
54 * have to fetch the additional LP events once they have drained the
55 * event stack.
56 *
57 * The first 16-bytes are known by both the OS and PLIC. The remainder
58 * of the cache line is for use by the OS.
59 */
60 u8 hq_overflow_pending; /* 0x00 Overflow events are pending */
61 u8 hq_status; /* 0x01 DedicatedIo or DedicatedLp or NotUsed */
62 u16 hq_proc_index; /* 0x02 Logical Proc Index for correlation */
63 u8 hq_reserved1[12]; /* 0x04 */
64 char *hq_current_event; /* 0x10 */
65 char *hq_last_event; /* 0x18 */
66 char *hq_event_stack; /* 0x20 */
67 u8 hq_index; /* 0x28 unique sequential index. */
68 u8 hq_reserved2[3]; /* 0x29-2b */
69 spinlock_t hq_lock;
70};
71
72extern struct hvlpevent_queue hvlpevent_queue;
73
74extern int hvlpevent_is_pending(void);
75extern void process_hvlpevents(void);
76extern void setup_hvlpevent_queue(void);
77
78#endif /* _ASM_POWERPC_ISERIES_IT_LP_QUEUE_H */
diff --git a/arch/powerpc/include/asm/iseries/lpar_map.h b/arch/powerpc/include/asm/iseries/lpar_map.h
deleted file mode 100644
index 5e9f3e128ee2..000000000000
--- a/arch/powerpc/include/asm/iseries/lpar_map.h
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ASM_POWERPC_ISERIES_LPAR_MAP_H
19#define _ASM_POWERPC_ISERIES_LPAR_MAP_H
20
21#ifndef __ASSEMBLY__
22
23#include <asm/types.h>
24
25#endif
26
27/*
28 * The iSeries hypervisor will set up mapping for one or more
29 * ESID/VSID pairs (in SLB/segment registers) and will set up
30 * mappings of one or more ranges of pages to VAs.
31 * We will have the hypervisor set up the ESID->VSID mapping
32 * for the four kernel segments (C-F). With shared processors,
33 * the hypervisor will clear all segment registers and reload
34 * these four whenever the processor is switched from one
35 * partition to another.
36 */
37
38/* The Vsid and Esid identified below will be used by the hypervisor
39 * to set up a memory mapping for part of the load area before giving
40 * control to the Linux kernel. The load area is 64 MB, but this must
41 * not attempt to map the whole load area. The Hashed Page Table may
42 * need to be located within the load area (if the total partition size
43 * is 64 MB), but cannot be mapped. Typically, this should specify
44 * to map half (32 MB) of the load area.
45 *
46 * The hypervisor will set up page table entries for the number of
47 * pages specified.
48 *
49 * In 32-bit mode, the hypervisor will load all four of the
50 * segment registers (identified by the low-order four bits of the
51 * Esid field. In 64-bit mode, the hypervisor will load one SLB
52 * entry to map the Esid to the Vsid.
53*/
54
55#define HvEsidsToMap 2
56#define HvRangesToMap 1
57
58/* Hypervisor initially maps 32MB of the load area */
59#define HvPagesToMap 8192
60
61#ifndef __ASSEMBLY__
62struct LparMap {
63 u64 xNumberEsids; // Number of ESID/VSID pairs
64 u64 xNumberRanges; // Number of VA ranges to map
65 u64 xSegmentTableOffs; // Page number within load area of seg table
66 u64 xRsvd[5];
67 struct {
68 u64 xKernelEsid; // Esid used to map kernel load
69 u64 xKernelVsid; // Vsid used to map kernel load
70 } xEsids[HvEsidsToMap];
71 struct {
72 u64 xPages; // Number of pages to be mapped
73 u64 xOffset; // Offset from start of load area
74 u64 xVPN; // Virtual Page Number
75 } xRanges[HvRangesToMap];
76};
77
78extern const struct LparMap xLparMap;
79
80#endif /* __ASSEMBLY__ */
81
82/* the fixed address where the LparMap exists */
83#define LPARMAP_PHYS 0x7000
84
85#endif /* _ASM_POWERPC_ISERIES_LPAR_MAP_H */
diff --git a/arch/powerpc/include/asm/iseries/mf.h b/arch/powerpc/include/asm/iseries/mf.h
deleted file mode 100644
index eb851a9c9e5c..000000000000
--- a/arch/powerpc/include/asm/iseries/mf.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/*
2 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
3 * Copyright (C) 2004 Stephen Rothwell IBM Corporation
4 *
5 * This modules exists as an interface between a Linux secondary partition
6 * running on an iSeries and the primary partition's Virtual Service
7 * Processor (VSP) object. The VSP has final authority over powering on/off
8 * all partitions in the iSeries. It also provides miscellaneous low-level
9 * machine facility type operations.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25#ifndef _ASM_POWERPC_ISERIES_MF_H
26#define _ASM_POWERPC_ISERIES_MF_H
27
28#include <linux/types.h>
29
30#include <asm/iseries/hv_types.h>
31#include <asm/iseries/hv_call_event.h>
32
33struct rtc_time;
34
35typedef void (*MFCompleteHandler)(void *clientToken, int returnCode);
36
37extern void mf_allocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type,
38 unsigned size, unsigned amount, MFCompleteHandler hdlr,
39 void *userToken);
40extern void mf_deallocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type,
41 unsigned count, MFCompleteHandler hdlr, void *userToken);
42
43extern void mf_power_off(void);
44extern void mf_reboot(char *cmd);
45
46extern void mf_display_src(u32 word);
47extern void mf_display_progress(u16 value);
48
49extern void mf_init(void);
50
51#endif /* _ASM_POWERPC_ISERIES_MF_H */
diff --git a/arch/powerpc/include/asm/iseries/vio.h b/arch/powerpc/include/asm/iseries/vio.h
deleted file mode 100644
index f9ac0d00b951..000000000000
--- a/arch/powerpc/include/asm/iseries/vio.h
+++ /dev/null
@@ -1,265 +0,0 @@
1/* -*- linux-c -*-
2 *
3 * iSeries Virtual I/O Message Path header
4 *
5 * Authors: Dave Boutcher <boutcher@us.ibm.com>
6 * Ryan Arnold <ryanarn@us.ibm.com>
7 * Colin Devilbiss <devilbis@us.ibm.com>
8 *
9 * (C) Copyright 2000 IBM Corporation
10 *
11 * This header file is used by the iSeries virtual I/O device
12 * drivers. It defines the interfaces to the common functions
13 * (implemented in drivers/char/viopath.h) as well as defining
14 * common functions and structures. Currently (at the time I
15 * wrote this comment) the iSeries virtual I/O device drivers
16 * that use this are
17 * drivers/block/viodasd.c
18 * drivers/char/viocons.c
19 * drivers/char/viotape.c
20 * drivers/cdrom/viocd.c
21 *
22 * The iSeries virtual ethernet support (veth.c) uses a whole
23 * different set of functions.
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License as
27 * published by the Free Software Foundation; either version 2 of the
28 * License, or (at your option) anyu later version.
29 *
30 * This program is distributed in the hope that it will be useful, but
31 * WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software Foundation,
37 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 *
39 */
40#ifndef _ASM_POWERPC_ISERIES_VIO_H
41#define _ASM_POWERPC_ISERIES_VIO_H
42
43#include <asm/iseries/hv_types.h>
44#include <asm/iseries/hv_lp_event.h>
45
46/*
47 * iSeries virtual I/O events use the subtype field in
48 * HvLpEvent to figure out what kind of vio event is coming
49 * in. We use a table to route these, and this defines
50 * the maximum number of distinct subtypes
51 */
52#define VIO_MAX_SUBTYPES 8
53
54#define VIOMAXBLOCKDMA 12
55
56struct open_data {
57 u64 disk_size;
58 u16 max_disk;
59 u16 cylinders;
60 u16 tracks;
61 u16 sectors;
62 u16 bytes_per_sector;
63};
64
65struct rw_data {
66 u64 offset;
67 struct {
68 u32 token;
69 u32 reserved;
70 u64 len;
71 } dma_info[VIOMAXBLOCKDMA];
72};
73
74struct vioblocklpevent {
75 struct HvLpEvent event;
76 u32 reserved;
77 u16 version;
78 u16 sub_result;
79 u16 disk;
80 u16 flags;
81 union {
82 struct open_data open_data;
83 struct rw_data rw_data;
84 u64 changed;
85 } u;
86};
87
88#define vioblockflags_ro 0x0001
89
90enum vioblocksubtype {
91 vioblockopen = 0x0001,
92 vioblockclose = 0x0002,
93 vioblockread = 0x0003,
94 vioblockwrite = 0x0004,
95 vioblockflush = 0x0005,
96 vioblockcheck = 0x0007
97};
98
99struct viocdlpevent {
100 struct HvLpEvent event;
101 u32 reserved;
102 u16 version;
103 u16 sub_result;
104 u16 disk;
105 u16 flags;
106 u32 token;
107 u64 offset; /* On open, max number of disks */
108 u64 len; /* On open, size of the disk */
109 u32 block_size; /* Only set on open */
110 u32 media_size; /* Only set on open */
111};
112
113enum viocdsubtype {
114 viocdopen = 0x0001,
115 viocdclose = 0x0002,
116 viocdread = 0x0003,
117 viocdwrite = 0x0004,
118 viocdlockdoor = 0x0005,
119 viocdgetinfo = 0x0006,
120 viocdcheck = 0x0007
121};
122
123struct viotapelpevent {
124 struct HvLpEvent event;
125 u32 reserved;
126 u16 version;
127 u16 sub_type_result;
128 u16 tape;
129 u16 flags;
130 u32 token;
131 u64 len;
132 union {
133 struct {
134 u32 tape_op;
135 u32 count;
136 } op;
137 struct {
138 u32 type;
139 u32 resid;
140 u32 dsreg;
141 u32 gstat;
142 u32 erreg;
143 u32 file_no;
144 u32 block_no;
145 } get_status;
146 struct {
147 u32 block_no;
148 } get_pos;
149 } u;
150};
151
152enum viotapesubtype {
153 viotapeopen = 0x0001,
154 viotapeclose = 0x0002,
155 viotaperead = 0x0003,
156 viotapewrite = 0x0004,
157 viotapegetinfo = 0x0005,
158 viotapeop = 0x0006,
159 viotapegetpos = 0x0007,
160 viotapesetpos = 0x0008,
161 viotapegetstatus = 0x0009
162};
163
164/*
165 * Each subtype can register a handler to process their events.
166 * The handler must have this interface.
167 */
168typedef void (vio_event_handler_t) (struct HvLpEvent * event);
169
170extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
171extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
172extern int vio_setHandler(int subtype, vio_event_handler_t * beh);
173extern int vio_clearHandler(int subtype);
174extern int viopath_isactive(HvLpIndex lp);
175extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
176extern HvLpInstanceId viopath_targetinst(HvLpIndex lp);
177extern void vio_set_hostlp(void);
178extern void *vio_get_event_buffer(int subtype);
179extern void vio_free_event_buffer(int subtype, void *buffer);
180
181extern struct vio_dev *vio_create_viodasd(u32 unit);
182
183extern HvLpIndex viopath_hostLp;
184extern HvLpIndex viopath_ourLp;
185
186#define VIOCHAR_MAX_DATA 200
187
188#define VIOMAJOR_SUBTYPE_MASK 0xff00
189#define VIOMINOR_SUBTYPE_MASK 0x00ff
190#define VIOMAJOR_SUBTYPE_SHIFT 8
191
192#define VIOVERSION 0x0101
193
194/*
195 * This is the general structure for VIO errors; each module should have
196 * a table of them, and each table should be terminated by an entry of
197 * { 0, 0, NULL }. Then, to find a specific error message, a module
198 * should pass its local table and the return code.
199 */
200struct vio_error_entry {
201 u16 rc;
202 int errno;
203 const char *msg;
204};
205extern const struct vio_error_entry *vio_lookup_rc(
206 const struct vio_error_entry *local_table, u16 rc);
207
208enum viosubtypes {
209 viomajorsubtype_monitor = 0x0100,
210 viomajorsubtype_blockio = 0x0200,
211 viomajorsubtype_chario = 0x0300,
212 viomajorsubtype_config = 0x0400,
213 viomajorsubtype_cdio = 0x0500,
214 viomajorsubtype_tape = 0x0600,
215 viomajorsubtype_scsi = 0x0700
216};
217
218enum vioconfigsubtype {
219 vioconfigget = 0x0001,
220};
221
222enum viorc {
223 viorc_good = 0x0000,
224 viorc_noConnection = 0x0001,
225 viorc_noReceiver = 0x0002,
226 viorc_noBufferAvailable = 0x0003,
227 viorc_invalidMessageType = 0x0004,
228 viorc_invalidRange = 0x0201,
229 viorc_invalidToken = 0x0202,
230 viorc_DMAError = 0x0203,
231 viorc_useError = 0x0204,
232 viorc_releaseError = 0x0205,
233 viorc_invalidDisk = 0x0206,
234 viorc_openRejected = 0x0301
235};
236
237/*
238 * The structure of the events that flow between us and OS/400 for chario
239 * events. You can't mess with this unless the OS/400 side changes too.
240 */
241struct viocharlpevent {
242 struct HvLpEvent event;
243 u32 reserved;
244 u16 version;
245 u16 subtype_result_code;
246 u8 virtual_device;
247 u8 len;
248 u8 data[VIOCHAR_MAX_DATA];
249};
250
251#define VIOCHAR_WINDOW 10
252
253enum viocharsubtype {
254 viocharopen = 0x0001,
255 viocharclose = 0x0002,
256 viochardata = 0x0003,
257 viocharack = 0x0004,
258 viocharconfig = 0x0005
259};
260
261enum viochar_rc {
262 viochar_rc_ebusy = 1
263};
264
265#endif /* _ASM_POWERPC_ISERIES_VIO_H */
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index e0298d26ce5d..a76254af0aaa 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -41,15 +41,7 @@
41 * We only have to have statically allocated lppaca structs on 41 * We only have to have statically allocated lppaca structs on
42 * legacy iSeries, which supports at most 64 cpus. 42 * legacy iSeries, which supports at most 64 cpus.
43 */ 43 */
44#ifdef CONFIG_PPC_ISERIES
45#if NR_CPUS < 64
46#define NR_LPPACAS NR_CPUS
47#else
48#define NR_LPPACAS 64
49#endif
50#else /* not iSeries */
51#define NR_LPPACAS 1 44#define NR_LPPACAS 1
52#endif
53 45
54 46
55/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k 47/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index a5b7c56237f9..c65b9294376e 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -273,7 +273,6 @@ struct mpic
273 unsigned int isu_size; 273 unsigned int isu_size;
274 unsigned int isu_shift; 274 unsigned int isu_shift;
275 unsigned int isu_mask; 275 unsigned int isu_mask;
276 unsigned int irq_count;
277 /* Number of sources */ 276 /* Number of sources */
278 unsigned int num_sources; 277 unsigned int num_sources;
279 /* default senses array */ 278 /* default senses array */
@@ -349,8 +348,6 @@ struct mpic
349#define MPIC_U3_HT_IRQS 0x00000004 348#define MPIC_U3_HT_IRQS 0x00000004
350/* Broken IPI registers (autodetected) */ 349/* Broken IPI registers (autodetected) */
351#define MPIC_BROKEN_IPI 0x00000008 350#define MPIC_BROKEN_IPI 0x00000008
352/* MPIC wants a reset */
353#define MPIC_WANTS_RESET 0x00000010
354/* Spurious vector requires EOI */ 351/* Spurious vector requires EOI */
355#define MPIC_SPV_EOI 0x00000020 352#define MPIC_SPV_EOI 0x00000020
356/* No passthrough disable */ 353/* No passthrough disable */
@@ -363,15 +360,11 @@ struct mpic
363#define MPIC_ENABLE_MCK 0x00000200 360#define MPIC_ENABLE_MCK 0x00000200
364/* Disable bias among target selection, spread interrupts evenly */ 361/* Disable bias among target selection, spread interrupts evenly */
365#define MPIC_NO_BIAS 0x00000400 362#define MPIC_NO_BIAS 0x00000400
366/* Ignore NIRQS as reported by FRR */
367#define MPIC_BROKEN_FRR_NIRQS 0x00000800
368/* Destination only supports a single CPU at a time */ 363/* Destination only supports a single CPU at a time */
369#define MPIC_SINGLE_DEST_CPU 0x00001000 364#define MPIC_SINGLE_DEST_CPU 0x00001000
370/* Enable CoreInt delivery of interrupts */ 365/* Enable CoreInt delivery of interrupts */
371#define MPIC_ENABLE_COREINT 0x00002000 366#define MPIC_ENABLE_COREINT 0x00002000
372/* Disable resetting of the MPIC. 367/* Do not reset the MPIC during initialization */
373 * NOTE: This flag trumps MPIC_WANTS_RESET.
374 */
375#define MPIC_NO_RESET 0x00004000 368#define MPIC_NO_RESET 0x00004000
376/* Freescale MPIC (compatible includes "fsl,mpic") */ 369/* Freescale MPIC (compatible includes "fsl,mpic") */
377#define MPIC_FSL 0x00008000 370#define MPIC_FSL 0x00008000
diff --git a/arch/powerpc/include/asm/mpic_msgr.h b/arch/powerpc/include/asm/mpic_msgr.h
new file mode 100644
index 000000000000..3ec37dc9003e
--- /dev/null
+++ b/arch/powerpc/include/asm/mpic_msgr.h
@@ -0,0 +1,132 @@
1/*
2 * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; version 2 of the
7 * License.
8 *
9 */
10
11#ifndef _ASM_MPIC_MSGR_H
12#define _ASM_MPIC_MSGR_H
13
14#include <linux/types.h>
15#include <linux/spinlock.h>
16
17struct mpic_msgr {
18 u32 __iomem *base;
19 u32 __iomem *mer;
20 int irq;
21 unsigned char in_use;
22 raw_spinlock_t lock;
23 int num;
24};
25
26/* Get a message register
27 *
28 * @reg_num: the MPIC message register to get
29 *
30 * A pointer to the message register is returned. If
31 * the message register asked for is already in use, then
32 * EBUSY is returned. If the number given is not associated
33 * with an actual message register, then ENODEV is returned.
34 * Successfully getting the register marks it as in use.
35 */
36extern struct mpic_msgr *mpic_msgr_get(unsigned int reg_num);
37
38/* Relinquish a message register
39 *
40 * @msgr: the message register to return
41 *
42 * Disables the given message register and marks it as free.
43 * After this call has completed successully the message
44 * register is available to be acquired by a call to
45 * mpic_msgr_get.
46 */
47extern void mpic_msgr_put(struct mpic_msgr *msgr);
48
49/* Enable a message register
50 *
51 * @msgr: the message register to enable
52 *
53 * The given message register is enabled for sending
54 * messages.
55 */
56extern void mpic_msgr_enable(struct mpic_msgr *msgr);
57
58/* Disable a message register
59 *
60 * @msgr: the message register to disable
61 *
62 * The given message register is disabled for sending
63 * messages.
64 */
65extern void mpic_msgr_disable(struct mpic_msgr *msgr);
66
67/* Write a message to a message register
68 *
69 * @msgr: the message register to write to
70 * @message: the message to write
71 *
72 * The given 32-bit message is written to the given message
73 * register. Writing to an enabled message registers fires
74 * an interrupt.
75 */
76static inline void mpic_msgr_write(struct mpic_msgr *msgr, u32 message)
77{
78 out_be32(msgr->base, message);
79}
80
81/* Read a message from a message register
82 *
83 * @msgr: the message register to read from
84 *
85 * Returns the 32-bit value currently in the given message register.
86 * Upon reading the register any interrupts for that register are
87 * cleared.
88 */
89static inline u32 mpic_msgr_read(struct mpic_msgr *msgr)
90{
91 return in_be32(msgr->base);
92}
93
94/* Clear a message register
95 *
96 * @msgr: the message register to clear
97 *
98 * Clears any interrupts associated with the given message register.
99 */
100static inline void mpic_msgr_clear(struct mpic_msgr *msgr)
101{
102 (void) mpic_msgr_read(msgr);
103}
104
105/* Set the destination CPU for the message register
106 *
107 * @msgr: the message register whose destination is to be set
108 * @cpu_num: the Linux CPU number to bind the message register to
109 *
110 * Note that the CPU number given is the CPU number used by the kernel
111 * and *not* the actual hardware CPU number.
112 */
113static inline void mpic_msgr_set_destination(struct mpic_msgr *msgr,
114 u32 cpu_num)
115{
116 out_be32(msgr->base, 1 << get_hard_smp_processor_id(cpu_num));
117}
118
119/* Get the IRQ number for the message register
120 * @msgr: the message register whose IRQ is to be returned
121 *
122 * Returns the IRQ number associated with the given message register.
123 * NO_IRQ is returned if this message register is not capable of
124 * receiving interrupts. What message register can and cannot receive
125 * interrupts is specified in the device tree for the system.
126 */
127static inline int mpic_msgr_get_irq(struct mpic_msgr *msgr)
128{
129 return msgr->irq;
130}
131
132#endif
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 269c05a36d91..daf813fea91f 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -132,7 +132,7 @@ struct paca_struct {
132 u64 saved_msr; /* MSR saved here by enter_rtas */ 132 u64 saved_msr; /* MSR saved here by enter_rtas */
133 u16 trap_save; /* Used when bad stack is encountered */ 133 u16 trap_save; /* Used when bad stack is encountered */
134 u8 soft_enabled; /* irq soft-enable flag */ 134 u8 soft_enabled; /* irq soft-enable flag */
135 u8 hard_enabled; /* set if irqs are enabled in MSR */ 135 u8 irq_happened; /* irq happened while soft-disabled */
136 u8 io_sync; /* writel() needs spin_unlock sync */ 136 u8 io_sync; /* writel() needs spin_unlock sync */
137 u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ 137 u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */
138 u8 nap_state_lost; /* NV GPR values lost in power7_idle */ 138 u8 nap_state_lost; /* NV GPR values lost in power7_idle */
diff --git a/arch/powerpc/include/asm/phyp_dump.h b/arch/powerpc/include/asm/phyp_dump.h
deleted file mode 100644
index fa74c6c3e106..000000000000
--- a/arch/powerpc/include/asm/phyp_dump.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 * Hypervisor-assisted dump
3 *
4 * Linas Vepstas, Manish Ahuja 2008
5 * Copyright 2008 IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#ifndef _PPC64_PHYP_DUMP_H
14#define _PPC64_PHYP_DUMP_H
15
16#ifdef CONFIG_PHYP_DUMP
17
18/* The RMR region will be saved for later dumping
19 * whenever the kernel crashes. Set this to 256MB. */
20#define PHYP_DUMP_RMR_START 0x0
21#define PHYP_DUMP_RMR_END (1UL<<28)
22
23struct phyp_dump {
24 /* Memory that is reserved during very early boot. */
25 unsigned long init_reserve_start;
26 unsigned long init_reserve_size;
27 /* cmd line options during boot */
28 unsigned long reserve_bootvar;
29 unsigned long phyp_dump_at_boot;
30 /* Check status during boot if dump supported, active & present*/
31 unsigned long phyp_dump_configured;
32 unsigned long phyp_dump_is_active;
33 /* store cpu & hpte size */
34 unsigned long cpu_state_size;
35 unsigned long hpte_region_size;
36 /* previous scratch area values */
37 unsigned long reserved_scratch_addr;
38 unsigned long reserved_scratch_size;
39};
40
41extern struct phyp_dump *phyp_dump_info;
42
43int early_init_dt_scan_phyp_dump(unsigned long node,
44 const char *uname, int depth, void *data);
45
46#endif /* CONFIG_PHYP_DUMP */
47#endif /* _PPC64_PHYP_DUMP_H */
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 6d422979ebaf..e660b37aa7d0 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -47,92 +47,21 @@ extern int rtas_setup_phb(struct pci_controller *phb);
47 47
48extern unsigned long pci_probe_only; 48extern unsigned long pci_probe_only;
49 49
50/* ---- EEH internal-use-only related routines ---- */
51#ifdef CONFIG_EEH 50#ifdef CONFIG_EEH
52 51
52void pci_addr_cache_build(void);
53void pci_addr_cache_insert_device(struct pci_dev *dev); 53void pci_addr_cache_insert_device(struct pci_dev *dev);
54void pci_addr_cache_remove_device(struct pci_dev *dev); 54void pci_addr_cache_remove_device(struct pci_dev *dev);
55void pci_addr_cache_build(void); 55struct pci_dev *pci_addr_cache_get_device(unsigned long addr);
56struct pci_dev *pci_get_device_by_addr(unsigned long addr); 56void eeh_slot_error_detail(struct eeh_dev *edev, int severity);
57 57int eeh_pci_enable(struct eeh_dev *edev, int function);
58/** 58int eeh_reset_pe(struct eeh_dev *);
59 * eeh_slot_error_detail -- record and EEH error condition to the log 59void eeh_restore_bars(struct eeh_dev *);
60 * @pdn: pci device node
61 * @severity: EEH_LOG_TEMP_FAILURE or EEH_LOG_PERM_FAILURE
62 *
63 * Obtains the EEH error details from the RTAS subsystem,
64 * and then logs these details with the RTAS error log system.
65 */
66#define EEH_LOG_TEMP_FAILURE 1
67#define EEH_LOG_PERM_FAILURE 2
68void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
69
70/**
71 * rtas_pci_enable - enable IO transfers for this slot
72 * @pdn: pci device node
73 * @function: either EEH_THAW_MMIO or EEH_THAW_DMA
74 *
75 * Enable I/O transfers to this slot
76 */
77#define EEH_THAW_MMIO 2
78#define EEH_THAW_DMA 3
79int rtas_pci_enable(struct pci_dn *pdn, int function);
80
81/**
82 * rtas_set_slot_reset -- unfreeze a frozen slot
83 * @pdn: pci device node
84 *
85 * Clear the EEH-frozen condition on a slot. This routine
86 * does this by asserting the PCI #RST line for 1/8th of
87 * a second; this routine will sleep while the adapter is
88 * being reset.
89 *
90 * Returns a non-zero value if the reset failed.
91 */
92int rtas_set_slot_reset (struct pci_dn *);
93int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs);
94
95/**
96 * eeh_restore_bars - Restore device configuration info.
97 * @pdn: pci device node
98 *
99 * A reset of a PCI device will clear out its config space.
100 * This routines will restore the config space for this
101 * device, and is children, to values previously obtained
102 * from the firmware.
103 */
104void eeh_restore_bars(struct pci_dn *);
105
106/**
107 * rtas_configure_bridge -- firmware initialization of pci bridge
108 * @pdn: pci device node
109 *
110 * Ask the firmware to configure all PCI bridges devices
111 * located behind the indicated node. Required after a
112 * pci device reset. Does essentially the same hing as
113 * eeh_restore_bars, but for brdges, and lets firmware
114 * do the work.
115 */
116void rtas_configure_bridge(struct pci_dn *);
117
118int rtas_write_config(struct pci_dn *, int where, int size, u32 val); 60int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
119int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); 61int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
120 62void eeh_mark_slot(struct device_node *dn, int mode_flag);
121/** 63void eeh_clear_slot(struct device_node *dn, int mode_flag);
122 * eeh_mark_slot -- set mode flags for pertition endpoint 64struct device_node *eeh_find_device_pe(struct device_node *dn);
123 * @pdn: pci device node
124 *
125 * mark and clear slots: find "partition endpoint" PE and set or
126 * clear the flags for each subnode of the PE.
127 */
128void eeh_mark_slot (struct device_node *dn, int mode_flag);
129void eeh_clear_slot (struct device_node *dn, int mode_flag);
130
131/**
132 * find_device_pe -- Find the associated "Partiationable Endpoint" PE
133 * @pdn: pci device node
134 */
135struct device_node * find_device_pe(struct device_node *dn);
136 65
137void eeh_sysfs_add_device(struct pci_dev *pdev); 66void eeh_sysfs_add_device(struct pci_dev *pdev);
138void eeh_sysfs_remove_device(struct pci_dev *pdev); 67void eeh_sysfs_remove_device(struct pci_dev *pdev);
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 368f72f79808..50f73aa2ba21 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -60,6 +60,8 @@ BEGIN_FW_FTR_SECTION; \
60 cmpd cr1,r11,r10; \ 60 cmpd cr1,r11,r10; \
61 beq+ cr1,33f; \ 61 beq+ cr1,33f; \
62 bl .accumulate_stolen_time; \ 62 bl .accumulate_stolen_time; \
63 ld r12,_MSR(r1); \
64 andi. r10,r12,MSR_PR; /* Restore cr0 (coming from user) */ \
6333: \ 6533: \
64END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) 66END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
65 67
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 7fdc2c0b7fa0..b1a215eabef6 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1079,30 +1079,12 @@
1079 1079
1080#define proc_trap() asm volatile("trap") 1080#define proc_trap() asm volatile("trap")
1081 1081
1082#ifdef CONFIG_PPC64 1082#define __get_SP() ({unsigned long sp; \
1083 1083 asm volatile("mr %0,1": "=r" (sp)); sp;})
1084extern void ppc64_runlatch_on(void);
1085extern void __ppc64_runlatch_off(void);
1086
1087#define ppc64_runlatch_off() \
1088 do { \
1089 if (cpu_has_feature(CPU_FTR_CTRL) && \
1090 test_thread_flag(TIF_RUNLATCH)) \
1091 __ppc64_runlatch_off(); \
1092 } while (0)
1093 1084
1094extern unsigned long scom970_read(unsigned int address); 1085extern unsigned long scom970_read(unsigned int address);
1095extern void scom970_write(unsigned int address, unsigned long value); 1086extern void scom970_write(unsigned int address, unsigned long value);
1096 1087
1097#else
1098#define ppc64_runlatch_on()
1099#define ppc64_runlatch_off()
1100
1101#endif /* CONFIG_PPC64 */
1102
1103#define __get_SP() ({unsigned long sp; \
1104 asm volatile("mr %0,1": "=r" (sp)); sp;})
1105
1106struct pt_regs; 1088struct pt_regs;
1107 1089
1108extern void ppc_save_regs(struct pt_regs *regs); 1090extern void ppc_save_regs(struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 500fe1dc43e6..8a97aa7289d3 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -62,6 +62,7 @@
62#define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */ 62#define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */
63#define SPRN_MAS8 0x155 /* MMU Assist Register 8 */ 63#define SPRN_MAS8 0x155 /* MMU Assist Register 8 */
64#define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */ 64#define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */
65#define SPRN_TLB1PS 0x159 /* TLB 1 Page Size Register */
65#define SPRN_MAS5_MAS6 0x15c /* MMU Assist Register 5 || 6 */ 66#define SPRN_MAS5_MAS6 0x15c /* MMU Assist Register 5 || 6 */
66#define SPRN_MAS8_MAS1 0x15d /* MMU Assist Register 8 || 1 */ 67#define SPRN_MAS8_MAS1 0x15d /* MMU Assist Register 8 || 1 */
67#define SPRN_EPTCFG 0x15e /* Embedded Page Table Config */ 68#define SPRN_EPTCFG 0x15e /* Embedded Page Table Config */
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
index f9611bd69ed2..7124fc06ad47 100644
--- a/arch/powerpc/include/asm/spinlock.h
+++ b/arch/powerpc/include/asm/spinlock.h
@@ -23,7 +23,6 @@
23#ifdef CONFIG_PPC64 23#ifdef CONFIG_PPC64
24#include <asm/paca.h> 24#include <asm/paca.h>
25#include <asm/hvcall.h> 25#include <asm/hvcall.h>
26#include <asm/iseries/hv_call.h>
27#endif 26#endif
28#include <asm/asm-compat.h> 27#include <asm/asm-compat.h>
29#include <asm/synch.h> 28#include <asm/synch.h>
@@ -95,12 +94,12 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
95 * value. 94 * value.
96 */ 95 */
97 96
98#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) 97#if defined(CONFIG_PPC_SPLPAR)
99/* We only yield to the hypervisor if we are in shared processor mode */ 98/* We only yield to the hypervisor if we are in shared processor mode */
100#define SHARED_PROCESSOR (get_lppaca()->shared_proc) 99#define SHARED_PROCESSOR (get_lppaca()->shared_proc)
101extern void __spin_yield(arch_spinlock_t *lock); 100extern void __spin_yield(arch_spinlock_t *lock);
102extern void __rw_yield(arch_rwlock_t *lock); 101extern void __rw_yield(arch_rwlock_t *lock);
103#else /* SPLPAR || ISERIES */ 102#else /* SPLPAR */
104#define __spin_yield(x) barrier() 103#define __spin_yield(x) barrier()
105#define __rw_yield(x) barrier() 104#define __rw_yield(x) barrier()
106#define SHARED_PROCESSOR 0 105#define SHARED_PROCESSOR 0
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h
index c377457d1b89..a02883d5af43 100644
--- a/arch/powerpc/include/asm/system.h
+++ b/arch/powerpc/include/asm/system.h
@@ -550,5 +550,43 @@ extern void reloc_got2(unsigned long);
550 550
551extern struct dentry *powerpc_debugfs_root; 551extern struct dentry *powerpc_debugfs_root;
552 552
553#ifdef CONFIG_PPC64
554
555extern void __ppc64_runlatch_on(void);
556extern void __ppc64_runlatch_off(void);
557
558/*
559 * We manually hard enable-disable, this is called
560 * in the idle loop and we don't want to mess up
561 * with soft-disable/enable & interrupt replay.
562 */
563#define ppc64_runlatch_off() \
564 do { \
565 if (cpu_has_feature(CPU_FTR_CTRL) && \
566 test_thread_local_flags(_TLF_RUNLATCH)) { \
567 unsigned long msr = mfmsr(); \
568 __hard_irq_disable(); \
569 __ppc64_runlatch_off(); \
570 if (msr & MSR_EE) \
571 __hard_irq_enable(); \
572 } \
573 } while (0)
574
575#define ppc64_runlatch_on() \
576 do { \
577 if (cpu_has_feature(CPU_FTR_CTRL) && \
578 !test_thread_local_flags(_TLF_RUNLATCH)) { \
579 unsigned long msr = mfmsr(); \
580 __hard_irq_disable(); \
581 __ppc64_runlatch_on(); \
582 if (msr & MSR_EE) \
583 __hard_irq_enable(); \
584 } \
585 } while (0)
586#else
587#define ppc64_runlatch_on()
588#define ppc64_runlatch_off()
589#endif /* CONFIG_PPC64 */
590
553#endif /* __KERNEL__ */ 591#endif /* __KERNEL__ */
554#endif /* _ASM_POWERPC_SYSTEM_H */ 592#endif /* _ASM_POWERPC_SYSTEM_H */
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 964714940961..4a741c7efd02 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -110,7 +110,6 @@ static inline struct thread_info *current_thread_info(void)
110#define TIF_NOERROR 12 /* Force successful syscall return */ 110#define TIF_NOERROR 12 /* Force successful syscall return */
111#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */ 111#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
112#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */ 112#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
113#define TIF_RUNLATCH 16 /* Is the runlatch enabled? */
114 113
115/* as above, but as bit values */ 114/* as above, but as bit values */
116#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 115#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -141,11 +140,13 @@ static inline struct thread_info *current_thread_info(void)
141#define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */ 140#define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */
142#define TLF_RESTORE_SIGMASK 2 /* Restore signal mask in do_signal */ 141#define TLF_RESTORE_SIGMASK 2 /* Restore signal mask in do_signal */
143#define TLF_LAZY_MMU 3 /* tlb_batch is active */ 142#define TLF_LAZY_MMU 3 /* tlb_batch is active */
143#define TLF_RUNLATCH 4 /* Is the runlatch enabled? */
144 144
145#define _TLF_NAPPING (1 << TLF_NAPPING) 145#define _TLF_NAPPING (1 << TLF_NAPPING)
146#define _TLF_SLEEPING (1 << TLF_SLEEPING) 146#define _TLF_SLEEPING (1 << TLF_SLEEPING)
147#define _TLF_RESTORE_SIGMASK (1 << TLF_RESTORE_SIGMASK) 147#define _TLF_RESTORE_SIGMASK (1 << TLF_RESTORE_SIGMASK)
148#define _TLF_LAZY_MMU (1 << TLF_LAZY_MMU) 148#define _TLF_LAZY_MMU (1 << TLF_LAZY_MMU)
149#define _TLF_RUNLATCH (1 << TLF_RUNLATCH)
149 150
150#ifndef __ASSEMBLY__ 151#ifndef __ASSEMBLY__
151#define HAVE_SET_RESTORE_SIGMASK 1 152#define HAVE_SET_RESTORE_SIGMASK 1
@@ -156,6 +157,12 @@ static inline void set_restore_sigmask(void)
156 set_bit(TIF_SIGPENDING, &ti->flags); 157 set_bit(TIF_SIGPENDING, &ti->flags);
157} 158}
158 159
160static inline bool test_thread_local_flags(unsigned int flags)
161{
162 struct thread_info *ti = current_thread_info();
163 return (ti->local_flags & flags) != 0;
164}
165
159#ifdef CONFIG_PPC64 166#ifdef CONFIG_PPC64
160#define is_32bit_task() (test_thread_flag(TIF_32BIT)) 167#define is_32bit_task() (test_thread_flag(TIF_32BIT))
161#else 168#else
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index 7eb10fb96cd0..2136f58a54e8 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -18,11 +18,6 @@
18#include <linux/percpu.h> 18#include <linux/percpu.h>
19 19
20#include <asm/processor.h> 20#include <asm/processor.h>
21#ifdef CONFIG_PPC_ISERIES
22#include <asm/paca.h>
23#include <asm/firmware.h>
24#include <asm/iseries/hv_call.h>
25#endif
26 21
27/* time.c */ 22/* time.c */
28extern unsigned long tb_ticks_per_jiffy; 23extern unsigned long tb_ticks_per_jiffy;
@@ -167,15 +162,6 @@ static inline void set_dec(int val)
167#ifndef CONFIG_BOOKE 162#ifndef CONFIG_BOOKE
168 --val; 163 --val;
169#endif 164#endif
170#ifdef CONFIG_PPC_ISERIES
171 if (firmware_has_feature(FW_FEATURE_ISERIES) &&
172 get_lppaca()->shared_proc) {
173 get_lppaca()->virtual_decr = val;
174 if (get_dec() > val)
175 HvCall_setVirtualDecr();
176 return;
177 }
178#endif
179 mtspr(SPRN_DEC, val); 165 mtspr(SPRN_DEC, val);
180#endif /* not 40x or 8xx_CPU6 */ 166#endif /* not 40x or 8xx_CPU6 */
181} 167}
@@ -217,7 +203,6 @@ DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
217#endif 203#endif
218 204
219extern void secondary_cpu_time_init(void); 205extern void secondary_cpu_time_init(void);
220extern void iSeries_time_init_early(void);
221 206
222DECLARE_PER_CPU(u64, decrementers_next_tb); 207DECLARE_PER_CPU(u64, decrementers_next_tb);
223 208
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ee728e433aa2..f5808a35688c 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_IBMVIO) += vio.o
60obj-$(CONFIG_IBMEBUS) += ibmebus.o 60obj-$(CONFIG_IBMEBUS) += ibmebus.o
61obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 61obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
62obj-$(CONFIG_CRASH_DUMP) += crash_dump.o 62obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
63obj-$(CONFIG_FA_DUMP) += fadump.o
63ifeq ($(CONFIG_PPC32),y) 64ifeq ($(CONFIG_PPC32),y)
64obj-$(CONFIG_E500) += idle_e500.o 65obj-$(CONFIG_E500) += idle_e500.o
65endif 66endif
@@ -113,15 +114,6 @@ obj-$(CONFIG_PPC_IO_WORKAROUNDS) += io-workarounds.o
113obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 114obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
114obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 115obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
115obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o 116obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
116obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
117
118obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
119obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
120 power5+-pmu.o power6-pmu.o power7-pmu.o
121obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
122
123obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o
124obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o
125 117
126obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o 118obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
127 119
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 04caee7d9bc1..cc492e48ddfa 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -46,9 +46,6 @@
46#include <asm/hvcall.h> 46#include <asm/hvcall.h>
47#include <asm/xics.h> 47#include <asm/xics.h>
48#endif 48#endif
49#ifdef CONFIG_PPC_ISERIES
50#include <asm/iseries/alpaca.h>
51#endif
52#ifdef CONFIG_PPC_POWERNV 49#ifdef CONFIG_PPC_POWERNV
53#include <asm/opal.h> 50#include <asm/opal.h>
54#endif 51#endif
@@ -147,7 +144,7 @@ int main(void)
147 DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase)); 144 DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
148 DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr)); 145 DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
149 DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); 146 DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
150 DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); 147 DEFINE(PACAIRQHAPPENED, offsetof(struct paca_struct, irq_happened));
151 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); 148 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
152#ifdef CONFIG_PPC_MM_SLICES 149#ifdef CONFIG_PPC_MM_SLICES
153 DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct, 150 DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
@@ -384,17 +381,6 @@ int main(void)
384 DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry)); 381 DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
385#endif 382#endif
386 383
387#ifdef CONFIG_PPC_ISERIES
388 /* the assembler miscalculates the VSID values */
389 DEFINE(PAGE_OFFSET_ESID, GET_ESID(PAGE_OFFSET));
390 DEFINE(PAGE_OFFSET_VSID, KERNEL_VSID(PAGE_OFFSET));
391 DEFINE(VMALLOC_START_ESID, GET_ESID(VMALLOC_START));
392 DEFINE(VMALLOC_START_VSID, KERNEL_VSID(VMALLOC_START));
393
394 /* alpaca */
395 DEFINE(ALPACA_SIZE, sizeof(struct alpaca));
396#endif
397
398 DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE); 384 DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
399 DEFINE(PTE_SIZE, sizeof(pte_t)); 385 DEFINE(PTE_SIZE, sizeof(pte_t));
400 386
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 81db9e2a8a20..138ae183c440 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1816,7 +1816,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
1816 .platform = "ppc440", 1816 .platform = "ppc440",
1817 }, 1817 },
1818 { /* 464 in APM821xx */ 1818 { /* 464 in APM821xx */
1819 .pvr_mask = 0xffffff00, 1819 .pvr_mask = 0xfffffff0,
1820 .pvr_value = 0x12C41C80, 1820 .pvr_value = 0x12C41C80,
1821 .cpu_name = "APM821XX", 1821 .cpu_name = "APM821XX",
1822 .cpu_features = CPU_FTRS_44X, 1822 .cpu_features = CPU_FTRS_44X,
@@ -2019,6 +2019,24 @@ static struct cpu_spec __initdata cpu_specs[] = {
2019 .machine_check = machine_check_e500mc, 2019 .machine_check = machine_check_e500mc,
2020 .platform = "ppce5500", 2020 .platform = "ppce5500",
2021 }, 2021 },
2022 { /* e6500 */
2023 .pvr_mask = 0xffff0000,
2024 .pvr_value = 0x80400000,
2025 .cpu_name = "e6500",
2026 .cpu_features = CPU_FTRS_E6500,
2027 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
2028 .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
2029 MMU_FTR_USE_TLBILX,
2030 .icache_bsize = 64,
2031 .dcache_bsize = 64,
2032 .num_pmcs = 4,
2033 .oprofile_cpu_type = "ppc/e6500",
2034 .oprofile_type = PPC_OPROFILE_FSL_EMB,
2035 .cpu_setup = __setup_cpu_e5500,
2036 .cpu_restore = __restore_cpu_e5500,
2037 .machine_check = machine_check_e500mc,
2038 .platform = "ppce6500",
2039 },
2022#ifdef CONFIG_PPC32 2040#ifdef CONFIG_PPC32
2023 { /* default match */ 2041 { /* default match */
2024 .pvr_mask = 0x00000000, 2042 .pvr_mask = 0x00000000,
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index 2cc451aaaca7..5b25c8060fd6 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -37,6 +37,8 @@ void doorbell_exception(struct pt_regs *regs)
37 37
38 irq_enter(); 38 irq_enter();
39 39
40 may_hard_irq_enable();
41
40 smp_ipi_demux(); 42 smp_ipi_demux();
41 43
42 irq_exit(); 44 irq_exit();
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 866462cbe2d8..f8a7a1a1a9f4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -32,6 +32,7 @@
32#include <asm/ptrace.h> 32#include <asm/ptrace.h>
33#include <asm/irqflags.h> 33#include <asm/irqflags.h>
34#include <asm/ftrace.h> 34#include <asm/ftrace.h>
35#include <asm/hw_irq.h>
35 36
36/* 37/*
37 * System calls. 38 * System calls.
@@ -115,39 +116,33 @@ BEGIN_FW_FTR_SECTION
115END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) 116END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
116#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */ 117#endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */
117 118
118#ifdef CONFIG_TRACE_IRQFLAGS 119 /*
119 bl .trace_hardirqs_on 120 * A syscall should always be called with interrupts enabled
120 REST_GPR(0,r1) 121 * so we just unconditionally hard-enable here. When some kind
121 REST_4GPRS(3,r1) 122 * of irq tracing is used, we additionally check that condition
122 REST_2GPRS(7,r1) 123 * is correct
123 addi r9,r1,STACK_FRAME_OVERHEAD 124 */
124 ld r12,_MSR(r1) 125#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_BUG)
125#endif /* CONFIG_TRACE_IRQFLAGS */ 126 lbz r10,PACASOFTIRQEN(r13)
126 li r10,1 127 xori r10,r10,1
127 stb r10,PACASOFTIRQEN(r13) 1281: tdnei r10,0
128 stb r10,PACAHARDIRQEN(r13) 129 EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING
129 std r10,SOFTE(r1) 130#endif
130#ifdef CONFIG_PPC_ISERIES
131BEGIN_FW_FTR_SECTION
132 /* Hack for handling interrupts when soft-enabling on iSeries */
133 cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
134 andi. r10,r12,MSR_PR /* from kernel */
135 crand 4*cr0+eq,4*cr1+eq,4*cr0+eq
136 bne 2f
137 b hardware_interrupt_entry
1382:
139END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
140#endif /* CONFIG_PPC_ISERIES */
141 131
142 /* Hard enable interrupts */
143#ifdef CONFIG_PPC_BOOK3E 132#ifdef CONFIG_PPC_BOOK3E
144 wrteei 1 133 wrteei 1
145#else 134#else
146 mfmsr r11 135 ld r11,PACAKMSR(r13)
147 ori r11,r11,MSR_EE 136 ori r11,r11,MSR_EE
148 mtmsrd r11,1 137 mtmsrd r11,1
149#endif /* CONFIG_PPC_BOOK3E */ 138#endif /* CONFIG_PPC_BOOK3E */
150 139
140 /* We do need to set SOFTE in the stack frame or the return
141 * from interrupt will be painful
142 */
143 li r10,1
144 std r10,SOFTE(r1)
145
151#ifdef SHOW_SYSCALLS 146#ifdef SHOW_SYSCALLS
152 bl .do_show_syscall 147 bl .do_show_syscall
153 REST_GPR(0,r1) 148 REST_GPR(0,r1)
@@ -198,16 +193,14 @@ syscall_exit:
198 andi. r10,r8,MSR_RI 193 andi. r10,r8,MSR_RI
199 beq- unrecov_restore 194 beq- unrecov_restore
200#endif 195#endif
201 196 /*
202 /* Disable interrupts so current_thread_info()->flags can't change, 197 * Disable interrupts so current_thread_info()->flags can't change,
203 * and so that we don't get interrupted after loading SRR0/1. 198 * and so that we don't get interrupted after loading SRR0/1.
204 */ 199 */
205#ifdef CONFIG_PPC_BOOK3E 200#ifdef CONFIG_PPC_BOOK3E
206 wrteei 0 201 wrteei 0
207#else 202#else
208 mfmsr r10 203 ld r10,PACAKMSR(r13)
209 rldicl r10,r10,48,1
210 rotldi r10,r10,16
211 mtmsrd r10,1 204 mtmsrd r10,1
212#endif /* CONFIG_PPC_BOOK3E */ 205#endif /* CONFIG_PPC_BOOK3E */
213 206
@@ -319,7 +312,7 @@ syscall_exit_work:
319#ifdef CONFIG_PPC_BOOK3E 312#ifdef CONFIG_PPC_BOOK3E
320 wrteei 1 313 wrteei 1
321#else 314#else
322 mfmsr r10 315 ld r10,PACAKMSR(r13)
323 ori r10,r10,MSR_EE 316 ori r10,r10,MSR_EE
324 mtmsrd r10,1 317 mtmsrd r10,1
325#endif /* CONFIG_PPC_BOOK3E */ 318#endif /* CONFIG_PPC_BOOK3E */
@@ -565,10 +558,8 @@ _GLOBAL(ret_from_except_lite)
565#ifdef CONFIG_PPC_BOOK3E 558#ifdef CONFIG_PPC_BOOK3E
566 wrteei 0 559 wrteei 0
567#else 560#else
568 mfmsr r10 /* Get current interrupt state */ 561 ld r10,PACAKMSR(r13) /* Get kernel MSR without EE */
569 rldicl r9,r10,48,1 /* clear MSR_EE */ 562 mtmsrd r10,1 /* Update machine state */
570 rotldi r9,r9,16
571 mtmsrd r9,1 /* Update machine state */
572#endif /* CONFIG_PPC_BOOK3E */ 563#endif /* CONFIG_PPC_BOOK3E */
573 564
574#ifdef CONFIG_PREEMPT 565#ifdef CONFIG_PREEMPT
@@ -591,25 +582,74 @@ _GLOBAL(ret_from_except_lite)
591 ld r4,TI_FLAGS(r9) 582 ld r4,TI_FLAGS(r9)
592 andi. r0,r4,_TIF_USER_WORK_MASK 583 andi. r0,r4,_TIF_USER_WORK_MASK
593 bne do_work 584 bne do_work
594#endif 585#endif /* !CONFIG_PREEMPT */
595 586
587 .globl fast_exc_return_irq
588fast_exc_return_irq:
596restore: 589restore:
597BEGIN_FW_FTR_SECTION 590 /*
591 * This is the main kernel exit path, we first check if we
592 * have to change our interrupt state.
593 */
598 ld r5,SOFTE(r1) 594 ld r5,SOFTE(r1)
599FW_FTR_SECTION_ELSE 595 lbz r6,PACASOFTIRQEN(r13)
600 b .Liseries_check_pending_irqs 596 cmpwi cr1,r5,0
601ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) 597 cmpw cr0,r5,r6
6022: 598 beq cr0,4f
603 TRACE_AND_RESTORE_IRQ(r5); 599
600 /* We do, handle disable first, which is easy */
601 bne cr1,3f;
602 li r0,0
603 stb r0,PACASOFTIRQEN(r13);
604 TRACE_DISABLE_INTS
605 b 4f
604 606
605 /* extract EE bit and use it to restore paca->hard_enabled */ 6073: /*
606 ld r3,_MSR(r1) 608 * We are about to soft-enable interrupts (we are hard disabled
607 rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ 609 * at this point). We check if there's anything that needs to
608 stb r4,PACAHARDIRQEN(r13) 610 * be replayed first.
611 */
612 lbz r0,PACAIRQHAPPENED(r13)
613 cmpwi cr0,r0,0
614 bne- restore_check_irq_replay
609 615
616 /*
617 * Get here when nothing happened while soft-disabled, just
618 * soft-enable and move-on. We will hard-enable as a side
619 * effect of rfi
620 */
621restore_no_replay:
622 TRACE_ENABLE_INTS
623 li r0,1
624 stb r0,PACASOFTIRQEN(r13);
625
626 /*
627 * Final return path. BookE is handled in a different file
628 */
6294:
610#ifdef CONFIG_PPC_BOOK3E 630#ifdef CONFIG_PPC_BOOK3E
611 b .exception_return_book3e 631 b .exception_return_book3e
612#else 632#else
633 /*
634 * Clear the reservation. If we know the CPU tracks the address of
635 * the reservation then we can potentially save some cycles and use
636 * a larx. On POWER6 and POWER7 this is significantly faster.
637 */
638BEGIN_FTR_SECTION
639 stdcx. r0,0,r1 /* to clear the reservation */
640FTR_SECTION_ELSE
641 ldarx r4,0,r1
642ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
643
644 /*
645 * Some code path such as load_up_fpu or altivec return directly
646 * here. They run entirely hard disabled and do not alter the
647 * interrupt state. They also don't use lwarx/stwcx. and thus
648 * are known not to leave dangling reservations.
649 */
650 .globl fast_exception_return
651fast_exception_return:
652 ld r3,_MSR(r1)
613 ld r4,_CTR(r1) 653 ld r4,_CTR(r1)
614 ld r0,_LINK(r1) 654 ld r0,_LINK(r1)
615 mtctr r4 655 mtctr r4
@@ -623,28 +663,18 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
623 beq- unrecov_restore 663 beq- unrecov_restore
624 664
625 /* 665 /*
626 * Clear the reservation. If we know the CPU tracks the address of
627 * the reservation then we can potentially save some cycles and use
628 * a larx. On POWER6 and POWER7 this is significantly faster.
629 */
630BEGIN_FTR_SECTION
631 stdcx. r0,0,r1 /* to clear the reservation */
632FTR_SECTION_ELSE
633 ldarx r4,0,r1
634ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
635
636 /*
637 * Clear RI before restoring r13. If we are returning to 666 * Clear RI before restoring r13. If we are returning to
638 * userspace and we take an exception after restoring r13, 667 * userspace and we take an exception after restoring r13,
639 * we end up corrupting the userspace r13 value. 668 * we end up corrupting the userspace r13 value.
640 */ 669 */
641 mfmsr r4 670 ld r4,PACAKMSR(r13) /* Get kernel MSR without EE */
642 andc r4,r4,r0 /* r0 contains MSR_RI here */ 671 andc r4,r4,r0 /* r0 contains MSR_RI here */
643 mtmsrd r4,1 672 mtmsrd r4,1
644 673
645 /* 674 /*
646 * r13 is our per cpu area, only restore it if we are returning to 675 * r13 is our per cpu area, only restore it if we are returning to
647 * userspace 676 * userspace the value stored in the stack frame may belong to
677 * another CPU.
648 */ 678 */
649 andi. r0,r3,MSR_PR 679 andi. r0,r3,MSR_PR
650 beq 1f 680 beq 1f
@@ -669,30 +699,55 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
669 699
670#endif /* CONFIG_PPC_BOOK3E */ 700#endif /* CONFIG_PPC_BOOK3E */
671 701
672.Liseries_check_pending_irqs: 702 /*
673#ifdef CONFIG_PPC_ISERIES 703 * Something did happen, check if a re-emit is needed
674 ld r5,SOFTE(r1) 704 * (this also clears paca->irq_happened)
675 cmpdi 0,r5,0 705 */
676 beq 2b 706restore_check_irq_replay:
677 /* Check for pending interrupts (iSeries) */ 707 /* XXX: We could implement a fast path here where we check
678 ld r3,PACALPPACAPTR(r13) 708 * for irq_happened being just 0x01, in which case we can
679 ld r3,LPPACAANYINT(r3) 709 * clear it and return. That means that we would potentially
680 cmpdi r3,0 710 * miss a decrementer having wrapped all the way around.
681 beq+ 2b /* skip do_IRQ if no interrupts */ 711 *
682 712 * Still, this might be useful for things like hash_page
683 li r3,0 713 */
684 stb r3,PACASOFTIRQEN(r13) /* ensure we are soft-disabled */ 714 bl .__check_irq_replay
685#ifdef CONFIG_TRACE_IRQFLAGS 715 cmpwi cr0,r3,0
686 bl .trace_hardirqs_off 716 beq restore_no_replay
687 mfmsr r10 717
688#endif 718 /*
689 ori r10,r10,MSR_EE 719 * We need to re-emit an interrupt. We do so by re-using our
690 mtmsrd r10 /* hard-enable again */ 720 * existing exception frame. We first change the trap value,
691 addi r3,r1,STACK_FRAME_OVERHEAD 721 * but we need to ensure we preserve the low nibble of it
692 bl .do_IRQ 722 */
693 b .ret_from_except_lite /* loop back and handle more */ 723 ld r4,_TRAP(r1)
694#endif 724 clrldi r4,r4,60
725 or r4,r4,r3
726 std r4,_TRAP(r1)
695 727
728 /*
729 * Then find the right handler and call it. Interrupts are
730 * still soft-disabled and we keep them that way.
731 */
732 cmpwi cr0,r3,0x500
733 bne 1f
734 addi r3,r1,STACK_FRAME_OVERHEAD;
735 bl .do_IRQ
736 b .ret_from_except
7371: cmpwi cr0,r3,0x900
738 bne 1f
739 addi r3,r1,STACK_FRAME_OVERHEAD;
740 bl .timer_interrupt
741 b .ret_from_except
742#ifdef CONFIG_PPC_BOOK3E
7431: cmpwi cr0,r3,0x280
744 bne 1f
745 addi r3,r1,STACK_FRAME_OVERHEAD;
746 bl .doorbell_exception
747 b .ret_from_except
748#endif /* CONFIG_PPC_BOOK3E */
7491: b .ret_from_except /* What else to do here ? */
750
696do_work: 751do_work:
697#ifdef CONFIG_PREEMPT 752#ifdef CONFIG_PREEMPT
698 andi. r0,r3,MSR_PR /* Returning to user mode? */ 753 andi. r0,r3,MSR_PR /* Returning to user mode? */
@@ -705,31 +760,22 @@ do_work:
705 crandc eq,cr1*4+eq,eq 760 crandc eq,cr1*4+eq,eq
706 bne restore 761 bne restore
707 762
708 /* Here we are preempting the current task. 763 /*
709 * 764 * Here we are preempting the current task. We want to make
710 * Ensure interrupts are soft-disabled. We also properly mark 765 * sure we are soft-disabled first
711 * the PACA to reflect the fact that they are hard-disabled
712 * and trace the change
713 */ 766 */
714 li r0,0 767 SOFT_DISABLE_INTS(r3,r4)
715 stb r0,PACASOFTIRQEN(r13)
716 stb r0,PACAHARDIRQEN(r13)
717 TRACE_DISABLE_INTS
718
719 /* Call the scheduler with soft IRQs off */
7201: bl .preempt_schedule_irq 7681: bl .preempt_schedule_irq
721 769
722 /* Hard-disable interrupts again (and update PACA) */ 770 /* Hard-disable interrupts again (and update PACA) */
723#ifdef CONFIG_PPC_BOOK3E 771#ifdef CONFIG_PPC_BOOK3E
724 wrteei 0 772 wrteei 0
725#else 773#else
726 mfmsr r10 774 ld r10,PACAKMSR(r13) /* Get kernel MSR without EE */
727 rldicl r10,r10,48,1
728 rotldi r10,r10,16
729 mtmsrd r10,1 775 mtmsrd r10,1
730#endif /* CONFIG_PPC_BOOK3E */ 776#endif /* CONFIG_PPC_BOOK3E */
731 li r0,0 777 li r0,PACA_IRQ_HARD_DIS
732 stb r0,PACAHARDIRQEN(r13) 778 stb r0,PACAIRQHAPPENED(r13)
733 779
734 /* Re-test flags and eventually loop */ 780 /* Re-test flags and eventually loop */
735 clrrdi r9,r1,THREAD_SHIFT 781 clrrdi r9,r1,THREAD_SHIFT
@@ -751,14 +797,12 @@ user_work:
751 797
752 andi. r0,r4,_TIF_NEED_RESCHED 798 andi. r0,r4,_TIF_NEED_RESCHED
753 beq 1f 799 beq 1f
754 li r5,1 800 bl .restore_interrupts
755 TRACE_AND_RESTORE_IRQ(r5);
756 bl .schedule 801 bl .schedule
757 b .ret_from_except_lite 802 b .ret_from_except_lite
758 803
7591: bl .save_nvgprs 8041: bl .save_nvgprs
760 li r5,1 805 bl .restore_interrupts
761 TRACE_AND_RESTORE_IRQ(r5);
762 addi r3,r1,STACK_FRAME_OVERHEAD 806 addi r3,r1,STACK_FRAME_OVERHEAD
763 bl .do_notify_resume 807 bl .do_notify_resume
764 b .ret_from_except 808 b .ret_from_except
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 429983c06f91..7215cc2495df 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -24,6 +24,7 @@
24#include <asm/ptrace.h> 24#include <asm/ptrace.h>
25#include <asm/ppc-opcode.h> 25#include <asm/ppc-opcode.h>
26#include <asm/mmu.h> 26#include <asm/mmu.h>
27#include <asm/hw_irq.h>
27 28
28/* XXX This will ultimately add space for a special exception save 29/* XXX This will ultimately add space for a special exception save
29 * structure used to save things like SRR0/SRR1, SPRGs, MAS, etc... 30 * structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
@@ -77,59 +78,55 @@
77#define SPRN_MC_SRR1 SPRN_MCSRR1 78#define SPRN_MC_SRR1 SPRN_MCSRR1
78 79
79#define NORMAL_EXCEPTION_PROLOG(n, addition) \ 80#define NORMAL_EXCEPTION_PROLOG(n, addition) \
80 EXCEPTION_PROLOG(n, GEN, addition##_GEN) 81 EXCEPTION_PROLOG(n, GEN, addition##_GEN(n))
81 82
82#define CRIT_EXCEPTION_PROLOG(n, addition) \ 83#define CRIT_EXCEPTION_PROLOG(n, addition) \
83 EXCEPTION_PROLOG(n, CRIT, addition##_CRIT) 84 EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n))
84 85
85#define DBG_EXCEPTION_PROLOG(n, addition) \ 86#define DBG_EXCEPTION_PROLOG(n, addition) \
86 EXCEPTION_PROLOG(n, DBG, addition##_DBG) 87 EXCEPTION_PROLOG(n, DBG, addition##_DBG(n))
87 88
88#define MC_EXCEPTION_PROLOG(n, addition) \ 89#define MC_EXCEPTION_PROLOG(n, addition) \
89 EXCEPTION_PROLOG(n, MC, addition##_MC) 90 EXCEPTION_PROLOG(n, MC, addition##_MC(n))
90 91
91 92
92/* Variants of the "addition" argument for the prolog 93/* Variants of the "addition" argument for the prolog
93 */ 94 */
94#define PROLOG_ADDITION_NONE_GEN 95#define PROLOG_ADDITION_NONE_GEN(n)
95#define PROLOG_ADDITION_NONE_CRIT 96#define PROLOG_ADDITION_NONE_CRIT(n)
96#define PROLOG_ADDITION_NONE_DBG 97#define PROLOG_ADDITION_NONE_DBG(n)
97#define PROLOG_ADDITION_NONE_MC 98#define PROLOG_ADDITION_NONE_MC(n)
98 99
99#define PROLOG_ADDITION_MASKABLE_GEN \ 100#define PROLOG_ADDITION_MASKABLE_GEN(n) \
100 lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ 101 lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \
101 cmpwi cr0,r11,0; /* yes -> go out of line */ \ 102 cmpwi cr0,r11,0; /* yes -> go out of line */ \
102 beq masked_interrupt_book3e; 103 beq masked_interrupt_book3e_##n
103 104
104#define PROLOG_ADDITION_2REGS_GEN \ 105#define PROLOG_ADDITION_2REGS_GEN(n) \
105 std r14,PACA_EXGEN+EX_R14(r13); \ 106 std r14,PACA_EXGEN+EX_R14(r13); \
106 std r15,PACA_EXGEN+EX_R15(r13) 107 std r15,PACA_EXGEN+EX_R15(r13)
107 108
108#define PROLOG_ADDITION_1REG_GEN \ 109#define PROLOG_ADDITION_1REG_GEN(n) \
109 std r14,PACA_EXGEN+EX_R14(r13); 110 std r14,PACA_EXGEN+EX_R14(r13);
110 111
111#define PROLOG_ADDITION_2REGS_CRIT \ 112#define PROLOG_ADDITION_2REGS_CRIT(n) \
112 std r14,PACA_EXCRIT+EX_R14(r13); \ 113 std r14,PACA_EXCRIT+EX_R14(r13); \
113 std r15,PACA_EXCRIT+EX_R15(r13) 114 std r15,PACA_EXCRIT+EX_R15(r13)
114 115
115#define PROLOG_ADDITION_2REGS_DBG \ 116#define PROLOG_ADDITION_2REGS_DBG(n) \
116 std r14,PACA_EXDBG+EX_R14(r13); \ 117 std r14,PACA_EXDBG+EX_R14(r13); \
117 std r15,PACA_EXDBG+EX_R15(r13) 118 std r15,PACA_EXDBG+EX_R15(r13)
118 119
119#define PROLOG_ADDITION_2REGS_MC \ 120#define PROLOG_ADDITION_2REGS_MC(n) \
120 std r14,PACA_EXMC+EX_R14(r13); \ 121 std r14,PACA_EXMC+EX_R14(r13); \
121 std r15,PACA_EXMC+EX_R15(r13) 122 std r15,PACA_EXMC+EX_R15(r13)
122 123
123#define PROLOG_ADDITION_DOORBELL_GEN \
124 lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \
125 cmpwi cr0,r11,0; /* yes -> go out of line */ \
126 beq masked_doorbell_book3e
127
128 124
129/* Core exception code for all exceptions except TLB misses. 125/* Core exception code for all exceptions except TLB misses.
130 * XXX: Needs to make SPRN_SPRG_GEN depend on exception type 126 * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
131 */ 127 */
132#define EXCEPTION_COMMON(n, excf, ints) \ 128#define EXCEPTION_COMMON(n, excf, ints) \
129exc_##n##_common: \
133 std r0,GPR0(r1); /* save r0 in stackframe */ \ 130 std r0,GPR0(r1); /* save r0 in stackframe */ \
134 std r2,GPR2(r1); /* save r2 in stackframe */ \ 131 std r2,GPR2(r1); /* save r2 in stackframe */ \
135 SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ 132 SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \
@@ -167,20 +164,21 @@
167 std r0,RESULT(r1); /* clear regs->result */ \ 164 std r0,RESULT(r1); /* clear regs->result */ \
168 ints; 165 ints;
169 166
170/* Variants for the "ints" argument */ 167/* Variants for the "ints" argument. This one does nothing when we want
168 * to keep interrupts in their original state
169 */
171#define INTS_KEEP 170#define INTS_KEEP
172#define INTS_DISABLE_SOFT \ 171
173 stb r0,PACASOFTIRQEN(r13); /* mark interrupts soft-disabled */ \ 172/* This second version is meant for exceptions that don't immediately
174 TRACE_DISABLE_INTS; 173 * hard-enable. We set a bit in paca->irq_happened to ensure that
175#define INTS_DISABLE_HARD \ 174 * a subsequent call to arch_local_irq_restore() will properly
176 stb r0,PACAHARDIRQEN(r13); /* and hard disabled */ 175 * hard-enable and avoid the fast-path
177#define INTS_DISABLE_ALL \ 176 */
178 INTS_DISABLE_SOFT \ 177#define INTS_DISABLE SOFT_DISABLE_INTS(r3,r4)
179 INTS_DISABLE_HARD 178
180 179/* This is called by exceptions that used INTS_KEEP (that did not touch
181/* This is called by exceptions that used INTS_KEEP (that is did not clear 180 * irq indicators in the PACA). This will restore MSR:EE to it's previous
182 * neither soft nor hard IRQ indicators in the PACA. This will restore MSR:EE 181 * value
183 * to it's previous value
184 * 182 *
185 * XXX In the long run, we may want to open-code it in order to separate the 183 * XXX In the long run, we may want to open-code it in order to separate the
186 * load from the wrtee, thus limiting the latency caused by the dependency 184 * load from the wrtee, thus limiting the latency caused by the dependency
@@ -238,7 +236,7 @@ exc_##n##_bad_stack: \
238#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ 236#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \
239 START_EXCEPTION(label); \ 237 START_EXCEPTION(label); \
240 NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ 238 NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \
241 EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ 239 EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE) \
242 ack(r8); \ 240 ack(r8); \
243 CHECK_NAPPING(); \ 241 CHECK_NAPPING(); \
244 addi r3,r1,STACK_FRAME_OVERHEAD; \ 242 addi r3,r1,STACK_FRAME_OVERHEAD; \
@@ -289,7 +287,7 @@ interrupt_end_book3e:
289/* Critical Input Interrupt */ 287/* Critical Input Interrupt */
290 START_EXCEPTION(critical_input); 288 START_EXCEPTION(critical_input);
291 CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) 289 CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
292// EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) 290// EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
293// bl special_reg_save_crit 291// bl special_reg_save_crit
294// CHECK_NAPPING(); 292// CHECK_NAPPING();
295// addi r3,r1,STACK_FRAME_OVERHEAD 293// addi r3,r1,STACK_FRAME_OVERHEAD
@@ -300,7 +298,7 @@ interrupt_end_book3e:
300/* Machine Check Interrupt */ 298/* Machine Check Interrupt */
301 START_EXCEPTION(machine_check); 299 START_EXCEPTION(machine_check);
302 CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE) 300 CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
303// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) 301// EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
304// bl special_reg_save_mc 302// bl special_reg_save_mc
305// addi r3,r1,STACK_FRAME_OVERHEAD 303// addi r3,r1,STACK_FRAME_OVERHEAD
306// CHECK_NAPPING(); 304// CHECK_NAPPING();
@@ -313,7 +311,7 @@ interrupt_end_book3e:
313 NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS) 311 NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS)
314 mfspr r14,SPRN_DEAR 312 mfspr r14,SPRN_DEAR
315 mfspr r15,SPRN_ESR 313 mfspr r15,SPRN_ESR
316 EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_KEEP) 314 EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
317 b storage_fault_common 315 b storage_fault_common
318 316
319/* Instruction Storage Interrupt */ 317/* Instruction Storage Interrupt */
@@ -321,7 +319,7 @@ interrupt_end_book3e:
321 NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS) 319 NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS)
322 li r15,0 320 li r15,0
323 mr r14,r10 321 mr r14,r10
324 EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_KEEP) 322 EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
325 b storage_fault_common 323 b storage_fault_common
326 324
327/* External Input Interrupt */ 325/* External Input Interrupt */
@@ -339,12 +337,11 @@ interrupt_end_book3e:
339 START_EXCEPTION(program); 337 START_EXCEPTION(program);
340 NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG) 338 NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG)
341 mfspr r14,SPRN_ESR 339 mfspr r14,SPRN_ESR
342 EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE_SOFT) 340 EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
343 std r14,_DSISR(r1) 341 std r14,_DSISR(r1)
344 addi r3,r1,STACK_FRAME_OVERHEAD 342 addi r3,r1,STACK_FRAME_OVERHEAD
345 ld r14,PACA_EXGEN+EX_R14(r13) 343 ld r14,PACA_EXGEN+EX_R14(r13)
346 bl .save_nvgprs 344 bl .save_nvgprs
347 INTS_RESTORE_HARD
348 bl .program_check_exception 345 bl .program_check_exception
349 b .ret_from_except 346 b .ret_from_except
350 347
@@ -353,15 +350,16 @@ interrupt_end_book3e:
353 NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE) 350 NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE)
354 /* we can probably do a shorter exception entry for that one... */ 351 /* we can probably do a shorter exception entry for that one... */
355 EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) 352 EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
356 bne 1f /* if from user, just load it up */ 353 ld r12,_MSR(r1)
354 andi. r0,r12,MSR_PR;
355 beq- 1f
356 bl .load_up_fpu
357 b fast_exception_return
3581: INTS_DISABLE
357 bl .save_nvgprs 359 bl .save_nvgprs
358 addi r3,r1,STACK_FRAME_OVERHEAD 360 addi r3,r1,STACK_FRAME_OVERHEAD
359 INTS_RESTORE_HARD
360 bl .kernel_fp_unavailable_exception 361 bl .kernel_fp_unavailable_exception
361 BUG_OPCODE 362 b .ret_from_except
3621: ld r12,_MSR(r1)
363 bl .load_up_fpu
364 b fast_exception_return
365 363
366/* Decrementer Interrupt */ 364/* Decrementer Interrupt */
367 MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC) 365 MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC)
@@ -372,7 +370,7 @@ interrupt_end_book3e:
372/* Watchdog Timer Interrupt */ 370/* Watchdog Timer Interrupt */
373 START_EXCEPTION(watchdog); 371 START_EXCEPTION(watchdog);
374 CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) 372 CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
375// EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) 373// EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
376// bl special_reg_save_crit 374// bl special_reg_save_crit
377// CHECK_NAPPING(); 375// CHECK_NAPPING();
378// addi r3,r1,STACK_FRAME_OVERHEAD 376// addi r3,r1,STACK_FRAME_OVERHEAD
@@ -391,10 +389,9 @@ interrupt_end_book3e:
391/* Auxiliary Processor Unavailable Interrupt */ 389/* Auxiliary Processor Unavailable Interrupt */
392 START_EXCEPTION(ap_unavailable); 390 START_EXCEPTION(ap_unavailable);
393 NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) 391 NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
394 EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP) 392 EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
395 addi r3,r1,STACK_FRAME_OVERHEAD
396 bl .save_nvgprs 393 bl .save_nvgprs
397 INTS_RESTORE_HARD 394 addi r3,r1,STACK_FRAME_OVERHEAD
398 bl .unknown_exception 395 bl .unknown_exception
399 b .ret_from_except 396 b .ret_from_except
400 397
@@ -450,7 +447,7 @@ interrupt_end_book3e:
450 mfspr r15,SPRN_SPRG_CRIT_SCRATCH 447 mfspr r15,SPRN_SPRG_CRIT_SCRATCH
451 mtspr SPRN_SPRG_GEN_SCRATCH,r15 448 mtspr SPRN_SPRG_GEN_SCRATCH,r15
452 mfspr r14,SPRN_DBSR 449 mfspr r14,SPRN_DBSR
453 EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE_ALL) 450 EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
454 std r14,_DSISR(r1) 451 std r14,_DSISR(r1)
455 addi r3,r1,STACK_FRAME_OVERHEAD 452 addi r3,r1,STACK_FRAME_OVERHEAD
456 mr r4,r14 453 mr r4,r14
@@ -465,7 +462,7 @@ kernel_dbg_exc:
465 462
466/* Debug exception as a debug interrupt*/ 463/* Debug exception as a debug interrupt*/
467 START_EXCEPTION(debug_debug); 464 START_EXCEPTION(debug_debug);
468 DBG_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS) 465 DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS)
469 466
470 /* 467 /*
471 * If there is a single step or branch-taken exception in an 468 * If there is a single step or branch-taken exception in an
@@ -515,7 +512,7 @@ kernel_dbg_exc:
515 mfspr r15,SPRN_SPRG_DBG_SCRATCH 512 mfspr r15,SPRN_SPRG_DBG_SCRATCH
516 mtspr SPRN_SPRG_GEN_SCRATCH,r15 513 mtspr SPRN_SPRG_GEN_SCRATCH,r15
517 mfspr r14,SPRN_DBSR 514 mfspr r14,SPRN_DBSR
518 EXCEPTION_COMMON(0xd00, PACA_EXDBG, INTS_DISABLE_ALL) 515 EXCEPTION_COMMON(0xd08, PACA_EXDBG, INTS_DISABLE)
519 std r14,_DSISR(r1) 516 std r14,_DSISR(r1)
520 addi r3,r1,STACK_FRAME_OVERHEAD 517 addi r3,r1,STACK_FRAME_OVERHEAD
521 mr r4,r14 518 mr r4,r14
@@ -525,21 +522,20 @@ kernel_dbg_exc:
525 bl .DebugException 522 bl .DebugException
526 b .ret_from_except 523 b .ret_from_except
527 524
528 MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE) 525 START_EXCEPTION(perfmon);
529 526 NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE)
530/* Doorbell interrupt */ 527 EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
531 START_EXCEPTION(doorbell)
532 NORMAL_EXCEPTION_PROLOG(0x2070, PROLOG_ADDITION_DOORBELL)
533 EXCEPTION_COMMON(0x2070, PACA_EXGEN, INTS_DISABLE_ALL)
534 CHECK_NAPPING()
535 addi r3,r1,STACK_FRAME_OVERHEAD 528 addi r3,r1,STACK_FRAME_OVERHEAD
536 bl .doorbell_exception 529 bl .performance_monitor_exception
537 b .ret_from_except_lite 530 b .ret_from_except_lite
538 531
532/* Doorbell interrupt */
533 MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE)
534
539/* Doorbell critical Interrupt */ 535/* Doorbell critical Interrupt */
540 START_EXCEPTION(doorbell_crit); 536 START_EXCEPTION(doorbell_crit);
541 CRIT_EXCEPTION_PROLOG(0x2080, PROLOG_ADDITION_NONE) 537 CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE)
542// EXCEPTION_COMMON(0x2080, PACA_EXCRIT, INTS_DISABLE_ALL) 538// EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
543// bl special_reg_save_crit 539// bl special_reg_save_crit
544// CHECK_NAPPING(); 540// CHECK_NAPPING();
545// addi r3,r1,STACK_FRAME_OVERHEAD 541// addi r3,r1,STACK_FRAME_OVERHEAD
@@ -547,36 +543,114 @@ kernel_dbg_exc:
547// b ret_from_crit_except 543// b ret_from_crit_except
548 b . 544 b .
549 545
546/* Guest Doorbell */
550 MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE) 547 MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
551 MASKABLE_EXCEPTION(0x2e0, guest_doorbell_crit, .unknown_exception, ACK_NONE)
552 MASKABLE_EXCEPTION(0x310, hypercall, .unknown_exception, ACK_NONE)
553 MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
554 548
549/* Guest Doorbell critical Interrupt */
550 START_EXCEPTION(guest_doorbell_crit);
551 CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE)
552// EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
553// bl special_reg_save_crit
554// CHECK_NAPPING();
555// addi r3,r1,STACK_FRAME_OVERHEAD
556// bl .guest_doorbell_critical_exception
557// b ret_from_crit_except
558 b .
559
560/* Hypervisor call */
561 START_EXCEPTION(hypercall);
562 NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
563 EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
564 addi r3,r1,STACK_FRAME_OVERHEAD
565 bl .save_nvgprs
566 INTS_RESTORE_HARD
567 bl .unknown_exception
568 b .ret_from_except
569
570/* Embedded Hypervisor priviledged */
571 START_EXCEPTION(ehpriv);
572 NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
573 EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
574 addi r3,r1,STACK_FRAME_OVERHEAD
575 bl .save_nvgprs
576 INTS_RESTORE_HARD
577 bl .unknown_exception
578 b .ret_from_except
555 579
556/* 580/*
557 * An interrupt came in while soft-disabled; clear EE in SRR1, 581 * An interrupt came in while soft-disabled; We mark paca->irq_happened
558 * clear paca->hard_enabled and return. 582 * accordingly and if the interrupt is level sensitive, we hard disable
559 */ 583 */
560masked_doorbell_book3e:
561 mtcr r10
562 /* Resend the doorbell to fire again when ints enabled */
563 mfspr r10,SPRN_PIR
564 PPC_MSGSND(r10)
565 b masked_interrupt_book3e_common
566 584
567masked_interrupt_book3e: 585masked_interrupt_book3e_0x500:
586 /* XXX When adding support for EPR, use PACA_IRQ_EE_EDGE */
587 li r11,PACA_IRQ_EE
588 b masked_interrupt_book3e_full_mask
589
590masked_interrupt_book3e_0x900:
591 ACK_DEC(r11);
592 li r11,PACA_IRQ_DEC
593 b masked_interrupt_book3e_no_mask
594masked_interrupt_book3e_0x980:
595 ACK_FIT(r11);
596 li r11,PACA_IRQ_DEC
597 b masked_interrupt_book3e_no_mask
598masked_interrupt_book3e_0x280:
599masked_interrupt_book3e_0x2c0:
600 li r11,PACA_IRQ_DBELL
601 b masked_interrupt_book3e_no_mask
602
603masked_interrupt_book3e_no_mask:
604 mtcr r10
605 lbz r10,PACAIRQHAPPENED(r13)
606 or r10,r10,r11
607 stb r10,PACAIRQHAPPENED(r13)
608 b 1f
609masked_interrupt_book3e_full_mask:
568 mtcr r10 610 mtcr r10
569masked_interrupt_book3e_common: 611 lbz r10,PACAIRQHAPPENED(r13)
570 stb r11,PACAHARDIRQEN(r13) 612 or r10,r10,r11
613 stb r10,PACAIRQHAPPENED(r13)
571 mfspr r10,SPRN_SRR1 614 mfspr r10,SPRN_SRR1
572 rldicl r11,r10,48,1 /* clear MSR_EE */ 615 rldicl r11,r10,48,1 /* clear MSR_EE */
573 rotldi r10,r11,16 616 rotldi r10,r11,16
574 mtspr SPRN_SRR1,r10 617 mtspr SPRN_SRR1,r10
575 ld r10,PACA_EXGEN+EX_R10(r13); /* restore registers */ 6181: ld r10,PACA_EXGEN+EX_R10(r13);
576 ld r11,PACA_EXGEN+EX_R11(r13); 619 ld r11,PACA_EXGEN+EX_R11(r13);
577 mfspr r13,SPRN_SPRG_GEN_SCRATCH; 620 mfspr r13,SPRN_SPRG_GEN_SCRATCH;
578 rfi 621 rfi
579 b . 622 b .
623/*
624 * Called from arch_local_irq_enable when an interrupt needs
625 * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280
626 * to indicate the kind of interrupt. MSR:EE is already off.
627 * We generate a stackframe like if a real interrupt had happened.
628 *
629 * Note: While MSR:EE is off, we need to make sure that _MSR
630 * in the generated frame has EE set to 1 or the exception
631 * handler will not properly re-enable them.
632 */
633_GLOBAL(__replay_interrupt)
634 /* We are going to jump to the exception common code which
635 * will retrieve various register values from the PACA which
636 * we don't give a damn about.
637 */
638 mflr r10
639 mfmsr r11
640 mfcr r4
641 mtspr SPRN_SPRG_GEN_SCRATCH,r13;
642 std r1,PACA_EXGEN+EX_R1(r13);
643 stw r4,PACA_EXGEN+EX_CR(r13);
644 ori r11,r11,MSR_EE
645 subi r1,r1,INT_FRAME_SIZE;
646 cmpwi cr0,r3,0x500
647 beq exc_0x500_common
648 cmpwi cr0,r3,0x900
649 beq exc_0x900_common
650 cmpwi cr0,r3,0x280
651 beq exc_0x280_common
652 blr
653
580 654
581/* 655/*
582 * This is called from 0x300 and 0x400 handlers after the prologs with 656 * This is called from 0x300 and 0x400 handlers after the prologs with
@@ -591,7 +665,6 @@ storage_fault_common:
591 mr r5,r15 665 mr r5,r15
592 ld r14,PACA_EXGEN+EX_R14(r13) 666 ld r14,PACA_EXGEN+EX_R14(r13)
593 ld r15,PACA_EXGEN+EX_R15(r13) 667 ld r15,PACA_EXGEN+EX_R15(r13)
594 INTS_RESTORE_HARD
595 bl .do_page_fault 668 bl .do_page_fault
596 cmpdi r3,0 669 cmpdi r3,0
597 bne- 1f 670 bne- 1f
@@ -680,6 +753,8 @@ BAD_STACK_TRAMPOLINE(0x000)
680BAD_STACK_TRAMPOLINE(0x100) 753BAD_STACK_TRAMPOLINE(0x100)
681BAD_STACK_TRAMPOLINE(0x200) 754BAD_STACK_TRAMPOLINE(0x200)
682BAD_STACK_TRAMPOLINE(0x260) 755BAD_STACK_TRAMPOLINE(0x260)
756BAD_STACK_TRAMPOLINE(0x280)
757BAD_STACK_TRAMPOLINE(0x2a0)
683BAD_STACK_TRAMPOLINE(0x2c0) 758BAD_STACK_TRAMPOLINE(0x2c0)
684BAD_STACK_TRAMPOLINE(0x2e0) 759BAD_STACK_TRAMPOLINE(0x2e0)
685BAD_STACK_TRAMPOLINE(0x300) 760BAD_STACK_TRAMPOLINE(0x300)
@@ -697,11 +772,10 @@ BAD_STACK_TRAMPOLINE(0xa00)
697BAD_STACK_TRAMPOLINE(0xb00) 772BAD_STACK_TRAMPOLINE(0xb00)
698BAD_STACK_TRAMPOLINE(0xc00) 773BAD_STACK_TRAMPOLINE(0xc00)
699BAD_STACK_TRAMPOLINE(0xd00) 774BAD_STACK_TRAMPOLINE(0xd00)
775BAD_STACK_TRAMPOLINE(0xd08)
700BAD_STACK_TRAMPOLINE(0xe00) 776BAD_STACK_TRAMPOLINE(0xe00)
701BAD_STACK_TRAMPOLINE(0xf00) 777BAD_STACK_TRAMPOLINE(0xf00)
702BAD_STACK_TRAMPOLINE(0xf20) 778BAD_STACK_TRAMPOLINE(0xf20)
703BAD_STACK_TRAMPOLINE(0x2070)
704BAD_STACK_TRAMPOLINE(0x2080)
705 779
706 .globl bad_stack_book3e 780 .globl bad_stack_book3e
707bad_stack_book3e: 781bad_stack_book3e:
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 15c5a4f6de01..2d0868a4e2f0 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -12,6 +12,7 @@
12 * 12 *
13 */ 13 */
14 14
15#include <asm/hw_irq.h>
15#include <asm/exception-64s.h> 16#include <asm/exception-64s.h>
16#include <asm/ptrace.h> 17#include <asm/ptrace.h>
17 18
@@ -19,7 +20,7 @@
19 * We layout physical memory as follows: 20 * We layout physical memory as follows:
20 * 0x0000 - 0x00ff : Secondary processor spin code 21 * 0x0000 - 0x00ff : Secondary processor spin code
21 * 0x0100 - 0x2fff : pSeries Interrupt prologs 22 * 0x0100 - 0x2fff : pSeries Interrupt prologs
22 * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs 23 * 0x3000 - 0x5fff : interrupt support common interrupt prologs
23 * 0x6000 - 0x6fff : Initial (CPU0) segment table 24 * 0x6000 - 0x6fff : Initial (CPU0) segment table
24 * 0x7000 - 0x7fff : FWNMI data area 25 * 0x7000 - 0x7fff : FWNMI data area
25 * 0x8000 - : Early init and support code 26 * 0x8000 - : Early init and support code
@@ -356,34 +357,60 @@ do_stab_bolted_pSeries:
356 KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40) 357 KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
357 358
358/* 359/*
359 * An interrupt came in while soft-disabled; clear EE in SRR1, 360 * An interrupt came in while soft-disabled. We set paca->irq_happened,
360 * clear paca->hard_enabled and return. 361 * then, if it was a decrementer interrupt, we bump the dec to max and
362 * and return, else we hard disable and return. This is called with
363 * r10 containing the value to OR to the paca field.
361 */ 364 */
362masked_interrupt: 365#define MASKED_INTERRUPT(_H) \
363 stb r10,PACAHARDIRQEN(r13) 366masked_##_H##interrupt: \
364 mtcrf 0x80,r9 367 std r11,PACA_EXGEN+EX_R11(r13); \
365 ld r9,PACA_EXGEN+EX_R9(r13) 368 lbz r11,PACAIRQHAPPENED(r13); \
366 mfspr r10,SPRN_SRR1 369 or r11,r11,r10; \
367 rldicl r10,r10,48,1 /* clear MSR_EE */ 370 stb r11,PACAIRQHAPPENED(r13); \
368 rotldi r10,r10,16 371 andi. r10,r10,PACA_IRQ_DEC; \
369 mtspr SPRN_SRR1,r10 372 beq 1f; \
370 ld r10,PACA_EXGEN+EX_R10(r13) 373 lis r10,0x7fff; \
371 GET_SCRATCH0(r13) 374 ori r10,r10,0xffff; \
372 rfid 375 mtspr SPRN_DEC,r10; \
376 b 2f; \
3771: mfspr r10,SPRN_##_H##SRR1; \
378 rldicl r10,r10,48,1; /* clear MSR_EE */ \
379 rotldi r10,r10,16; \
380 mtspr SPRN_##_H##SRR1,r10; \
3812: mtcrf 0x80,r9; \
382 ld r9,PACA_EXGEN+EX_R9(r13); \
383 ld r10,PACA_EXGEN+EX_R10(r13); \
384 ld r11,PACA_EXGEN+EX_R11(r13); \
385 GET_SCRATCH0(r13); \
386 ##_H##rfid; \
373 b . 387 b .
388
389 MASKED_INTERRUPT()
390 MASKED_INTERRUPT(H)
374 391
375masked_Hinterrupt: 392/*
376 stb r10,PACAHARDIRQEN(r13) 393 * Called from arch_local_irq_enable when an interrupt needs
377 mtcrf 0x80,r9 394 * to be resent. r3 contains 0x500 or 0x900 to indicate which
378 ld r9,PACA_EXGEN+EX_R9(r13) 395 * kind of interrupt. MSR:EE is already off. We generate a
379 mfspr r10,SPRN_HSRR1 396 * stackframe like if a real interrupt had happened.
380 rldicl r10,r10,48,1 /* clear MSR_EE */ 397 *
381 rotldi r10,r10,16 398 * Note: While MSR:EE is off, we need to make sure that _MSR
382 mtspr SPRN_HSRR1,r10 399 * in the generated frame has EE set to 1 or the exception
383 ld r10,PACA_EXGEN+EX_R10(r13) 400 * handler will not properly re-enable them.
384 GET_SCRATCH0(r13) 401 */
385 hrfid 402_GLOBAL(__replay_interrupt)
386 b . 403 /* We are going to jump to the exception common code which
404 * will retrieve various register values from the PACA which
405 * we don't give a damn about, so we don't bother storing them.
406 */
407 mfmsr r12
408 mflr r11
409 mfcr r9
410 ori r12,r12,MSR_EE
411 andi. r3,r3,0x0800
412 bne decrementer_common
413 b hardware_interrupt_common
387 414
388#ifdef CONFIG_PPC_PSERIES 415#ifdef CONFIG_PPC_PSERIES
389/* 416/*
@@ -458,14 +485,15 @@ machine_check_common:
458 bl .machine_check_exception 485 bl .machine_check_exception
459 b .ret_from_except 486 b .ret_from_except
460 487
461 STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt) 488 STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
489 STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
462 STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) 490 STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
463 STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) 491 STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
464 STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) 492 STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
465 STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) 493 STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
466 STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception) 494 STD_EXCEPTION_COMMON(0xe40, emulation_assist, .program_check_exception)
467 STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception) 495 STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
468 STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception) 496 STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
469 STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) 497 STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
470#ifdef CONFIG_ALTIVEC 498#ifdef CONFIG_ALTIVEC
471 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception) 499 STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
@@ -482,6 +510,9 @@ machine_check_common:
482system_call_entry: 510system_call_entry:
483 b system_call_common 511 b system_call_common
484 512
513ppc64_runlatch_on_trampoline:
514 b .__ppc64_runlatch_on
515
485/* 516/*
486 * Here we have detected that the kernel stack pointer is bad. 517 * Here we have detected that the kernel stack pointer is bad.
487 * R9 contains the saved CR, r13 points to the paca, 518 * R9 contains the saved CR, r13 points to the paca,
@@ -555,6 +586,8 @@ data_access_common:
555 mfspr r10,SPRN_DSISR 586 mfspr r10,SPRN_DSISR
556 stw r10,PACA_EXGEN+EX_DSISR(r13) 587 stw r10,PACA_EXGEN+EX_DSISR(r13)
557 EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) 588 EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
589 DISABLE_INTS
590 ld r12,_MSR(r1)
558 ld r3,PACA_EXGEN+EX_DAR(r13) 591 ld r3,PACA_EXGEN+EX_DAR(r13)
559 lwz r4,PACA_EXGEN+EX_DSISR(r13) 592 lwz r4,PACA_EXGEN+EX_DSISR(r13)
560 li r5,0x300 593 li r5,0x300
@@ -569,6 +602,7 @@ h_data_storage_common:
569 stw r10,PACA_EXGEN+EX_DSISR(r13) 602 stw r10,PACA_EXGEN+EX_DSISR(r13)
570 EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) 603 EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
571 bl .save_nvgprs 604 bl .save_nvgprs
605 DISABLE_INTS
572 addi r3,r1,STACK_FRAME_OVERHEAD 606 addi r3,r1,STACK_FRAME_OVERHEAD
573 bl .unknown_exception 607 bl .unknown_exception
574 b .ret_from_except 608 b .ret_from_except
@@ -577,6 +611,8 @@ h_data_storage_common:
577 .globl instruction_access_common 611 .globl instruction_access_common
578instruction_access_common: 612instruction_access_common:
579 EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) 613 EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
614 DISABLE_INTS
615 ld r12,_MSR(r1)
580 ld r3,_NIP(r1) 616 ld r3,_NIP(r1)
581 andis. r4,r12,0x5820 617 andis. r4,r12,0x5820
582 li r5,0x400 618 li r5,0x400
@@ -672,12 +708,6 @@ _GLOBAL(slb_miss_realmode)
672 ld r10,PACA_EXSLB+EX_LR(r13) 708 ld r10,PACA_EXSLB+EX_LR(r13)
673 ld r3,PACA_EXSLB+EX_R3(r13) 709 ld r3,PACA_EXSLB+EX_R3(r13)
674 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ 710 lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
675#ifdef CONFIG_PPC_ISERIES
676BEGIN_FW_FTR_SECTION
677 ld r11,PACALPPACAPTR(r13)
678 ld r11,LPPACASRR0(r11) /* get SRR0 value */
679END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
680#endif /* CONFIG_PPC_ISERIES */
681 711
682 mtlr r10 712 mtlr r10
683 713
@@ -690,12 +720,6 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
690 mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ 720 mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
691.machine pop 721.machine pop
692 722
693#ifdef CONFIG_PPC_ISERIES
694BEGIN_FW_FTR_SECTION
695 mtspr SPRN_SRR0,r11
696 mtspr SPRN_SRR1,r12
697END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
698#endif /* CONFIG_PPC_ISERIES */
699 ld r9,PACA_EXSLB+EX_R9(r13) 723 ld r9,PACA_EXSLB+EX_R9(r13)
700 ld r10,PACA_EXSLB+EX_R10(r13) 724 ld r10,PACA_EXSLB+EX_R10(r13)
701 ld r11,PACA_EXSLB+EX_R11(r13) 725 ld r11,PACA_EXSLB+EX_R11(r13)
@@ -704,13 +728,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
704 rfid 728 rfid
705 b . /* prevent speculative execution */ 729 b . /* prevent speculative execution */
706 730
7072: 7312: mfspr r11,SPRN_SRR0
708#ifdef CONFIG_PPC_ISERIES
709BEGIN_FW_FTR_SECTION
710 b unrecov_slb
711END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
712#endif /* CONFIG_PPC_ISERIES */
713 mfspr r11,SPRN_SRR0
714 ld r10,PACAKBASE(r13) 732 ld r10,PACAKBASE(r13)
715 LOAD_HANDLER(r10,unrecov_slb) 733 LOAD_HANDLER(r10,unrecov_slb)
716 mtspr SPRN_SRR0,r10 734 mtspr SPRN_SRR0,r10
@@ -727,20 +745,6 @@ unrecov_slb:
727 bl .unrecoverable_exception 745 bl .unrecoverable_exception
728 b 1b 746 b 1b
729 747
730 .align 7
731 .globl hardware_interrupt_common
732 .globl hardware_interrupt_entry
733hardware_interrupt_common:
734 EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
735 FINISH_NAP
736hardware_interrupt_entry:
737 DISABLE_INTS
738BEGIN_FTR_SECTION
739 bl .ppc64_runlatch_on
740END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
741 addi r3,r1,STACK_FRAME_OVERHEAD
742 bl .do_IRQ
743 b .ret_from_except_lite
744 748
745#ifdef CONFIG_PPC_970_NAP 749#ifdef CONFIG_PPC_970_NAP
746power4_fixup_nap: 750power4_fixup_nap:
@@ -785,8 +789,8 @@ fp_unavailable_common:
785 EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) 789 EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
786 bne 1f /* if from user, just load it up */ 790 bne 1f /* if from user, just load it up */
787 bl .save_nvgprs 791 bl .save_nvgprs
792 DISABLE_INTS
788 addi r3,r1,STACK_FRAME_OVERHEAD 793 addi r3,r1,STACK_FRAME_OVERHEAD
789 ENABLE_INTS
790 bl .kernel_fp_unavailable_exception 794 bl .kernel_fp_unavailable_exception
791 BUG_OPCODE 795 BUG_OPCODE
7921: bl .load_up_fpu 7961: bl .load_up_fpu
@@ -805,8 +809,8 @@ BEGIN_FTR_SECTION
805END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 809END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
806#endif 810#endif
807 bl .save_nvgprs 811 bl .save_nvgprs
812 DISABLE_INTS
808 addi r3,r1,STACK_FRAME_OVERHEAD 813 addi r3,r1,STACK_FRAME_OVERHEAD
809 ENABLE_INTS
810 bl .altivec_unavailable_exception 814 bl .altivec_unavailable_exception
811 b .ret_from_except 815 b .ret_from_except
812 816
@@ -816,13 +820,14 @@ vsx_unavailable_common:
816 EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN) 820 EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
817#ifdef CONFIG_VSX 821#ifdef CONFIG_VSX
818BEGIN_FTR_SECTION 822BEGIN_FTR_SECTION
819 bne .load_up_vsx 823 beq 1f
824 b .load_up_vsx
8201: 8251:
821END_FTR_SECTION_IFSET(CPU_FTR_VSX) 826END_FTR_SECTION_IFSET(CPU_FTR_VSX)
822#endif 827#endif
823 bl .save_nvgprs 828 bl .save_nvgprs
829 DISABLE_INTS
824 addi r3,r1,STACK_FRAME_OVERHEAD 830 addi r3,r1,STACK_FRAME_OVERHEAD
825 ENABLE_INTS
826 bl .vsx_unavailable_exception 831 bl .vsx_unavailable_exception
827 b .ret_from_except 832 b .ret_from_except
828 833
@@ -831,66 +836,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
831__end_handlers: 836__end_handlers:
832 837
833/* 838/*
834 * Return from an exception with minimal checks.
835 * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
836 * If interrupts have been enabled, or anything has been
837 * done that might have changed the scheduling status of
838 * any task or sent any task a signal, you should use
839 * ret_from_except or ret_from_except_lite instead of this.
840 */
841fast_exc_return_irq: /* restores irq state too */
842 ld r3,SOFTE(r1)
843 TRACE_AND_RESTORE_IRQ(r3);
844 ld r12,_MSR(r1)
845 rldicl r4,r12,49,63 /* get MSR_EE to LSB */
846 stb r4,PACAHARDIRQEN(r13) /* restore paca->hard_enabled */
847 b 1f
848
849 .globl fast_exception_return
850fast_exception_return:
851 ld r12,_MSR(r1)
8521: ld r11,_NIP(r1)
853 andi. r3,r12,MSR_RI /* check if RI is set */
854 beq- unrecov_fer
855
856#ifdef CONFIG_VIRT_CPU_ACCOUNTING
857 andi. r3,r12,MSR_PR
858 beq 2f
859 ACCOUNT_CPU_USER_EXIT(r3, r4)
8602:
861#endif
862
863 ld r3,_CCR(r1)
864 ld r4,_LINK(r1)
865 ld r5,_CTR(r1)
866 ld r6,_XER(r1)
867 mtcr r3
868 mtlr r4
869 mtctr r5
870 mtxer r6
871 REST_GPR(0, r1)
872 REST_8GPRS(2, r1)
873
874 mfmsr r10
875 rldicl r10,r10,48,1 /* clear EE */
876 rldicr r10,r10,16,61 /* clear RI (LE is 0 already) */
877 mtmsrd r10,1
878
879 mtspr SPRN_SRR1,r12
880 mtspr SPRN_SRR0,r11
881 REST_4GPRS(10, r1)
882 ld r1,GPR1(r1)
883 rfid
884 b . /* prevent speculative execution */
885
886unrecov_fer:
887 bl .save_nvgprs
8881: addi r3,r1,STACK_FRAME_OVERHEAD
889 bl .unrecoverable_exception
890 b 1b
891
892
893/*
894 * Hash table stuff 839 * Hash table stuff
895 */ 840 */
896 .align 7 841 .align 7
@@ -912,28 +857,6 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
912 lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ 857 lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */
913 andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ 858 andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */
914 bne 77f /* then don't call hash_page now */ 859 bne 77f /* then don't call hash_page now */
915
916 /*
917 * On iSeries, we soft-disable interrupts here, then
918 * hard-enable interrupts so that the hash_page code can spin on
919 * the hash_table_lock without problems on a shared processor.
920 */
921 DISABLE_INTS
922
923 /*
924 * Currently, trace_hardirqs_off() will be called by DISABLE_INTS
925 * and will clobber volatile registers when irq tracing is enabled
926 * so we need to reload them. It may be possible to be smarter here
927 * and move the irq tracing elsewhere but let's keep it simple for
928 * now
929 */
930#ifdef CONFIG_TRACE_IRQFLAGS
931 ld r3,_DAR(r1)
932 ld r4,_DSISR(r1)
933 ld r5,_TRAP(r1)
934 ld r12,_MSR(r1)
935 clrrdi r5,r5,4
936#endif /* CONFIG_TRACE_IRQFLAGS */
937 /* 860 /*
938 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are 861 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
939 * accessing a userspace segment (even from the kernel). We assume 862 * accessing a userspace segment (even from the kernel). We assume
@@ -951,62 +874,25 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
951 * r4 contains the required access permissions 874 * r4 contains the required access permissions
952 * r5 contains the trap number 875 * r5 contains the trap number
953 * 876 *
954 * at return r3 = 0 for success 877 * at return r3 = 0 for success, 1 for page fault, negative for error
955 */ 878 */
956 bl .hash_page /* build HPTE if possible */ 879 bl .hash_page /* build HPTE if possible */
957 cmpdi r3,0 /* see if hash_page succeeded */ 880 cmpdi r3,0 /* see if hash_page succeeded */
958 881
959BEGIN_FW_FTR_SECTION 882 /* Success */
960 /*
961 * If we had interrupts soft-enabled at the point where the
962 * DSI/ISI occurred, and an interrupt came in during hash_page,
963 * handle it now.
964 * We jump to ret_from_except_lite rather than fast_exception_return
965 * because ret_from_except_lite will check for and handle pending
966 * interrupts if necessary.
967 */
968 beq 13f
969END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
970
971BEGIN_FW_FTR_SECTION
972 /*
973 * Here we have interrupts hard-disabled, so it is sufficient
974 * to restore paca->{soft,hard}_enable and get out.
975 */
976 beq fast_exc_return_irq /* Return from exception on success */ 883 beq fast_exc_return_irq /* Return from exception on success */
977END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
978
979 /* For a hash failure, we don't bother re-enabling interrupts */
980 ble- 12f
981
982 /*
983 * hash_page couldn't handle it, set soft interrupt enable back
984 * to what it was before the trap. Note that .arch_local_irq_restore
985 * handles any interrupts pending at this point.
986 */
987 ld r3,SOFTE(r1)
988 TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f)
989 bl .arch_local_irq_restore
990 b 11f
991 884
992/* We have a data breakpoint exception - handle it */ 885 /* Error */
993handle_dabr_fault: 886 blt- 13f
994 bl .save_nvgprs
995 ld r4,_DAR(r1)
996 ld r5,_DSISR(r1)
997 addi r3,r1,STACK_FRAME_OVERHEAD
998 bl .do_dabr
999 b .ret_from_except_lite
1000 887
1001/* Here we have a page fault that hash_page can't handle. */ 888/* Here we have a page fault that hash_page can't handle. */
1002handle_page_fault: 889handle_page_fault:
1003 ENABLE_INTS
100411: ld r4,_DAR(r1) 89011: ld r4,_DAR(r1)
1005 ld r5,_DSISR(r1) 891 ld r5,_DSISR(r1)
1006 addi r3,r1,STACK_FRAME_OVERHEAD 892 addi r3,r1,STACK_FRAME_OVERHEAD
1007 bl .do_page_fault 893 bl .do_page_fault
1008 cmpdi r3,0 894 cmpdi r3,0
1009 beq+ 13f 895 beq+ 12f
1010 bl .save_nvgprs 896 bl .save_nvgprs
1011 mr r5,r3 897 mr r5,r3
1012 addi r3,r1,STACK_FRAME_OVERHEAD 898 addi r3,r1,STACK_FRAME_OVERHEAD
@@ -1014,12 +900,20 @@ handle_page_fault:
1014 bl .bad_page_fault 900 bl .bad_page_fault
1015 b .ret_from_except 901 b .ret_from_except
1016 902
101713: b .ret_from_except_lite 903/* We have a data breakpoint exception - handle it */
904handle_dabr_fault:
905 bl .save_nvgprs
906 ld r4,_DAR(r1)
907 ld r5,_DSISR(r1)
908 addi r3,r1,STACK_FRAME_OVERHEAD
909 bl .do_dabr
91012: b .ret_from_except_lite
911
1018 912
1019/* We have a page fault that hash_page could handle but HV refused 913/* We have a page fault that hash_page could handle but HV refused
1020 * the PTE insertion 914 * the PTE insertion
1021 */ 915 */
102212: bl .save_nvgprs 91613: bl .save_nvgprs
1023 mr r5,r3 917 mr r5,r3
1024 addi r3,r1,STACK_FRAME_OVERHEAD 918 addi r3,r1,STACK_FRAME_OVERHEAD
1025 ld r4,_DAR(r1) 919 ld r4,_DAR(r1)
@@ -1141,51 +1035,19 @@ _GLOBAL(do_stab_bolted)
1141 .= 0x7000 1035 .= 0x7000
1142 .globl fwnmi_data_area 1036 .globl fwnmi_data_area
1143fwnmi_data_area: 1037fwnmi_data_area:
1144#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
1145 1038
1146 /* iSeries does not use the FWNMI stuff, so it is safe to put
1147 * this here, even if we later allow kernels that will boot on
1148 * both pSeries and iSeries */
1149#ifdef CONFIG_PPC_ISERIES
1150 . = LPARMAP_PHYS
1151 .globl xLparMap
1152xLparMap:
1153 .quad HvEsidsToMap /* xNumberEsids */
1154 .quad HvRangesToMap /* xNumberRanges */
1155 .quad STAB0_PAGE /* xSegmentTableOffs */
1156 .zero 40 /* xRsvd */
1157 /* xEsids (HvEsidsToMap entries of 2 quads) */
1158 .quad PAGE_OFFSET_ESID /* xKernelEsid */
1159 .quad PAGE_OFFSET_VSID /* xKernelVsid */
1160 .quad VMALLOC_START_ESID /* xKernelEsid */
1161 .quad VMALLOC_START_VSID /* xKernelVsid */
1162 /* xRanges (HvRangesToMap entries of 3 quads) */
1163 .quad HvPagesToMap /* xPages */
1164 .quad 0 /* xOffset */
1165 .quad PAGE_OFFSET_VSID << (SID_SHIFT - HW_PAGE_SHIFT) /* xVPN */
1166
1167#endif /* CONFIG_PPC_ISERIES */
1168
1169#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
1170 /* pseries and powernv need to keep the whole page from 1039 /* pseries and powernv need to keep the whole page from
1171 * 0x7000 to 0x8000 free for use by the firmware 1040 * 0x7000 to 0x8000 free for use by the firmware
1172 */ 1041 */
1173 . = 0x8000 1042 . = 0x8000
1174#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ 1043#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
1175 1044
1176/* 1045/* Space for CPU0's segment table */
1177 * Space for CPU0's segment table. 1046 .balign 4096
1178 *
1179 * On iSeries, the hypervisor must fill in at least one entry before
1180 * we get control (with relocate on). The address is given to the hv
1181 * as a page number (see xLparMap above), so this must be at a
1182 * fixed address (the linker can't compute (u64)&initial_stab >>
1183 * PAGE_SHIFT).
1184 */
1185 . = STAB0_OFFSET /* 0x8000 */
1186 .globl initial_stab 1047 .globl initial_stab
1187initial_stab: 1048initial_stab:
1188 .space 4096 1049 .space 4096
1050
1189#ifdef CONFIG_PPC_POWERNV 1051#ifdef CONFIG_PPC_POWERNV
1190_GLOBAL(opal_mc_secondary_handler) 1052_GLOBAL(opal_mc_secondary_handler)
1191 HMT_MEDIUM 1053 HMT_MEDIUM
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
new file mode 100644
index 000000000000..cfe7a38708c3
--- /dev/null
+++ b/arch/powerpc/kernel/fadump.c
@@ -0,0 +1,1315 @@
1/*
2 * Firmware Assisted dump: A robust mechanism to get reliable kernel crash
3 * dump with assistance from firmware. This approach does not use kexec,
4 * instead firmware assists in booting the kdump kernel while preserving
5 * memory contents. The most of the code implementation has been adapted
6 * from phyp assisted dump implementation written by Linas Vepstas and
7 * Manish Ahuja
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 * Copyright 2011 IBM Corporation
24 * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
25 */
26
27#undef DEBUG
28#define pr_fmt(fmt) "fadump: " fmt
29
30#include <linux/string.h>
31#include <linux/memblock.h>
32#include <linux/delay.h>
33#include <linux/debugfs.h>
34#include <linux/seq_file.h>
35#include <linux/crash_dump.h>
36#include <linux/kobject.h>
37#include <linux/sysfs.h>
38
39#include <asm/page.h>
40#include <asm/prom.h>
41#include <asm/rtas.h>
42#include <asm/fadump.h>
43
44static struct fw_dump fw_dump;
45static struct fadump_mem_struct fdm;
46static const struct fadump_mem_struct *fdm_active;
47
48static DEFINE_MUTEX(fadump_mutex);
49struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES];
50int crash_mem_ranges;
51
52/* Scan the Firmware Assisted dump configuration details. */
53int __init early_init_dt_scan_fw_dump(unsigned long node,
54 const char *uname, int depth, void *data)
55{
56 __be32 *sections;
57 int i, num_sections;
58 unsigned long size;
59 const int *token;
60
61 if (depth != 1 || strcmp(uname, "rtas") != 0)
62 return 0;
63
64 /*
65 * Check if Firmware Assisted dump is supported. if yes, check
66 * if dump has been initiated on last reboot.
67 */
68 token = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL);
69 if (!token)
70 return 0;
71
72 fw_dump.fadump_supported = 1;
73 fw_dump.ibm_configure_kernel_dump = *token;
74
75 /*
76 * The 'ibm,kernel-dump' rtas node is present only if there is
77 * dump data waiting for us.
78 */
79 fdm_active = of_get_flat_dt_prop(node, "ibm,kernel-dump", NULL);
80 if (fdm_active)
81 fw_dump.dump_active = 1;
82
83 /* Get the sizes required to store dump data for the firmware provided
84 * dump sections.
85 * For each dump section type supported, a 32bit cell which defines
86 * the ID of a supported section followed by two 32 bit cells which
87 * gives teh size of the section in bytes.
88 */
89 sections = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
90 &size);
91
92 if (!sections)
93 return 0;
94
95 num_sections = size / (3 * sizeof(u32));
96
97 for (i = 0; i < num_sections; i++, sections += 3) {
98 u32 type = (u32)of_read_number(sections, 1);
99
100 switch (type) {
101 case FADUMP_CPU_STATE_DATA:
102 fw_dump.cpu_state_data_size =
103 of_read_ulong(&sections[1], 2);
104 break;
105 case FADUMP_HPTE_REGION:
106 fw_dump.hpte_region_size =
107 of_read_ulong(&sections[1], 2);
108 break;
109 }
110 }
111 return 1;
112}
113
114int is_fadump_active(void)
115{
116 return fw_dump.dump_active;
117}
118
119/* Print firmware assisted dump configurations for debugging purpose. */
120static void fadump_show_config(void)
121{
122 pr_debug("Support for firmware-assisted dump (fadump): %s\n",
123 (fw_dump.fadump_supported ? "present" : "no support"));
124
125 if (!fw_dump.fadump_supported)
126 return;
127
128 pr_debug("Fadump enabled : %s\n",
129 (fw_dump.fadump_enabled ? "yes" : "no"));
130 pr_debug("Dump Active : %s\n",
131 (fw_dump.dump_active ? "yes" : "no"));
132 pr_debug("Dump section sizes:\n");
133 pr_debug(" CPU state data size: %lx\n", fw_dump.cpu_state_data_size);
134 pr_debug(" HPTE region size : %lx\n", fw_dump.hpte_region_size);
135 pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size);
136}
137
138static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
139 unsigned long addr)
140{
141 if (!fdm)
142 return 0;
143
144 memset(fdm, 0, sizeof(struct fadump_mem_struct));
145 addr = addr & PAGE_MASK;
146
147 fdm->header.dump_format_version = 0x00000001;
148 fdm->header.dump_num_sections = 3;
149 fdm->header.dump_status_flag = 0;
150 fdm->header.offset_first_dump_section =
151 (u32)offsetof(struct fadump_mem_struct, cpu_state_data);
152
153 /*
154 * Fields for disk dump option.
155 * We are not using disk dump option, hence set these fields to 0.
156 */
157 fdm->header.dd_block_size = 0;
158 fdm->header.dd_block_offset = 0;
159 fdm->header.dd_num_blocks = 0;
160 fdm->header.dd_offset_disk_path = 0;
161
162 /* set 0 to disable an automatic dump-reboot. */
163 fdm->header.max_time_auto = 0;
164
165 /* Kernel dump sections */
166 /* cpu state data section. */
167 fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG;
168 fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA;
169 fdm->cpu_state_data.source_address = 0;
170 fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size;
171 fdm->cpu_state_data.destination_address = addr;
172 addr += fw_dump.cpu_state_data_size;
173
174 /* hpte region section */
175 fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG;
176 fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION;
177 fdm->hpte_region.source_address = 0;
178 fdm->hpte_region.source_len = fw_dump.hpte_region_size;
179 fdm->hpte_region.destination_address = addr;
180 addr += fw_dump.hpte_region_size;
181
182 /* RMA region section */
183 fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG;
184 fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION;
185 fdm->rmr_region.source_address = RMA_START;
186 fdm->rmr_region.source_len = fw_dump.boot_memory_size;
187 fdm->rmr_region.destination_address = addr;
188 addr += fw_dump.boot_memory_size;
189
190 return addr;
191}
192
193/**
194 * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM
195 *
196 * Function to find the largest memory size we need to reserve during early
197 * boot process. This will be the size of the memory that is required for a
198 * kernel to boot successfully.
199 *
200 * This function has been taken from phyp-assisted dump feature implementation.
201 *
202 * returns larger of 256MB or 5% rounded down to multiples of 256MB.
203 *
204 * TODO: Come up with better approach to find out more accurate memory size
205 * that is required for a kernel to boot successfully.
206 *
207 */
208static inline unsigned long fadump_calculate_reserve_size(void)
209{
210 unsigned long size;
211
212 /*
213 * Check if the size is specified through fadump_reserve_mem= cmdline
214 * option. If yes, then use that.
215 */
216 if (fw_dump.reserve_bootvar)
217 return fw_dump.reserve_bootvar;
218
219 /* divide by 20 to get 5% of value */
220 size = memblock_end_of_DRAM() / 20;
221
222 /* round it down in multiples of 256 */
223 size = size & ~0x0FFFFFFFUL;
224
225 /* Truncate to memory_limit. We don't want to over reserve the memory.*/
226 if (memory_limit && size > memory_limit)
227 size = memory_limit;
228
229 return (size > MIN_BOOT_MEM ? size : MIN_BOOT_MEM);
230}
231
232/*
233 * Calculate the total memory size required to be reserved for
234 * firmware-assisted dump registration.
235 */
236static unsigned long get_fadump_area_size(void)
237{
238 unsigned long size = 0;
239
240 size += fw_dump.cpu_state_data_size;
241 size += fw_dump.hpte_region_size;
242 size += fw_dump.boot_memory_size;
243 size += sizeof(struct fadump_crash_info_header);
244 size += sizeof(struct elfhdr); /* ELF core header.*/
245 size += sizeof(struct elf_phdr); /* place holder for cpu notes */
246 /* Program headers for crash memory regions. */
247 size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2);
248
249 size = PAGE_ALIGN(size);
250 return size;
251}
252
253int __init fadump_reserve_mem(void)
254{
255 unsigned long base, size, memory_boundary;
256
257 if (!fw_dump.fadump_enabled)
258 return 0;
259
260 if (!fw_dump.fadump_supported) {
261 printk(KERN_INFO "Firmware-assisted dump is not supported on"
262 " this hardware\n");
263 fw_dump.fadump_enabled = 0;
264 return 0;
265 }
266 /*
267 * Initialize boot memory size
268 * If dump is active then we have already calculated the size during
269 * first kernel.
270 */
271 if (fdm_active)
272 fw_dump.boot_memory_size = fdm_active->rmr_region.source_len;
273 else
274 fw_dump.boot_memory_size = fadump_calculate_reserve_size();
275
276 /*
277 * Calculate the memory boundary.
278 * If memory_limit is less than actual memory boundary then reserve
279 * the memory for fadump beyond the memory_limit and adjust the
280 * memory_limit accordingly, so that the running kernel can run with
281 * specified memory_limit.
282 */
283 if (memory_limit && memory_limit < memblock_end_of_DRAM()) {
284 size = get_fadump_area_size();
285 if ((memory_limit + size) < memblock_end_of_DRAM())
286 memory_limit += size;
287 else
288 memory_limit = memblock_end_of_DRAM();
289 printk(KERN_INFO "Adjusted memory_limit for firmware-assisted"
290 " dump, now %#016llx\n",
291 (unsigned long long)memory_limit);
292 }
293 if (memory_limit)
294 memory_boundary = memory_limit;
295 else
296 memory_boundary = memblock_end_of_DRAM();
297
298 if (fw_dump.dump_active) {
299 printk(KERN_INFO "Firmware-assisted dump is active.\n");
300 /*
301 * If last boot has crashed then reserve all the memory
302 * above boot_memory_size so that we don't touch it until
303 * dump is written to disk by userspace tool. This memory
304 * will be released for general use once the dump is saved.
305 */
306 base = fw_dump.boot_memory_size;
307 size = memory_boundary - base;
308 memblock_reserve(base, size);
309 printk(KERN_INFO "Reserved %ldMB of memory at %ldMB "
310 "for saving crash dump\n",
311 (unsigned long)(size >> 20),
312 (unsigned long)(base >> 20));
313
314 fw_dump.fadumphdr_addr =
315 fdm_active->rmr_region.destination_address +
316 fdm_active->rmr_region.source_len;
317 pr_debug("fadumphdr_addr = %p\n",
318 (void *) fw_dump.fadumphdr_addr);
319 } else {
320 /* Reserve the memory at the top of memory. */
321 size = get_fadump_area_size();
322 base = memory_boundary - size;
323 memblock_reserve(base, size);
324 printk(KERN_INFO "Reserved %ldMB of memory at %ldMB "
325 "for firmware-assisted dump\n",
326 (unsigned long)(size >> 20),
327 (unsigned long)(base >> 20));
328 }
329 fw_dump.reserve_dump_area_start = base;
330 fw_dump.reserve_dump_area_size = size;
331 return 1;
332}
333
334/* Look for fadump= cmdline option. */
335static int __init early_fadump_param(char *p)
336{
337 if (!p)
338 return 1;
339
340 if (strncmp(p, "on", 2) == 0)
341 fw_dump.fadump_enabled = 1;
342 else if (strncmp(p, "off", 3) == 0)
343 fw_dump.fadump_enabled = 0;
344
345 return 0;
346}
347early_param("fadump", early_fadump_param);
348
349/* Look for fadump_reserve_mem= cmdline option */
350static int __init early_fadump_reserve_mem(char *p)
351{
352 if (p)
353 fw_dump.reserve_bootvar = memparse(p, &p);
354 return 0;
355}
356early_param("fadump_reserve_mem", early_fadump_reserve_mem);
357
358static void register_fw_dump(struct fadump_mem_struct *fdm)
359{
360 int rc;
361 unsigned int wait_time;
362
363 pr_debug("Registering for firmware-assisted kernel dump...\n");
364
365 /* TODO: Add upper time limit for the delay */
366 do {
367 rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL,
368 FADUMP_REGISTER, fdm,
369 sizeof(struct fadump_mem_struct));
370
371 wait_time = rtas_busy_delay_time(rc);
372 if (wait_time)
373 mdelay(wait_time);
374
375 } while (wait_time);
376
377 switch (rc) {
378 case -1:
379 printk(KERN_ERR "Failed to register firmware-assisted kernel"
380 " dump. Hardware Error(%d).\n", rc);
381 break;
382 case -3:
383 printk(KERN_ERR "Failed to register firmware-assisted kernel"
384 " dump. Parameter Error(%d).\n", rc);
385 break;
386 case -9:
387 printk(KERN_ERR "firmware-assisted kernel dump is already "
388 " registered.");
389 fw_dump.dump_registered = 1;
390 break;
391 case 0:
392 printk(KERN_INFO "firmware-assisted kernel dump registration"
393 " is successful\n");
394 fw_dump.dump_registered = 1;
395 break;
396 }
397}
398
399void crash_fadump(struct pt_regs *regs, const char *str)
400{
401 struct fadump_crash_info_header *fdh = NULL;
402
403 if (!fw_dump.dump_registered || !fw_dump.fadumphdr_addr)
404 return;
405
406 fdh = __va(fw_dump.fadumphdr_addr);
407 crashing_cpu = smp_processor_id();
408 fdh->crashing_cpu = crashing_cpu;
409 crash_save_vmcoreinfo();
410
411 if (regs)
412 fdh->regs = *regs;
413 else
414 ppc_save_regs(&fdh->regs);
415
416 fdh->cpu_online_mask = *cpu_online_mask;
417
418 /* Call ibm,os-term rtas call to trigger firmware assisted dump */
419 rtas_os_term((char *)str);
420}
421
422#define GPR_MASK 0xffffff0000000000
423static inline int fadump_gpr_index(u64 id)
424{
425 int i = -1;
426 char str[3];
427
428 if ((id & GPR_MASK) == REG_ID("GPR")) {
429 /* get the digits at the end */
430 id &= ~GPR_MASK;
431 id >>= 24;
432 str[2] = '\0';
433 str[1] = id & 0xff;
434 str[0] = (id >> 8) & 0xff;
435 sscanf(str, "%d", &i);
436 if (i > 31)
437 i = -1;
438 }
439 return i;
440}
441
442static inline void fadump_set_regval(struct pt_regs *regs, u64 reg_id,
443 u64 reg_val)
444{
445 int i;
446
447 i = fadump_gpr_index(reg_id);
448 if (i >= 0)
449 regs->gpr[i] = (unsigned long)reg_val;
450 else if (reg_id == REG_ID("NIA"))
451 regs->nip = (unsigned long)reg_val;
452 else if (reg_id == REG_ID("MSR"))
453 regs->msr = (unsigned long)reg_val;
454 else if (reg_id == REG_ID("CTR"))
455 regs->ctr = (unsigned long)reg_val;
456 else if (reg_id == REG_ID("LR"))
457 regs->link = (unsigned long)reg_val;
458 else if (reg_id == REG_ID("XER"))
459 regs->xer = (unsigned long)reg_val;
460 else if (reg_id == REG_ID("CR"))
461 regs->ccr = (unsigned long)reg_val;
462 else if (reg_id == REG_ID("DAR"))
463 regs->dar = (unsigned long)reg_val;
464 else if (reg_id == REG_ID("DSISR"))
465 regs->dsisr = (unsigned long)reg_val;
466}
467
468static struct fadump_reg_entry*
469fadump_read_registers(struct fadump_reg_entry *reg_entry, struct pt_regs *regs)
470{
471 memset(regs, 0, sizeof(struct pt_regs));
472
473 while (reg_entry->reg_id != REG_ID("CPUEND")) {
474 fadump_set_regval(regs, reg_entry->reg_id,
475 reg_entry->reg_value);
476 reg_entry++;
477 }
478 reg_entry++;
479 return reg_entry;
480}
481
482static u32 *fadump_append_elf_note(u32 *buf, char *name, unsigned type,
483 void *data, size_t data_len)
484{
485 struct elf_note note;
486
487 note.n_namesz = strlen(name) + 1;
488 note.n_descsz = data_len;
489 note.n_type = type;
490 memcpy(buf, &note, sizeof(note));
491 buf += (sizeof(note) + 3)/4;
492 memcpy(buf, name, note.n_namesz);
493 buf += (note.n_namesz + 3)/4;
494 memcpy(buf, data, note.n_descsz);
495 buf += (note.n_descsz + 3)/4;
496
497 return buf;
498}
499
500static void fadump_final_note(u32 *buf)
501{
502 struct elf_note note;
503
504 note.n_namesz = 0;
505 note.n_descsz = 0;
506 note.n_type = 0;
507 memcpy(buf, &note, sizeof(note));
508}
509
510static u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs)
511{
512 struct elf_prstatus prstatus;
513
514 memset(&prstatus, 0, sizeof(prstatus));
515 /*
516 * FIXME: How do i get PID? Do I really need it?
517 * prstatus.pr_pid = ????
518 */
519 elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
520 buf = fadump_append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
521 &prstatus, sizeof(prstatus));
522 return buf;
523}
524
525static void fadump_update_elfcore_header(char *bufp)
526{
527 struct elfhdr *elf;
528 struct elf_phdr *phdr;
529
530 elf = (struct elfhdr *)bufp;
531 bufp += sizeof(struct elfhdr);
532
533 /* First note is a place holder for cpu notes info. */
534 phdr = (struct elf_phdr *)bufp;
535
536 if (phdr->p_type == PT_NOTE) {
537 phdr->p_paddr = fw_dump.cpu_notes_buf;
538 phdr->p_offset = phdr->p_paddr;
539 phdr->p_filesz = fw_dump.cpu_notes_buf_size;
540 phdr->p_memsz = fw_dump.cpu_notes_buf_size;
541 }
542 return;
543}
544
545static void *fadump_cpu_notes_buf_alloc(unsigned long size)
546{
547 void *vaddr;
548 struct page *page;
549 unsigned long order, count, i;
550
551 order = get_order(size);
552 vaddr = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
553 if (!vaddr)
554 return NULL;
555
556 count = 1 << order;
557 page = virt_to_page(vaddr);
558 for (i = 0; i < count; i++)
559 SetPageReserved(page + i);
560 return vaddr;
561}
562
563static void fadump_cpu_notes_buf_free(unsigned long vaddr, unsigned long size)
564{
565 struct page *page;
566 unsigned long order, count, i;
567
568 order = get_order(size);
569 count = 1 << order;
570 page = virt_to_page(vaddr);
571 for (i = 0; i < count; i++)
572 ClearPageReserved(page + i);
573 __free_pages(page, order);
574}
575
576/*
577 * Read CPU state dump data and convert it into ELF notes.
578 * The CPU dump starts with magic number "REGSAVE". NumCpusOffset should be
579 * used to access the data to allow for additional fields to be added without
580 * affecting compatibility. Each list of registers for a CPU starts with
581 * "CPUSTRT" and ends with "CPUEND". Each register entry is of 16 bytes,
582 * 8 Byte ASCII identifier and 8 Byte register value. The register entry
583 * with identifier "CPUSTRT" and "CPUEND" contains 4 byte cpu id as part
584 * of register value. For more details refer to PAPR document.
585 *
586 * Only for the crashing cpu we ignore the CPU dump data and get exact
587 * state from fadump crash info structure populated by first kernel at the
588 * time of crash.
589 */
590static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
591{
592 struct fadump_reg_save_area_header *reg_header;
593 struct fadump_reg_entry *reg_entry;
594 struct fadump_crash_info_header *fdh = NULL;
595 void *vaddr;
596 unsigned long addr;
597 u32 num_cpus, *note_buf;
598 struct pt_regs regs;
599 int i, rc = 0, cpu = 0;
600
601 if (!fdm->cpu_state_data.bytes_dumped)
602 return -EINVAL;
603
604 addr = fdm->cpu_state_data.destination_address;
605 vaddr = __va(addr);
606
607 reg_header = vaddr;
608 if (reg_header->magic_number != REGSAVE_AREA_MAGIC) {
609 printk(KERN_ERR "Unable to read register save area.\n");
610 return -ENOENT;
611 }
612 pr_debug("--------CPU State Data------------\n");
613 pr_debug("Magic Number: %llx\n", reg_header->magic_number);
614 pr_debug("NumCpuOffset: %x\n", reg_header->num_cpu_offset);
615
616 vaddr += reg_header->num_cpu_offset;
617 num_cpus = *((u32 *)(vaddr));
618 pr_debug("NumCpus : %u\n", num_cpus);
619 vaddr += sizeof(u32);
620 reg_entry = (struct fadump_reg_entry *)vaddr;
621
622 /* Allocate buffer to hold cpu crash notes. */
623 fw_dump.cpu_notes_buf_size = num_cpus * sizeof(note_buf_t);
624 fw_dump.cpu_notes_buf_size = PAGE_ALIGN(fw_dump.cpu_notes_buf_size);
625 note_buf = fadump_cpu_notes_buf_alloc(fw_dump.cpu_notes_buf_size);
626 if (!note_buf) {
627 printk(KERN_ERR "Failed to allocate 0x%lx bytes for "
628 "cpu notes buffer\n", fw_dump.cpu_notes_buf_size);
629 return -ENOMEM;
630 }
631 fw_dump.cpu_notes_buf = __pa(note_buf);
632
633 pr_debug("Allocated buffer for cpu notes of size %ld at %p\n",
634 (num_cpus * sizeof(note_buf_t)), note_buf);
635
636 if (fw_dump.fadumphdr_addr)
637 fdh = __va(fw_dump.fadumphdr_addr);
638
639 for (i = 0; i < num_cpus; i++) {
640 if (reg_entry->reg_id != REG_ID("CPUSTRT")) {
641 printk(KERN_ERR "Unable to read CPU state data\n");
642 rc = -ENOENT;
643 goto error_out;
644 }
645 /* Lower 4 bytes of reg_value contains logical cpu id */
646 cpu = reg_entry->reg_value & FADUMP_CPU_ID_MASK;
647 if (!cpumask_test_cpu(cpu, &fdh->cpu_online_mask)) {
648 SKIP_TO_NEXT_CPU(reg_entry);
649 continue;
650 }
651 pr_debug("Reading register data for cpu %d...\n", cpu);
652 if (fdh && fdh->crashing_cpu == cpu) {
653 regs = fdh->regs;
654 note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
655 SKIP_TO_NEXT_CPU(reg_entry);
656 } else {
657 reg_entry++;
658 reg_entry = fadump_read_registers(reg_entry, &regs);
659 note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
660 }
661 }
662 fadump_final_note(note_buf);
663
664 pr_debug("Updating elfcore header (%llx) with cpu notes\n",
665 fdh->elfcorehdr_addr);
666 fadump_update_elfcore_header((char *)__va(fdh->elfcorehdr_addr));
667 return 0;
668
669error_out:
670 fadump_cpu_notes_buf_free((unsigned long)__va(fw_dump.cpu_notes_buf),
671 fw_dump.cpu_notes_buf_size);
672 fw_dump.cpu_notes_buf = 0;
673 fw_dump.cpu_notes_buf_size = 0;
674 return rc;
675
676}
677
678/*
679 * Validate and process the dump data stored by firmware before exporting
680 * it through '/proc/vmcore'.
681 */
682static int __init process_fadump(const struct fadump_mem_struct *fdm_active)
683{
684 struct fadump_crash_info_header *fdh;
685 int rc = 0;
686
687 if (!fdm_active || !fw_dump.fadumphdr_addr)
688 return -EINVAL;
689
690 /* Check if the dump data is valid. */
691 if ((fdm_active->header.dump_status_flag == FADUMP_ERROR_FLAG) ||
692 (fdm_active->cpu_state_data.error_flags != 0) ||
693 (fdm_active->rmr_region.error_flags != 0)) {
694 printk(KERN_ERR "Dump taken by platform is not valid\n");
695 return -EINVAL;
696 }
697 if ((fdm_active->rmr_region.bytes_dumped !=
698 fdm_active->rmr_region.source_len) ||
699 !fdm_active->cpu_state_data.bytes_dumped) {
700 printk(KERN_ERR "Dump taken by platform is incomplete\n");
701 return -EINVAL;
702 }
703
704 /* Validate the fadump crash info header */
705 fdh = __va(fw_dump.fadumphdr_addr);
706 if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) {
707 printk(KERN_ERR "Crash info header is not valid.\n");
708 return -EINVAL;
709 }
710
711 rc = fadump_build_cpu_notes(fdm_active);
712 if (rc)
713 return rc;
714
715 /*
716 * We are done validating dump info and elfcore header is now ready
717 * to be exported. set elfcorehdr_addr so that vmcore module will
718 * export the elfcore header through '/proc/vmcore'.
719 */
720 elfcorehdr_addr = fdh->elfcorehdr_addr;
721
722 return 0;
723}
724
725static inline void fadump_add_crash_memory(unsigned long long base,
726 unsigned long long end)
727{
728 if (base == end)
729 return;
730
731 pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n",
732 crash_mem_ranges, base, end - 1, (end - base));
733 crash_memory_ranges[crash_mem_ranges].base = base;
734 crash_memory_ranges[crash_mem_ranges].size = end - base;
735 crash_mem_ranges++;
736}
737
738static void fadump_exclude_reserved_area(unsigned long long start,
739 unsigned long long end)
740{
741 unsigned long long ra_start, ra_end;
742
743 ra_start = fw_dump.reserve_dump_area_start;
744 ra_end = ra_start + fw_dump.reserve_dump_area_size;
745
746 if ((ra_start < end) && (ra_end > start)) {
747 if ((start < ra_start) && (end > ra_end)) {
748 fadump_add_crash_memory(start, ra_start);
749 fadump_add_crash_memory(ra_end, end);
750 } else if (start < ra_start) {
751 fadump_add_crash_memory(start, ra_start);
752 } else if (ra_end < end) {
753 fadump_add_crash_memory(ra_end, end);
754 }
755 } else
756 fadump_add_crash_memory(start, end);
757}
758
759static int fadump_init_elfcore_header(char *bufp)
760{
761 struct elfhdr *elf;
762
763 elf = (struct elfhdr *) bufp;
764 bufp += sizeof(struct elfhdr);
765 memcpy(elf->e_ident, ELFMAG, SELFMAG);
766 elf->e_ident[EI_CLASS] = ELF_CLASS;
767 elf->e_ident[EI_DATA] = ELF_DATA;
768 elf->e_ident[EI_VERSION] = EV_CURRENT;
769 elf->e_ident[EI_OSABI] = ELF_OSABI;
770 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
771 elf->e_type = ET_CORE;
772 elf->e_machine = ELF_ARCH;
773 elf->e_version = EV_CURRENT;
774 elf->e_entry = 0;
775 elf->e_phoff = sizeof(struct elfhdr);
776 elf->e_shoff = 0;
777 elf->e_flags = ELF_CORE_EFLAGS;
778 elf->e_ehsize = sizeof(struct elfhdr);
779 elf->e_phentsize = sizeof(struct elf_phdr);
780 elf->e_phnum = 0;
781 elf->e_shentsize = 0;
782 elf->e_shnum = 0;
783 elf->e_shstrndx = 0;
784
785 return 0;
786}
787
788/*
789 * Traverse through memblock structure and setup crash memory ranges. These
790 * ranges will be used create PT_LOAD program headers in elfcore header.
791 */
792static void fadump_setup_crash_memory_ranges(void)
793{
794 struct memblock_region *reg;
795 unsigned long long start, end;
796
797 pr_debug("Setup crash memory ranges.\n");
798 crash_mem_ranges = 0;
799 /*
800 * add the first memory chunk (RMA_START through boot_memory_size) as
801 * a separate memory chunk. The reason is, at the time crash firmware
802 * will move the content of this memory chunk to different location
803 * specified during fadump registration. We need to create a separate
804 * program header for this chunk with the correct offset.
805 */
806 fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size);
807
808 for_each_memblock(memory, reg) {
809 start = (unsigned long long)reg->base;
810 end = start + (unsigned long long)reg->size;
811 if (start == RMA_START && end >= fw_dump.boot_memory_size)
812 start = fw_dump.boot_memory_size;
813
814 /* add this range excluding the reserved dump area. */
815 fadump_exclude_reserved_area(start, end);
816 }
817}
818
819/*
820 * If the given physical address falls within the boot memory region then
821 * return the relocated address that points to the dump region reserved
822 * for saving initial boot memory contents.
823 */
824static inline unsigned long fadump_relocate(unsigned long paddr)
825{
826 if (paddr > RMA_START && paddr < fw_dump.boot_memory_size)
827 return fdm.rmr_region.destination_address + paddr;
828 else
829 return paddr;
830}
831
832static int fadump_create_elfcore_headers(char *bufp)
833{
834 struct elfhdr *elf;
835 struct elf_phdr *phdr;
836 int i;
837
838 fadump_init_elfcore_header(bufp);
839 elf = (struct elfhdr *)bufp;
840 bufp += sizeof(struct elfhdr);
841
842 /*
843 * setup ELF PT_NOTE, place holder for cpu notes info. The notes info
844 * will be populated during second kernel boot after crash. Hence
845 * this PT_NOTE will always be the first elf note.
846 *
847 * NOTE: Any new ELF note addition should be placed after this note.
848 */
849 phdr = (struct elf_phdr *)bufp;
850 bufp += sizeof(struct elf_phdr);
851 phdr->p_type = PT_NOTE;
852 phdr->p_flags = 0;
853 phdr->p_vaddr = 0;
854 phdr->p_align = 0;
855
856 phdr->p_offset = 0;
857 phdr->p_paddr = 0;
858 phdr->p_filesz = 0;
859 phdr->p_memsz = 0;
860
861 (elf->e_phnum)++;
862
863 /* setup ELF PT_NOTE for vmcoreinfo */
864 phdr = (struct elf_phdr *)bufp;
865 bufp += sizeof(struct elf_phdr);
866 phdr->p_type = PT_NOTE;
867 phdr->p_flags = 0;
868 phdr->p_vaddr = 0;
869 phdr->p_align = 0;
870
871 phdr->p_paddr = fadump_relocate(paddr_vmcoreinfo_note());
872 phdr->p_offset = phdr->p_paddr;
873 phdr->p_memsz = vmcoreinfo_max_size;
874 phdr->p_filesz = vmcoreinfo_max_size;
875
876 /* Increment number of program headers. */
877 (elf->e_phnum)++;
878
879 /* setup PT_LOAD sections. */
880
881 for (i = 0; i < crash_mem_ranges; i++) {
882 unsigned long long mbase, msize;
883 mbase = crash_memory_ranges[i].base;
884 msize = crash_memory_ranges[i].size;
885
886 if (!msize)
887 continue;
888
889 phdr = (struct elf_phdr *)bufp;
890 bufp += sizeof(struct elf_phdr);
891 phdr->p_type = PT_LOAD;
892 phdr->p_flags = PF_R|PF_W|PF_X;
893 phdr->p_offset = mbase;
894
895 if (mbase == RMA_START) {
896 /*
897 * The entire RMA region will be moved by firmware
898 * to the specified destination_address. Hence set
899 * the correct offset.
900 */
901 phdr->p_offset = fdm.rmr_region.destination_address;
902 }
903
904 phdr->p_paddr = mbase;
905 phdr->p_vaddr = (unsigned long)__va(mbase);
906 phdr->p_filesz = msize;
907 phdr->p_memsz = msize;
908 phdr->p_align = 0;
909
910 /* Increment number of program headers. */
911 (elf->e_phnum)++;
912 }
913 return 0;
914}
915
916static unsigned long init_fadump_header(unsigned long addr)
917{
918 struct fadump_crash_info_header *fdh;
919
920 if (!addr)
921 return 0;
922
923 fw_dump.fadumphdr_addr = addr;
924 fdh = __va(addr);
925 addr += sizeof(struct fadump_crash_info_header);
926
927 memset(fdh, 0, sizeof(struct fadump_crash_info_header));
928 fdh->magic_number = FADUMP_CRASH_INFO_MAGIC;
929 fdh->elfcorehdr_addr = addr;
930 /* We will set the crashing cpu id in crash_fadump() during crash. */
931 fdh->crashing_cpu = CPU_UNKNOWN;
932
933 return addr;
934}
935
936static void register_fadump(void)
937{
938 unsigned long addr;
939 void *vaddr;
940
941 /*
942 * If no memory is reserved then we can not register for firmware-
943 * assisted dump.
944 */
945 if (!fw_dump.reserve_dump_area_size)
946 return;
947
948 fadump_setup_crash_memory_ranges();
949
950 addr = fdm.rmr_region.destination_address + fdm.rmr_region.source_len;
951 /* Initialize fadump crash info header. */
952 addr = init_fadump_header(addr);
953 vaddr = __va(addr);
954
955 pr_debug("Creating ELF core headers at %#016lx\n", addr);
956 fadump_create_elfcore_headers(vaddr);
957
958 /* register the future kernel dump with firmware. */
959 register_fw_dump(&fdm);
960}
961
962static int fadump_unregister_dump(struct fadump_mem_struct *fdm)
963{
964 int rc = 0;
965 unsigned int wait_time;
966
967 pr_debug("Un-register firmware-assisted dump\n");
968
969 /* TODO: Add upper time limit for the delay */
970 do {
971 rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL,
972 FADUMP_UNREGISTER, fdm,
973 sizeof(struct fadump_mem_struct));
974
975 wait_time = rtas_busy_delay_time(rc);
976 if (wait_time)
977 mdelay(wait_time);
978 } while (wait_time);
979
980 if (rc) {
981 printk(KERN_ERR "Failed to un-register firmware-assisted dump."
982 " unexpected error(%d).\n", rc);
983 return rc;
984 }
985 fw_dump.dump_registered = 0;
986 return 0;
987}
988
989static int fadump_invalidate_dump(struct fadump_mem_struct *fdm)
990{
991 int rc = 0;
992 unsigned int wait_time;
993
994 pr_debug("Invalidating firmware-assisted dump registration\n");
995
996 /* TODO: Add upper time limit for the delay */
997 do {
998 rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL,
999 FADUMP_INVALIDATE, fdm,
1000 sizeof(struct fadump_mem_struct));
1001
1002 wait_time = rtas_busy_delay_time(rc);
1003 if (wait_time)
1004 mdelay(wait_time);
1005 } while (wait_time);
1006
1007 if (rc) {
1008 printk(KERN_ERR "Failed to invalidate firmware-assisted dump "
1009 "rgistration. unexpected error(%d).\n", rc);
1010 return rc;
1011 }
1012 fw_dump.dump_active = 0;
1013 fdm_active = NULL;
1014 return 0;
1015}
1016
1017void fadump_cleanup(void)
1018{
1019 /* Invalidate the registration only if dump is active. */
1020 if (fw_dump.dump_active) {
1021 init_fadump_mem_struct(&fdm,
1022 fdm_active->cpu_state_data.destination_address);
1023 fadump_invalidate_dump(&fdm);
1024 }
1025}
1026
1027/*
1028 * Release the memory that was reserved in early boot to preserve the memory
1029 * contents. The released memory will be available for general use.
1030 */
1031static void fadump_release_memory(unsigned long begin, unsigned long end)
1032{
1033 unsigned long addr;
1034 unsigned long ra_start, ra_end;
1035
1036 ra_start = fw_dump.reserve_dump_area_start;
1037 ra_end = ra_start + fw_dump.reserve_dump_area_size;
1038
1039 for (addr = begin; addr < end; addr += PAGE_SIZE) {
1040 /*
1041 * exclude the dump reserve area. Will reuse it for next
1042 * fadump registration.
1043 */
1044 if (addr <= ra_end && ((addr + PAGE_SIZE) > ra_start))
1045 continue;
1046
1047 ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
1048 init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
1049 free_page((unsigned long)__va(addr));
1050 totalram_pages++;
1051 }
1052}
1053
1054static void fadump_invalidate_release_mem(void)
1055{
1056 unsigned long reserved_area_start, reserved_area_end;
1057 unsigned long destination_address;
1058
1059 mutex_lock(&fadump_mutex);
1060 if (!fw_dump.dump_active) {
1061 mutex_unlock(&fadump_mutex);
1062 return;
1063 }
1064
1065 destination_address = fdm_active->cpu_state_data.destination_address;
1066 fadump_cleanup();
1067 mutex_unlock(&fadump_mutex);
1068
1069 /*
1070 * Save the current reserved memory bounds we will require them
1071 * later for releasing the memory for general use.
1072 */
1073 reserved_area_start = fw_dump.reserve_dump_area_start;
1074 reserved_area_end = reserved_area_start +
1075 fw_dump.reserve_dump_area_size;
1076 /*
1077 * Setup reserve_dump_area_start and its size so that we can
1078 * reuse this reserved memory for Re-registration.
1079 */
1080 fw_dump.reserve_dump_area_start = destination_address;
1081 fw_dump.reserve_dump_area_size = get_fadump_area_size();
1082
1083 fadump_release_memory(reserved_area_start, reserved_area_end);
1084 if (fw_dump.cpu_notes_buf) {
1085 fadump_cpu_notes_buf_free(
1086 (unsigned long)__va(fw_dump.cpu_notes_buf),
1087 fw_dump.cpu_notes_buf_size);
1088 fw_dump.cpu_notes_buf = 0;
1089 fw_dump.cpu_notes_buf_size = 0;
1090 }
1091 /* Initialize the kernel dump memory structure for FAD registration. */
1092 init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
1093}
1094
1095static ssize_t fadump_release_memory_store(struct kobject *kobj,
1096 struct kobj_attribute *attr,
1097 const char *buf, size_t count)
1098{
1099 if (!fw_dump.dump_active)
1100 return -EPERM;
1101
1102 if (buf[0] == '1') {
1103 /*
1104 * Take away the '/proc/vmcore'. We are releasing the dump
1105 * memory, hence it will not be valid anymore.
1106 */
1107 vmcore_cleanup();
1108 fadump_invalidate_release_mem();
1109
1110 } else
1111 return -EINVAL;
1112 return count;
1113}
1114
1115static ssize_t fadump_enabled_show(struct kobject *kobj,
1116 struct kobj_attribute *attr,
1117 char *buf)
1118{
1119 return sprintf(buf, "%d\n", fw_dump.fadump_enabled);
1120}
1121
1122static ssize_t fadump_register_show(struct kobject *kobj,
1123 struct kobj_attribute *attr,
1124 char *buf)
1125{
1126 return sprintf(buf, "%d\n", fw_dump.dump_registered);
1127}
1128
1129static ssize_t fadump_register_store(struct kobject *kobj,
1130 struct kobj_attribute *attr,
1131 const char *buf, size_t count)
1132{
1133 int ret = 0;
1134
1135 if (!fw_dump.fadump_enabled || fdm_active)
1136 return -EPERM;
1137
1138 mutex_lock(&fadump_mutex);
1139
1140 switch (buf[0]) {
1141 case '0':
1142 if (fw_dump.dump_registered == 0) {
1143 ret = -EINVAL;
1144 goto unlock_out;
1145 }
1146 /* Un-register Firmware-assisted dump */
1147 fadump_unregister_dump(&fdm);
1148 break;
1149 case '1':
1150 if (fw_dump.dump_registered == 1) {
1151 ret = -EINVAL;
1152 goto unlock_out;
1153 }
1154 /* Register Firmware-assisted dump */
1155 register_fadump();
1156 break;
1157 default:
1158 ret = -EINVAL;
1159 break;
1160 }
1161
1162unlock_out:
1163 mutex_unlock(&fadump_mutex);
1164 return ret < 0 ? ret : count;
1165}
1166
1167static int fadump_region_show(struct seq_file *m, void *private)
1168{
1169 const struct fadump_mem_struct *fdm_ptr;
1170
1171 if (!fw_dump.fadump_enabled)
1172 return 0;
1173
1174 mutex_lock(&fadump_mutex);
1175 if (fdm_active)
1176 fdm_ptr = fdm_active;
1177 else {
1178 mutex_unlock(&fadump_mutex);
1179 fdm_ptr = &fdm;
1180 }
1181
1182 seq_printf(m,
1183 "CPU : [%#016llx-%#016llx] %#llx bytes, "
1184 "Dumped: %#llx\n",
1185 fdm_ptr->cpu_state_data.destination_address,
1186 fdm_ptr->cpu_state_data.destination_address +
1187 fdm_ptr->cpu_state_data.source_len - 1,
1188 fdm_ptr->cpu_state_data.source_len,
1189 fdm_ptr->cpu_state_data.bytes_dumped);
1190 seq_printf(m,
1191 "HPTE: [%#016llx-%#016llx] %#llx bytes, "
1192 "Dumped: %#llx\n",
1193 fdm_ptr->hpte_region.destination_address,
1194 fdm_ptr->hpte_region.destination_address +
1195 fdm_ptr->hpte_region.source_len - 1,
1196 fdm_ptr->hpte_region.source_len,
1197 fdm_ptr->hpte_region.bytes_dumped);
1198 seq_printf(m,
1199 "DUMP: [%#016llx-%#016llx] %#llx bytes, "
1200 "Dumped: %#llx\n",
1201 fdm_ptr->rmr_region.destination_address,
1202 fdm_ptr->rmr_region.destination_address +
1203 fdm_ptr->rmr_region.source_len - 1,
1204 fdm_ptr->rmr_region.source_len,
1205 fdm_ptr->rmr_region.bytes_dumped);
1206
1207 if (!fdm_active ||
1208 (fw_dump.reserve_dump_area_start ==
1209 fdm_ptr->cpu_state_data.destination_address))
1210 goto out;
1211
1212 /* Dump is active. Show reserved memory region. */
1213 seq_printf(m,
1214 " : [%#016llx-%#016llx] %#llx bytes, "
1215 "Dumped: %#llx\n",
1216 (unsigned long long)fw_dump.reserve_dump_area_start,
1217 fdm_ptr->cpu_state_data.destination_address - 1,
1218 fdm_ptr->cpu_state_data.destination_address -
1219 fw_dump.reserve_dump_area_start,
1220 fdm_ptr->cpu_state_data.destination_address -
1221 fw_dump.reserve_dump_area_start);
1222out:
1223 if (fdm_active)
1224 mutex_unlock(&fadump_mutex);
1225 return 0;
1226}
1227
1228static struct kobj_attribute fadump_release_attr = __ATTR(fadump_release_mem,
1229 0200, NULL,
1230 fadump_release_memory_store);
1231static struct kobj_attribute fadump_attr = __ATTR(fadump_enabled,
1232 0444, fadump_enabled_show,
1233 NULL);
1234static struct kobj_attribute fadump_register_attr = __ATTR(fadump_registered,
1235 0644, fadump_register_show,
1236 fadump_register_store);
1237
1238static int fadump_region_open(struct inode *inode, struct file *file)
1239{
1240 return single_open(file, fadump_region_show, inode->i_private);
1241}
1242
1243static const struct file_operations fadump_region_fops = {
1244 .open = fadump_region_open,
1245 .read = seq_read,
1246 .llseek = seq_lseek,
1247 .release = single_release,
1248};
1249
1250static void fadump_init_files(void)
1251{
1252 struct dentry *debugfs_file;
1253 int rc = 0;
1254
1255 rc = sysfs_create_file(kernel_kobj, &fadump_attr.attr);
1256 if (rc)
1257 printk(KERN_ERR "fadump: unable to create sysfs file"
1258 " fadump_enabled (%d)\n", rc);
1259
1260 rc = sysfs_create_file(kernel_kobj, &fadump_register_attr.attr);
1261 if (rc)
1262 printk(KERN_ERR "fadump: unable to create sysfs file"
1263 " fadump_registered (%d)\n", rc);
1264
1265 debugfs_file = debugfs_create_file("fadump_region", 0444,
1266 powerpc_debugfs_root, NULL,
1267 &fadump_region_fops);
1268 if (!debugfs_file)
1269 printk(KERN_ERR "fadump: unable to create debugfs file"
1270 " fadump_region\n");
1271
1272 if (fw_dump.dump_active) {
1273 rc = sysfs_create_file(kernel_kobj, &fadump_release_attr.attr);
1274 if (rc)
1275 printk(KERN_ERR "fadump: unable to create sysfs file"
1276 " fadump_release_mem (%d)\n", rc);
1277 }
1278 return;
1279}
1280
1281/*
1282 * Prepare for firmware-assisted dump.
1283 */
1284int __init setup_fadump(void)
1285{
1286 if (!fw_dump.fadump_enabled)
1287 return 0;
1288
1289 if (!fw_dump.fadump_supported) {
1290 printk(KERN_ERR "Firmware-assisted dump is not supported on"
1291 " this hardware\n");
1292 return 0;
1293 }
1294
1295 fadump_show_config();
1296 /*
1297 * If dump data is available then see if it is valid and prepare for
1298 * saving it to the disk.
1299 */
1300 if (fw_dump.dump_active) {
1301 /*
1302 * if dump process fails then invalidate the registration
1303 * and release memory before proceeding for re-registration.
1304 */
1305 if (process_fadump(fdm_active) < 0)
1306 fadump_invalidate_release_mem();
1307 }
1308 /* Initialize the kernel dump memory structure for FAD registration. */
1309 else if (fw_dump.reserve_dump_area_size)
1310 init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
1311 fadump_init_files();
1312
1313 return 1;
1314}
1315subsys_initcall(setup_fadump);
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 0654dba2c1f1..dc0488b6f6e1 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -395,7 +395,7 @@ DataAccess:
395 bl hash_page 395 bl hash_page
3961: lwz r5,_DSISR(r11) /* get DSISR value */ 3961: lwz r5,_DSISR(r11) /* get DSISR value */
397 mfspr r4,SPRN_DAR 397 mfspr r4,SPRN_DAR
398 EXC_XFER_EE_LITE(0x300, handle_page_fault) 398 EXC_XFER_LITE(0x300, handle_page_fault)
399 399
400 400
401/* Instruction access exception. */ 401/* Instruction access exception. */
@@ -410,7 +410,7 @@ InstructionAccess:
410 bl hash_page 410 bl hash_page
4111: mr r4,r12 4111: mr r4,r12
412 mr r5,r9 412 mr r5,r9
413 EXC_XFER_EE_LITE(0x400, handle_page_fault) 413 EXC_XFER_LITE(0x400, handle_page_fault)
414 414
415/* External interrupt */ 415/* External interrupt */
416 EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) 416 EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S
index 872a6af83bad..4989661b710b 100644
--- a/arch/powerpc/kernel/head_40x.S
+++ b/arch/powerpc/kernel/head_40x.S
@@ -394,7 +394,7 @@ label:
394 NORMAL_EXCEPTION_PROLOG 394 NORMAL_EXCEPTION_PROLOG
395 mr r4,r12 /* Pass SRR0 as arg2 */ 395 mr r4,r12 /* Pass SRR0 as arg2 */
396 li r5,0 /* Pass zero as arg3 */ 396 li r5,0 /* Pass zero as arg3 */
397 EXC_XFER_EE_LITE(0x400, handle_page_fault) 397 EXC_XFER_LITE(0x400, handle_page_fault)
398 398
399/* 0x0500 - External Interrupt Exception */ 399/* 0x0500 - External Interrupt Exception */
400 EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) 400 EXCEPTION(0x0500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
@@ -747,7 +747,7 @@ DataAccess:
747 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ 747 mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */
748 stw r5,_ESR(r11) 748 stw r5,_ESR(r11)
749 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 749 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
750 EXC_XFER_EE_LITE(0x300, handle_page_fault) 750 EXC_XFER_LITE(0x300, handle_page_fault)
751 751
752/* Other PowerPC processors, namely those derived from the 6xx-series 752/* Other PowerPC processors, namely those derived from the 6xx-series
753 * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved. 753 * have vectors from 0x2100 through 0x2F00 defined, but marked as reserved.
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 06c7251c1bf7..58bddee8e1e8 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -32,13 +32,13 @@
32#include <asm/cputable.h> 32#include <asm/cputable.h>
33#include <asm/setup.h> 33#include <asm/setup.h>
34#include <asm/hvcall.h> 34#include <asm/hvcall.h>
35#include <asm/iseries/lpar_map.h>
36#include <asm/thread_info.h> 35#include <asm/thread_info.h>
37#include <asm/firmware.h> 36#include <asm/firmware.h>
38#include <asm/page_64.h> 37#include <asm/page_64.h>
39#include <asm/irqflags.h> 38#include <asm/irqflags.h>
40#include <asm/kvm_book3s_asm.h> 39#include <asm/kvm_book3s_asm.h>
41#include <asm/ptrace.h> 40#include <asm/ptrace.h>
41#include <asm/hw_irq.h>
42 42
43/* The physical memory is laid out such that the secondary processor 43/* The physical memory is laid out such that the secondary processor
44 * spin code sits at 0x0000...0x00ff. On server, the vectors follow 44 * spin code sits at 0x0000...0x00ff. On server, the vectors follow
@@ -57,10 +57,6 @@
57 * entry in r9 for debugging purposes 57 * entry in r9 for debugging purposes
58 * 2. Secondary processors enter at 0x60 with PIR in gpr3 58 * 2. Secondary processors enter at 0x60 with PIR in gpr3
59 * 59 *
60 * For iSeries:
61 * 1. The MMU is on (as it always is for iSeries)
62 * 2. The kernel is entered at system_reset_iSeries
63 *
64 * For Book3E processors: 60 * For Book3E processors:
65 * 1. The MMU is on running in AS0 in a state defined in ePAPR 61 * 1. The MMU is on running in AS0 in a state defined in ePAPR
66 * 2. The kernel is entered at __start 62 * 2. The kernel is entered at __start
@@ -93,15 +89,6 @@ __secondary_hold_spinloop:
93__secondary_hold_acknowledge: 89__secondary_hold_acknowledge:
94 .llong 0x0 90 .llong 0x0
95 91
96#ifdef CONFIG_PPC_ISERIES
97 /*
98 * At offset 0x20, there is a pointer to iSeries LPAR data.
99 * This is required by the hypervisor
100 */
101 . = 0x20
102 .llong hvReleaseData-KERNELBASE
103#endif /* CONFIG_PPC_ISERIES */
104
105#ifdef CONFIG_RELOCATABLE 92#ifdef CONFIG_RELOCATABLE
106 /* This flag is set to 1 by a loader if the kernel should run 93 /* This flag is set to 1 by a loader if the kernel should run
107 * at the loaded address instead of the linked address. This 94 * at the loaded address instead of the linked address. This
@@ -564,7 +551,8 @@ _GLOBAL(pmac_secondary_start)
564 */ 551 */
565 li r0,0 552 li r0,0
566 stb r0,PACASOFTIRQEN(r13) 553 stb r0,PACASOFTIRQEN(r13)
567 stb r0,PACAHARDIRQEN(r13) 554 li r0,PACA_IRQ_HARD_DIS
555 stb r0,PACAIRQHAPPENED(r13)
568 556
569 /* Create a temp kernel stack for use before relocation is on. */ 557 /* Create a temp kernel stack for use before relocation is on. */
570 ld r1,PACAEMERGSP(r13) 558 ld r1,PACAEMERGSP(r13)
@@ -582,7 +570,7 @@ _GLOBAL(pmac_secondary_start)
582 * 1. Processor number 570 * 1. Processor number
583 * 2. Segment table pointer (virtual address) 571 * 2. Segment table pointer (virtual address)
584 * On entry the following are set: 572 * On entry the following are set:
585 * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries 573 * r1 = stack pointer (real addr of temp stack)
586 * r24 = cpu# (in Linux terms) 574 * r24 = cpu# (in Linux terms)
587 * r13 = paca virtual address 575 * r13 = paca virtual address
588 * SPRG_PACA = paca virtual address 576 * SPRG_PACA = paca virtual address
@@ -595,7 +583,7 @@ __secondary_start:
595 /* Set thread priority to MEDIUM */ 583 /* Set thread priority to MEDIUM */
596 HMT_MEDIUM 584 HMT_MEDIUM
597 585
598 /* Initialize the kernel stack. Just a repeat for iSeries. */ 586 /* Initialize the kernel stack */
599 LOAD_REG_ADDR(r3, current_set) 587 LOAD_REG_ADDR(r3, current_set)
600 sldi r28,r24,3 /* get current_set[cpu#] */ 588 sldi r28,r24,3 /* get current_set[cpu#] */
601 ldx r14,r3,r28 589 ldx r14,r3,r28
@@ -615,20 +603,16 @@ __secondary_start:
615 li r7,0 603 li r7,0
616 mtlr r7 604 mtlr r7
617 605
606 /* Mark interrupts soft and hard disabled (they might be enabled
607 * in the PACA when doing hotplug)
608 */
609 stb r7,PACASOFTIRQEN(r13)
610 li r0,PACA_IRQ_HARD_DIS
611 stb r0,PACAIRQHAPPENED(r13)
612
618 /* enable MMU and jump to start_secondary */ 613 /* enable MMU and jump to start_secondary */
619 LOAD_REG_ADDR(r3, .start_secondary_prolog) 614 LOAD_REG_ADDR(r3, .start_secondary_prolog)
620 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) 615 LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
621#ifdef CONFIG_PPC_ISERIES
622BEGIN_FW_FTR_SECTION
623 ori r4,r4,MSR_EE
624 li r8,1
625 stb r8,PACAHARDIRQEN(r13)
626END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
627#endif
628BEGIN_FW_FTR_SECTION
629 stb r7,PACAHARDIRQEN(r13)
630END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
631 stb r7,PACASOFTIRQEN(r13)
632 616
633 mtspr SPRN_SRR0,r3 617 mtspr SPRN_SRR0,r3
634 mtspr SPRN_SRR1,r4 618 mtspr SPRN_SRR1,r4
@@ -771,22 +755,18 @@ _INIT_GLOBAL(start_here_common)
771 /* Load the TOC (virtual address) */ 755 /* Load the TOC (virtual address) */
772 ld r2,PACATOC(r13) 756 ld r2,PACATOC(r13)
773 757
758 /* Do more system initializations in virtual mode */
774 bl .setup_system 759 bl .setup_system
775 760
776 /* Load up the kernel context */ 761 /* Mark interrupts soft and hard disabled (they might be enabled
7775: 762 * in the PACA when doing hotplug)
778 li r5,0 763 */
779 stb r5,PACASOFTIRQEN(r13) /* Soft Disabled */ 764 li r0,0
780#ifdef CONFIG_PPC_ISERIES 765 stb r0,PACASOFTIRQEN(r13)
781BEGIN_FW_FTR_SECTION 766 li r0,PACA_IRQ_HARD_DIS
782 mfmsr r5 767 stb r0,PACAIRQHAPPENED(r13)
783 ori r5,r5,MSR_EE /* Hard Enabled on iSeries*/
784 mtmsrd r5
785 li r5,1
786END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
787#endif
788 stb r5,PACAHARDIRQEN(r13) /* Hard Disabled on others */
789 768
769 /* Generic kernel entry */
790 bl .start_kernel 770 bl .start_kernel
791 771
792 /* Not reached */ 772 /* Not reached */
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index b68cb173ba2c..b2a5860accfb 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -220,7 +220,7 @@ DataAccess:
220 mfspr r4,SPRN_DAR 220 mfspr r4,SPRN_DAR
221 li r10,0x00f0 221 li r10,0x00f0
222 mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ 222 mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */
223 EXC_XFER_EE_LITE(0x300, handle_page_fault) 223 EXC_XFER_LITE(0x300, handle_page_fault)
224 224
225/* Instruction access exception. 225/* Instruction access exception.
226 * This is "never generated" by the MPC8xx. We jump to it for other 226 * This is "never generated" by the MPC8xx. We jump to it for other
@@ -231,7 +231,7 @@ InstructionAccess:
231 EXCEPTION_PROLOG 231 EXCEPTION_PROLOG
232 mr r4,r12 232 mr r4,r12
233 mr r5,r9 233 mr r5,r9
234 EXC_XFER_EE_LITE(0x400, handle_page_fault) 234 EXC_XFER_LITE(0x400, handle_page_fault)
235 235
236/* External interrupt */ 236/* External interrupt */
237 EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE) 237 EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index fc921bf62e15..0e4175388f47 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -359,7 +359,7 @@ label:
359 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ 359 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
360 stw r5,_ESR(r11); \ 360 stw r5,_ESR(r11); \
361 mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \ 361 mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \
362 EXC_XFER_EE_LITE(0x0300, handle_page_fault) 362 EXC_XFER_LITE(0x0300, handle_page_fault)
363 363
364#define INSTRUCTION_STORAGE_EXCEPTION \ 364#define INSTRUCTION_STORAGE_EXCEPTION \
365 START_EXCEPTION(InstructionStorage) \ 365 START_EXCEPTION(InstructionStorage) \
@@ -368,7 +368,7 @@ label:
368 stw r5,_ESR(r11); \ 368 stw r5,_ESR(r11); \
369 mr r4,r12; /* Pass SRR0 as arg2 */ \ 369 mr r4,r12; /* Pass SRR0 as arg2 */ \
370 li r5,0; /* Pass zero as arg3 */ \ 370 li r5,0; /* Pass zero as arg3 */ \
371 EXC_XFER_EE_LITE(0x0400, handle_page_fault) 371 EXC_XFER_LITE(0x0400, handle_page_fault)
372 372
373#define ALIGNMENT_EXCEPTION \ 373#define ALIGNMENT_EXCEPTION \
374 START_EXCEPTION(Alignment) \ 374 START_EXCEPTION(Alignment) \
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index d5d78c4ceef6..28e62598d0e8 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -319,7 +319,7 @@ interrupt_base:
319 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ 319 mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */
320 andis. r10,r5,(ESR_ILK|ESR_DLK)@h 320 andis. r10,r5,(ESR_ILK|ESR_DLK)@h
321 bne 1f 321 bne 1f
322 EXC_XFER_EE_LITE(0x0300, handle_page_fault) 322 EXC_XFER_LITE(0x0300, handle_page_fault)
3231: 3231:
324 addi r3,r1,STACK_FRAME_OVERHEAD 324 addi r3,r1,STACK_FRAME_OVERHEAD
325 EXC_XFER_EE_LITE(0x0300, CacheLockingException) 325 EXC_XFER_EE_LITE(0x0300, CacheLockingException)
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index c97fc60c790c..e8e821146f38 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -84,7 +84,11 @@ void cpu_idle(void)
84 84
85 start_critical_timings(); 85 start_critical_timings();
86 86
87 local_irq_enable(); 87 /* Some power_save functions return with
88 * interrupts enabled, some don't.
89 */
90 if (irqs_disabled())
91 local_irq_enable();
88 set_thread_flag(TIF_POLLING_NRFLAG); 92 set_thread_flag(TIF_POLLING_NRFLAG);
89 93
90 } else { 94 } else {
diff --git a/arch/powerpc/kernel/idle_book3e.S b/arch/powerpc/kernel/idle_book3e.S
index 16c002d6bdf1..ff007b59448d 100644
--- a/arch/powerpc/kernel/idle_book3e.S
+++ b/arch/powerpc/kernel/idle_book3e.S
@@ -29,43 +29,30 @@ _GLOBAL(book3e_idle)
29 wrteei 0 29 wrteei 0
30 30
31 /* Now check if an interrupt came in while we were soft disabled 31 /* Now check if an interrupt came in while we were soft disabled
32 * since we may otherwise lose it (doorbells etc...). We know 32 * since we may otherwise lose it (doorbells etc...).
33 * that since PACAHARDIRQEN will have been cleared in that case.
34 */ 33 */
35 lbz r3,PACAHARDIRQEN(r13) 34 lbz r3,PACAIRQHAPPENED(r13)
36 cmpwi cr0,r3,0 35 cmpwi cr0,r3,0
37 beqlr 36 bnelr
38 37
39 /* Now we are going to mark ourselves as soft and hard enables in 38 /* Now we are going to mark ourselves as soft and hard enabled in
40 * order to be able to take interrupts while asleep. We inform lockdep 39 * order to be able to take interrupts while asleep. We inform lockdep
41 * of that. We don't actually turn interrupts on just yet tho. 40 * of that. We don't actually turn interrupts on just yet tho.
42 */ 41 */
43#ifdef CONFIG_TRACE_IRQFLAGS 42#ifdef CONFIG_TRACE_IRQFLAGS
44 stdu r1,-128(r1) 43 stdu r1,-128(r1)
45 bl .trace_hardirqs_on 44 bl .trace_hardirqs_on
45 addi r1,r1,128
46#endif 46#endif
47 li r0,1 47 li r0,1
48 stb r0,PACASOFTIRQEN(r13) 48 stb r0,PACASOFTIRQEN(r13)
49 stb r0,PACAHARDIRQEN(r13)
50 49
51 /* Interrupts will make use return to LR, so get something we want 50 /* Interrupts will make use return to LR, so get something we want
52 * in there 51 * in there
53 */ 52 */
54 bl 1f 53 bl 1f
55 54
56 /* Hard disable interrupts again */ 55 /* And return (interrupts are on) */
57 wrteei 0
58
59 /* Mark them off again in the PACA as well */
60 li r0,0
61 stb r0,PACASOFTIRQEN(r13)
62 stb r0,PACAHARDIRQEN(r13)
63
64 /* Tell lockdep about it */
65#ifdef CONFIG_TRACE_IRQFLAGS
66 bl .trace_hardirqs_off
67 addi r1,r1,128
68#endif
69 ld r0,16(r1) 56 ld r0,16(r1)
70 mtlr r0 57 mtlr r0
71 blr 58 blr
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index ba3195478600..2c71b0fc9f91 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -14,6 +14,7 @@
14#include <asm/thread_info.h> 14#include <asm/thread_info.h>
15#include <asm/ppc_asm.h> 15#include <asm/ppc_asm.h>
16#include <asm/asm-offsets.h> 16#include <asm/asm-offsets.h>
17#include <asm/irqflags.h>
17 18
18#undef DEBUG 19#undef DEBUG
19 20
@@ -29,14 +30,31 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
29 cmpwi 0,r4,0 30 cmpwi 0,r4,0
30 beqlr 31 beqlr
31 32
32 /* Go to NAP now */ 33 /* Hard disable interrupts */
33 mfmsr r7 34 mfmsr r7
34 rldicl r0,r7,48,1 35 rldicl r0,r7,48,1
35 rotldi r0,r0,16 36 rotldi r0,r0,16
36 mtmsrd r0,1 /* hard-disable interrupts */ 37 mtmsrd r0,1
38
39 /* Check if something happened while soft-disabled */
40 lbz r0,PACAIRQHAPPENED(r13)
41 cmpwi cr0,r0,0
42 bnelr
43
44 /* Soft-enable interrupts */
45#ifdef CONFIG_TRACE_IRQFLAGS
46 mflr r0
47 std r0,16(r1)
48 stdu r1,-128(r1)
49 bl .trace_hardirqs_on
50 addi r1,r1,128
51 ld r0,16(r1)
52 mtlr r0
53 mfmsr r7
54#endif /* CONFIG_TRACE_IRQFLAGS */
55
37 li r0,1 56 li r0,1
38 stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */ 57 stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
39 stb r0,PACAHARDIRQEN(r13)
40BEGIN_FTR_SECTION 58BEGIN_FTR_SECTION
41 DSSALL 59 DSSALL
42 sync 60 sync
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index fcdff198da4b..0cdc9a392839 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -1,5 +1,5 @@
1/* 1/*
2 * This file contains the power_save function for 970-family CPUs. 2 * This file contains the power_save function for Power7 CPUs.
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 5 * modify it under the terms of the GNU General Public License
@@ -15,6 +15,7 @@
15#include <asm/ppc_asm.h> 15#include <asm/ppc_asm.h>
16#include <asm/asm-offsets.h> 16#include <asm/asm-offsets.h>
17#include <asm/ppc-opcode.h> 17#include <asm/ppc-opcode.h>
18#include <asm/hw_irq.h>
18 19
19#undef DEBUG 20#undef DEBUG
20 21
@@ -51,9 +52,25 @@ _GLOBAL(power7_idle)
51 rldicl r9,r9,48,1 52 rldicl r9,r9,48,1
52 rotldi r9,r9,16 53 rotldi r9,r9,16
53 mtmsrd r9,1 /* hard-disable interrupts */ 54 mtmsrd r9,1 /* hard-disable interrupts */
55
56 /* Check if something happened while soft-disabled */
57 lbz r0,PACAIRQHAPPENED(r13)
58 cmpwi cr0,r0,0
59 beq 1f
60 addi r1,r1,INT_FRAME_SIZE
61 ld r0,16(r1)
62 mtlr r0
63 blr
64
651: /* We mark irqs hard disabled as this is the state we'll
66 * be in when returning and we need to tell arch_local_irq_restore()
67 * about it
68 */
69 li r0,PACA_IRQ_HARD_DIS
70 stb r0,PACAIRQHAPPENED(r13)
71
72 /* We haven't lost state ... yet */
54 li r0,0 73 li r0,0
55 stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
56 stb r0,PACAHARDIRQEN(r13)
57 stb r0,PACA_NAPSTATELOST(r13) 74 stb r0,PACA_NAPSTATELOST(r13)
58 75
59 /* Continue saving state */ 76 /* Continue saving state */
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 0cfcf98aafca..359f078571c7 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -39,6 +39,7 @@
39#include <asm/pci-bridge.h> 39#include <asm/pci-bridge.h>
40#include <asm/machdep.h> 40#include <asm/machdep.h>
41#include <asm/kdump.h> 41#include <asm/kdump.h>
42#include <asm/fadump.h>
42 43
43#define DBG(...) 44#define DBG(...)
44 45
@@ -445,7 +446,12 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
445 446
446static void iommu_table_clear(struct iommu_table *tbl) 447static void iommu_table_clear(struct iommu_table *tbl)
447{ 448{
448 if (!is_kdump_kernel()) { 449 /*
450 * In case of firmware assisted dump system goes through clean
451 * reboot process at the time of system crash. Hence it's safe to
452 * clear the TCE entries if firmware assisted dump is active.
453 */
454 if (!is_kdump_kernel() || is_fadump_active()) {
449 /* Clear the table in case firmware left allocations in it */ 455 /* Clear the table in case firmware left allocations in it */
450 ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); 456 ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
451 return; 457 return;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index bdfb3eee3e6f..a3d128e94cff 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -93,20 +93,16 @@ extern int tau_interrupts(int);
93 93
94#ifdef CONFIG_PPC64 94#ifdef CONFIG_PPC64
95 95
96#ifndef CONFIG_SPARSE_IRQ
97EXPORT_SYMBOL(irq_desc);
98#endif
99
100int distribute_irqs = 1; 96int distribute_irqs = 1;
101 97
102static inline notrace unsigned long get_hard_enabled(void) 98static inline notrace unsigned long get_irq_happened(void)
103{ 99{
104 unsigned long enabled; 100 unsigned long happened;
105 101
106 __asm__ __volatile__("lbz %0,%1(13)" 102 __asm__ __volatile__("lbz %0,%1(13)"
107 : "=r" (enabled) : "i" (offsetof(struct paca_struct, hard_enabled))); 103 : "=r" (happened) : "i" (offsetof(struct paca_struct, irq_happened)));
108 104
109 return enabled; 105 return happened;
110} 106}
111 107
112static inline notrace void set_soft_enabled(unsigned long enable) 108static inline notrace void set_soft_enabled(unsigned long enable)
@@ -115,88 +111,162 @@ static inline notrace void set_soft_enabled(unsigned long enable)
115 : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled))); 111 : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled)));
116} 112}
117 113
118static inline notrace void decrementer_check_overflow(void) 114static inline notrace int decrementer_check_overflow(void)
119{ 115{
120 u64 now = get_tb_or_rtc(); 116 u64 now = get_tb_or_rtc();
121 u64 *next_tb; 117 u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
122 118
123 preempt_disable();
124 next_tb = &__get_cpu_var(decrementers_next_tb);
125
126 if (now >= *next_tb) 119 if (now >= *next_tb)
127 set_dec(1); 120 set_dec(1);
128 preempt_enable(); 121 return now >= *next_tb;
129} 122}
130 123
131notrace void arch_local_irq_restore(unsigned long en) 124/* This is called whenever we are re-enabling interrupts
125 * and returns either 0 (nothing to do) or 500/900 if there's
126 * either an EE or a DEC to generate.
127 *
128 * This is called in two contexts: From arch_local_irq_restore()
129 * before soft-enabling interrupts, and from the exception exit
130 * path when returning from an interrupt from a soft-disabled to
131 * a soft enabled context. In both case we have interrupts hard
132 * disabled.
133 *
134 * We take care of only clearing the bits we handled in the
135 * PACA irq_happened field since we can only re-emit one at a
136 * time and we don't want to "lose" one.
137 */
138notrace unsigned int __check_irq_replay(void)
132{ 139{
133 /* 140 /*
134 * get_paca()->soft_enabled = en; 141 * We use local_paca rather than get_paca() to avoid all
135 * Is it ever valid to use local_irq_restore(0) when soft_enabled is 1? 142 * the debug_smp_processor_id() business in this low level
136 * That was allowed before, and in such a case we do need to take care 143 * function
137 * that gcc will set soft_enabled directly via r13, not choose to use
138 * an intermediate register, lest we're preempted to a different cpu.
139 */ 144 */
140 set_soft_enabled(en); 145 unsigned char happened = local_paca->irq_happened;
141 if (!en)
142 return;
143 146
144#ifdef CONFIG_PPC_STD_MMU_64 147 /* Clear bit 0 which we wouldn't clear otherwise */
145 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 148 local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
146 /* 149
147 * Do we need to disable preemption here? Not really: in the 150 /*
148 * unlikely event that we're preempted to a different cpu in 151 * Force the delivery of pending soft-disabled interrupts on PS3.
149 * between getting r13, loading its lppaca_ptr, and loading 152 * Any HV call will have this side effect.
150 * its any_int, we might call iseries_handle_interrupts without 153 */
151 * an interrupt pending on the new cpu, but that's no disaster, 154 if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
152 * is it? And the business of preempting us off the old cpu 155 u64 tmp, tmp2;
153 * would itself involve a local_irq_restore which handles the 156 lv1_get_version_info(&tmp, &tmp2);
154 * interrupt to that cpu.
155 *
156 * But use "local_paca->lppaca_ptr" instead of "get_lppaca()"
157 * to avoid any preemption checking added into get_paca().
158 */
159 if (local_paca->lppaca_ptr->int_dword.any_int)
160 iseries_handle_interrupts();
161 } 157 }
162#endif /* CONFIG_PPC_STD_MMU_64 */
163 158
164 /* 159 /*
165 * if (get_paca()->hard_enabled) return; 160 * We may have missed a decrementer interrupt. We check the
166 * But again we need to take care that gcc gets hard_enabled directly 161 * decrementer itself rather than the paca irq_happened field
167 * via r13, not choose to use an intermediate register, lest we're 162 * in case we also had a rollover while hard disabled
168 * preempted to a different cpu in between the two instructions. 163 */
164 local_paca->irq_happened &= ~PACA_IRQ_DEC;
165 if (decrementer_check_overflow())
166 return 0x900;
167
168 /* Finally check if an external interrupt happened */
169 local_paca->irq_happened &= ~PACA_IRQ_EE;
170 if (happened & PACA_IRQ_EE)
171 return 0x500;
172
173#ifdef CONFIG_PPC_BOOK3E
174 /* Finally check if an EPR external interrupt happened
175 * this bit is typically set if we need to handle another
176 * "edge" interrupt from within the MPIC "EPR" handler
169 */ 177 */
170 if (get_hard_enabled()) 178 local_paca->irq_happened &= ~PACA_IRQ_EE_EDGE;
179 if (happened & PACA_IRQ_EE_EDGE)
180 return 0x500;
181
182 local_paca->irq_happened &= ~PACA_IRQ_DBELL;
183 if (happened & PACA_IRQ_DBELL)
184 return 0x280;
185#endif /* CONFIG_PPC_BOOK3E */
186
187 /* There should be nothing left ! */
188 BUG_ON(local_paca->irq_happened != 0);
189
190 return 0;
191}
192
193notrace void arch_local_irq_restore(unsigned long en)
194{
195 unsigned char irq_happened;
196 unsigned int replay;
197
198 /* Write the new soft-enabled value */
199 set_soft_enabled(en);
200 if (!en)
201 return;
202 /*
203 * From this point onward, we can take interrupts, preempt,
204 * etc... unless we got hard-disabled. We check if an event
205 * happened. If none happened, we know we can just return.
206 *
207 * We may have preempted before the check below, in which case
208 * we are checking the "new" CPU instead of the old one. This
209 * is only a problem if an event happened on the "old" CPU.
210 *
211 * External interrupt events on non-iseries will have caused
212 * interrupts to be hard-disabled, so there is no problem, we
213 * cannot have preempted.
214 */
215 irq_happened = get_irq_happened();
216 if (!irq_happened)
171 return; 217 return;
172 218
173 /* 219 /*
174 * Need to hard-enable interrupts here. Since currently disabled, 220 * We need to hard disable to get a trusted value from
175 * no need to take further asm precautions against preemption; but 221 * __check_irq_replay(). We also need to soft-disable
176 * use local_paca instead of get_paca() to avoid preemption checking. 222 * again to avoid warnings in there due to the use of
223 * per-cpu variables.
224 *
225 * We know that if the value in irq_happened is exactly 0x01
226 * then we are already hard disabled (there are other less
227 * common cases that we'll ignore for now), so we skip the
228 * (expensive) mtmsrd.
177 */ 229 */
178 local_paca->hard_enabled = en; 230 if (unlikely(irq_happened != PACA_IRQ_HARD_DIS))
231 __hard_irq_disable();
232 set_soft_enabled(0);
179 233
180 /* 234 /*
181 * Trigger the decrementer if we have a pending event. Some processors 235 * Check if anything needs to be re-emitted. We haven't
182 * only trigger on edge transitions of the sign bit. We might also 236 * soft-enabled yet to avoid warnings in decrementer_check_overflow
183 * have disabled interrupts long enough that the decrementer wrapped 237 * accessing per-cpu variables
184 * to positive.
185 */ 238 */
186 decrementer_check_overflow(); 239 replay = __check_irq_replay();
240
241 /* We can soft-enable now */
242 set_soft_enabled(1);
187 243
188 /* 244 /*
189 * Force the delivery of pending soft-disabled interrupts on PS3. 245 * And replay if we have to. This will return with interrupts
190 * Any HV call will have this side effect. 246 * hard-enabled.
191 */ 247 */
192 if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { 248 if (replay) {
193 u64 tmp, tmp2; 249 __replay_interrupt(replay);
194 lv1_get_version_info(&tmp, &tmp2); 250 return;
195 } 251 }
196 252
253 /* Finally, let's ensure we are hard enabled */
197 __hard_irq_enable(); 254 __hard_irq_enable();
198} 255}
199EXPORT_SYMBOL(arch_local_irq_restore); 256EXPORT_SYMBOL(arch_local_irq_restore);
257
258/*
259 * This is specifically called by assembly code to re-enable interrupts
260 * if they are currently disabled. This is typically called before
261 * schedule() or do_signal() when returning to userspace. We do it
262 * in C to avoid the burden of dealing with lockdep etc...
263 */
264void restore_interrupts(void)
265{
266 if (irqs_disabled())
267 local_irq_enable();
268}
269
200#endif /* CONFIG_PPC64 */ 270#endif /* CONFIG_PPC64 */
201 271
202int arch_show_interrupts(struct seq_file *p, int prec) 272int arch_show_interrupts(struct seq_file *p, int prec)
@@ -364,8 +434,17 @@ void do_IRQ(struct pt_regs *regs)
364 434
365 check_stack_overflow(); 435 check_stack_overflow();
366 436
437 /*
438 * Query the platform PIC for the interrupt & ack it.
439 *
440 * This will typically lower the interrupt line to the CPU
441 */
367 irq = ppc_md.get_irq(); 442 irq = ppc_md.get_irq();
368 443
444 /* We can hard enable interrupts now */
445 may_hard_irq_enable();
446
447 /* And finally process it */
369 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) 448 if (irq != NO_IRQ && irq != NO_IRQ_IGNORE)
370 handle_one_irq(irq); 449 handle_one_irq(irq);
371 else if (irq != NO_IRQ_IGNORE) 450 else if (irq != NO_IRQ_IGNORE)
@@ -374,15 +453,6 @@ void do_IRQ(struct pt_regs *regs)
374 irq_exit(); 453 irq_exit();
375 set_irq_regs(old_regs); 454 set_irq_regs(old_regs);
376 455
377#ifdef CONFIG_PPC_ISERIES
378 if (firmware_has_feature(FW_FEATURE_ISERIES) &&
379 get_lppaca()->int_dword.fields.decr_int) {
380 get_lppaca()->int_dword.fields.decr_int = 0;
381 /* Signal a fake decrementer interrupt */
382 timer_interrupt(regs);
383 }
384#endif
385
386 trace_irq_exit(regs); 456 trace_irq_exit(regs);
387} 457}
388 458
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
index 479752901ec6..d45ec58703ce 100644
--- a/arch/powerpc/kernel/isa-bridge.c
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -29,7 +29,6 @@
29#include <asm/pci-bridge.h> 29#include <asm/pci-bridge.h>
30#include <asm/machdep.h> 30#include <asm/machdep.h>
31#include <asm/ppc-pci.h> 31#include <asm/ppc-pci.h>
32#include <asm/firmware.h>
33 32
34unsigned long isa_io_base; /* NULL if no ISA bus */ 33unsigned long isa_io_base; /* NULL if no ISA bus */
35EXPORT_SYMBOL(isa_io_base); 34EXPORT_SYMBOL(isa_io_base);
@@ -261,8 +260,6 @@ static struct notifier_block isa_bridge_notifier = {
261 */ 260 */
262static int __init isa_bridge_init(void) 261static int __init isa_bridge_init(void)
263{ 262{
264 if (firmware_has_feature(FW_FEATURE_ISERIES))
265 return 0;
266 bus_register_notifier(&pci_bus_type, &isa_bridge_notifier); 263 bus_register_notifier(&pci_bus_type, &isa_bridge_notifier);
267 return 0; 264 return 0;
268} 265}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 578f35f18723..ac12bd80ad95 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -26,7 +26,6 @@
26#include <linux/seq_file.h> 26#include <linux/seq_file.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/iseries/hv_lp_config.h>
30#include <asm/lppaca.h> 29#include <asm/lppaca.h>
31#include <asm/hvcall.h> 30#include <asm/hvcall.h>
32#include <asm/firmware.h> 31#include <asm/firmware.h>
@@ -55,80 +54,14 @@ static unsigned long get_purr(void)
55 int cpu; 54 int cpu;
56 55
57 for_each_possible_cpu(cpu) { 56 for_each_possible_cpu(cpu) {
58 if (firmware_has_feature(FW_FEATURE_ISERIES)) 57 struct cpu_usage *cu;
59 sum_purr += lppaca_of(cpu).emulated_time_base;
60 else {
61 struct cpu_usage *cu;
62 58
63 cu = &per_cpu(cpu_usage_array, cpu); 59 cu = &per_cpu(cpu_usage_array, cpu);
64 sum_purr += cu->current_tb; 60 sum_purr += cu->current_tb;
65 }
66 } 61 }
67 return sum_purr; 62 return sum_purr;
68} 63}
69 64
70#ifdef CONFIG_PPC_ISERIES
71
72/*
73 * Methods used to fetch LPAR data when running on an iSeries platform.
74 */
75static int iseries_lparcfg_data(struct seq_file *m, void *v)
76{
77 unsigned long pool_id;
78 int shared, entitled_capacity, max_entitled_capacity;
79 int processors, max_processors;
80 unsigned long purr = get_purr();
81
82 shared = (int)(local_paca->lppaca_ptr->shared_proc);
83
84 seq_printf(m, "system_active_processors=%d\n",
85 (int)HvLpConfig_getSystemPhysicalProcessors());
86
87 seq_printf(m, "system_potential_processors=%d\n",
88 (int)HvLpConfig_getSystemPhysicalProcessors());
89
90 processors = (int)HvLpConfig_getPhysicalProcessors();
91 seq_printf(m, "partition_active_processors=%d\n", processors);
92
93 max_processors = (int)HvLpConfig_getMaxPhysicalProcessors();
94 seq_printf(m, "partition_potential_processors=%d\n", max_processors);
95
96 if (shared) {
97 entitled_capacity = HvLpConfig_getSharedProcUnits();
98 max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits();
99 } else {
100 entitled_capacity = processors * 100;
101 max_entitled_capacity = max_processors * 100;
102 }
103 seq_printf(m, "partition_entitled_capacity=%d\n", entitled_capacity);
104
105 seq_printf(m, "partition_max_entitled_capacity=%d\n",
106 max_entitled_capacity);
107
108 if (shared) {
109 pool_id = HvLpConfig_getSharedPoolIndex();
110 seq_printf(m, "pool=%d\n", (int)pool_id);
111 seq_printf(m, "pool_capacity=%d\n",
112 (int)(HvLpConfig_getNumProcsInSharedPool(pool_id) *
113 100));
114 seq_printf(m, "purr=%ld\n", purr);
115 }
116
117 seq_printf(m, "shared_processor_mode=%d\n", shared);
118
119 return 0;
120}
121
122#else /* CONFIG_PPC_ISERIES */
123
124static int iseries_lparcfg_data(struct seq_file *m, void *v)
125{
126 return 0;
127}
128
129#endif /* CONFIG_PPC_ISERIES */
130
131#ifdef CONFIG_PPC_PSERIES
132/* 65/*
133 * Methods used to fetch LPAR data when running on a pSeries platform. 66 * Methods used to fetch LPAR data when running on a pSeries platform.
134 */ 67 */
@@ -648,8 +581,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
648 u8 new_weight, *new_weight_ptr = &new_weight; 581 u8 new_weight, *new_weight_ptr = &new_weight;
649 ssize_t retval; 582 ssize_t retval;
650 583
651 if (!firmware_has_feature(FW_FEATURE_SPLPAR) || 584 if (!firmware_has_feature(FW_FEATURE_SPLPAR))
652 firmware_has_feature(FW_FEATURE_ISERIES))
653 return -EINVAL; 585 return -EINVAL;
654 586
655 if (count > kbuf_sz) 587 if (count > kbuf_sz)
@@ -709,21 +641,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
709 return retval; 641 return retval;
710} 642}
711 643
712#else /* CONFIG_PPC_PSERIES */
713
714static int pseries_lparcfg_data(struct seq_file *m, void *v)
715{
716 return 0;
717}
718
719static ssize_t lparcfg_write(struct file *file, const char __user * buf,
720 size_t count, loff_t * off)
721{
722 return -EINVAL;
723}
724
725#endif /* CONFIG_PPC_PSERIES */
726
727static int lparcfg_data(struct seq_file *m, void *v) 644static int lparcfg_data(struct seq_file *m, void *v)
728{ 645{
729 struct device_node *rootdn; 646 struct device_node *rootdn;
@@ -738,19 +655,11 @@ static int lparcfg_data(struct seq_file *m, void *v)
738 rootdn = of_find_node_by_path("/"); 655 rootdn = of_find_node_by_path("/");
739 if (rootdn) { 656 if (rootdn) {
740 tmp = of_get_property(rootdn, "model", NULL); 657 tmp = of_get_property(rootdn, "model", NULL);
741 if (tmp) { 658 if (tmp)
742 model = tmp; 659 model = tmp;
743 /* Skip "IBM," - see platforms/iseries/dt.c */
744 if (firmware_has_feature(FW_FEATURE_ISERIES))
745 model += 4;
746 }
747 tmp = of_get_property(rootdn, "system-id", NULL); 660 tmp = of_get_property(rootdn, "system-id", NULL);
748 if (tmp) { 661 if (tmp)
749 system_id = tmp; 662 system_id = tmp;
750 /* Skip "IBM," - see platforms/iseries/dt.c */
751 if (firmware_has_feature(FW_FEATURE_ISERIES))
752 system_id += 4;
753 }
754 lp_index_ptr = of_get_property(rootdn, "ibm,partition-no", 663 lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
755 NULL); 664 NULL);
756 if (lp_index_ptr) 665 if (lp_index_ptr)
@@ -761,8 +670,6 @@ static int lparcfg_data(struct seq_file *m, void *v)
761 seq_printf(m, "system_type=%s\n", model); 670 seq_printf(m, "system_type=%s\n", model);
762 seq_printf(m, "partition_id=%d\n", (int)lp_index); 671 seq_printf(m, "partition_id=%d\n", (int)lp_index);
763 672
764 if (firmware_has_feature(FW_FEATURE_ISERIES))
765 return iseries_lparcfg_data(m, v);
766 return pseries_lparcfg_data(m, v); 673 return pseries_lparcfg_data(m, v);
767} 674}
768 675
@@ -786,8 +693,7 @@ static int __init lparcfg_init(void)
786 umode_t mode = S_IRUSR | S_IRGRP | S_IROTH; 693 umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
787 694
788 /* Allow writing if we have FW_FEATURE_SPLPAR */ 695 /* Allow writing if we have FW_FEATURE_SPLPAR */
789 if (firmware_has_feature(FW_FEATURE_SPLPAR) && 696 if (firmware_has_feature(FW_FEATURE_SPLPAR))
790 !firmware_has_feature(FW_FEATURE_ISERIES))
791 mode |= S_IWUSR; 697 mode |= S_IWUSR;
792 698
793 ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops); 699 ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops);
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index b69463ec2010..ba16874fe294 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -5,7 +5,6 @@
5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) 5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras. 6 * and Paul Mackerras.
7 * 7 *
8 * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
9 * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) 8 * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
10 * 9 *
11 * setjmp/longjmp code by Paul Mackerras. 10 * setjmp/longjmp code by Paul Mackerras.
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index e1612dfb4a93..2049f2d00ffe 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -21,12 +21,13 @@
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_device.h> 22#include <linux/of_device.h>
23#include <linux/of_platform.h> 23#include <linux/of_platform.h>
24#include <linux/atomic.h>
24 25
25#include <asm/errno.h> 26#include <asm/errno.h>
26#include <asm/topology.h> 27#include <asm/topology.h>
27#include <asm/pci-bridge.h> 28#include <asm/pci-bridge.h>
28#include <asm/ppc-pci.h> 29#include <asm/ppc-pci.h>
29#include <linux/atomic.h> 30#include <asm/eeh.h>
30 31
31#ifdef CONFIG_PPC_OF_PLATFORM_PCI 32#ifdef CONFIG_PPC_OF_PLATFORM_PCI
32 33
@@ -66,6 +67,9 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev)
66 /* Init pci_dn data structures */ 67 /* Init pci_dn data structures */
67 pci_devs_phb_init_dynamic(phb); 68 pci_devs_phb_init_dynamic(phb);
68 69
70 /* Create EEH devices for the PHB */
71 eeh_dev_phb_init_dynamic(phb);
72
69 /* Register devices with EEH */ 73 /* Register devices with EEH */
70#ifdef CONFIG_EEH 74#ifdef CONFIG_EEH
71 if (dev->dev.of_node->child) 75 if (dev->dev.of_node->child)
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 41456ff55e14..0bb1f98613ba 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -11,13 +11,10 @@
11#include <linux/export.h> 11#include <linux/export.h>
12#include <linux/memblock.h> 12#include <linux/memblock.h>
13 13
14#include <asm/firmware.h>
15#include <asm/lppaca.h> 14#include <asm/lppaca.h>
16#include <asm/paca.h> 15#include <asm/paca.h>
17#include <asm/sections.h> 16#include <asm/sections.h>
18#include <asm/pgtable.h> 17#include <asm/pgtable.h>
19#include <asm/iseries/lpar_map.h>
20#include <asm/iseries/hv_types.h>
21#include <asm/kexec.h> 18#include <asm/kexec.h>
22 19
23/* This symbol is provided by the linker - let it fill in the paca 20/* This symbol is provided by the linker - let it fill in the paca
@@ -30,8 +27,8 @@ extern unsigned long __toc_start;
30 * The structure which the hypervisor knows about - this structure 27 * The structure which the hypervisor knows about - this structure
31 * should not cross a page boundary. The vpa_init/register_vpa call 28 * should not cross a page boundary. The vpa_init/register_vpa call
32 * is now known to fail if the lppaca structure crosses a page 29 * is now known to fail if the lppaca structure crosses a page
33 * boundary. The lppaca is also used on legacy iSeries and POWER5 30 * boundary. The lppaca is also used on POWER5 pSeries boxes.
34 * pSeries boxes. The lppaca is 640 bytes long, and cannot readily 31 * The lppaca is 640 bytes long, and cannot readily
35 * change since the hypervisor knows its layout, so a 1kB alignment 32 * change since the hypervisor knows its layout, so a 1kB alignment
36 * will suffice to ensure that it doesn't cross a page boundary. 33 * will suffice to ensure that it doesn't cross a page boundary.
37 */ 34 */
@@ -183,12 +180,9 @@ void __init allocate_pacas(void)
183 /* 180 /*
184 * We can't take SLB misses on the paca, and we want to access them 181 * We can't take SLB misses on the paca, and we want to access them
185 * in real mode, so allocate them within the RMA and also within 182 * in real mode, so allocate them within the RMA and also within
186 * the first segment. On iSeries they must be within the area mapped 183 * the first segment.
187 * by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
188 */ 184 */
189 limit = min(0x10000000ULL, ppc64_rma_size); 185 limit = min(0x10000000ULL, ppc64_rma_size);
190 if (firmware_has_feature(FW_FEATURE_ISERIES))
191 limit = min(limit, HvPagesToMap * HVPAGESIZE);
192 186
193 paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids); 187 paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
194 188
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index cce98d76e905..d0373bcb7c9d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -38,7 +38,6 @@
38#include <asm/byteorder.h> 38#include <asm/byteorder.h>
39#include <asm/machdep.h> 39#include <asm/machdep.h>
40#include <asm/ppc-pci.h> 40#include <asm/ppc-pci.h>
41#include <asm/firmware.h>
42#include <asm/eeh.h> 41#include <asm/eeh.h>
43 42
44static DEFINE_SPINLOCK(hose_spinlock); 43static DEFINE_SPINLOCK(hose_spinlock);
@@ -219,20 +218,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
219 struct of_irq oirq; 218 struct of_irq oirq;
220 unsigned int virq; 219 unsigned int virq;
221 220
222 /* The current device-tree that iSeries generates from the HV
223 * PCI informations doesn't contain proper interrupt routing,
224 * and all the fallback would do is print out crap, so we
225 * don't attempt to resolve the interrupts here at all, some
226 * iSeries specific fixup does it.
227 *
228 * In the long run, we will hopefully fix the generated device-tree
229 * instead.
230 */
231#ifdef CONFIG_PPC_ISERIES
232 if (firmware_has_feature(FW_FEATURE_ISERIES))
233 return -1;
234#endif
235
236 pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev)); 221 pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
237 222
238#ifdef DEBUG 223#ifdef DEBUG
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index d817ab018486..e40707032ac3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -647,6 +647,9 @@ void show_regs(struct pt_regs * regs)
647 printk("MSR: "REG" ", regs->msr); 647 printk("MSR: "REG" ", regs->msr);
648 printbits(regs->msr, msr_bits); 648 printbits(regs->msr, msr_bits);
649 printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); 649 printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
650#ifdef CONFIG_PPC64
651 printk("SOFTE: %ld\n", regs->softe);
652#endif
650 trap = TRAP(regs); 653 trap = TRAP(regs);
651 if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR)) 654 if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
652 printk("CFAR: "REG"\n", regs->orig_gpr3); 655 printk("CFAR: "REG"\n", regs->orig_gpr3);
@@ -1220,34 +1223,32 @@ void dump_stack(void)
1220EXPORT_SYMBOL(dump_stack); 1223EXPORT_SYMBOL(dump_stack);
1221 1224
1222#ifdef CONFIG_PPC64 1225#ifdef CONFIG_PPC64
1223void ppc64_runlatch_on(void) 1226/* Called with hard IRQs off */
1227void __ppc64_runlatch_on(void)
1224{ 1228{
1229 struct thread_info *ti = current_thread_info();
1225 unsigned long ctrl; 1230 unsigned long ctrl;
1226 1231
1227 if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) { 1232 ctrl = mfspr(SPRN_CTRLF);
1228 HMT_medium(); 1233 ctrl |= CTRL_RUNLATCH;
1229 1234 mtspr(SPRN_CTRLT, ctrl);
1230 ctrl = mfspr(SPRN_CTRLF);
1231 ctrl |= CTRL_RUNLATCH;
1232 mtspr(SPRN_CTRLT, ctrl);
1233 1235
1234 set_thread_flag(TIF_RUNLATCH); 1236 ti->local_flags |= TLF_RUNLATCH;
1235 }
1236} 1237}
1237 1238
1239/* Called with hard IRQs off */
1238void __ppc64_runlatch_off(void) 1240void __ppc64_runlatch_off(void)
1239{ 1241{
1242 struct thread_info *ti = current_thread_info();
1240 unsigned long ctrl; 1243 unsigned long ctrl;
1241 1244
1242 HMT_medium(); 1245 ti->local_flags &= ~TLF_RUNLATCH;
1243
1244 clear_thread_flag(TIF_RUNLATCH);
1245 1246
1246 ctrl = mfspr(SPRN_CTRLF); 1247 ctrl = mfspr(SPRN_CTRLF);
1247 ctrl &= ~CTRL_RUNLATCH; 1248 ctrl &= ~CTRL_RUNLATCH;
1248 mtspr(SPRN_CTRLT, ctrl); 1249 mtspr(SPRN_CTRLT, ctrl);
1249} 1250}
1250#endif 1251#endif /* CONFIG_PPC64 */
1251 1252
1252#if THREAD_SHIFT < PAGE_SHIFT 1253#if THREAD_SHIFT < PAGE_SHIFT
1253 1254
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index abe405dab34d..89e850af3dd6 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -52,9 +52,9 @@
52#include <asm/machdep.h> 52#include <asm/machdep.h>
53#include <asm/pSeries_reconfig.h> 53#include <asm/pSeries_reconfig.h>
54#include <asm/pci-bridge.h> 54#include <asm/pci-bridge.h>
55#include <asm/phyp_dump.h>
56#include <asm/kexec.h> 55#include <asm/kexec.h>
57#include <asm/opal.h> 56#include <asm/opal.h>
57#include <asm/fadump.h>
58 58
59#include <mm/mmu_decl.h> 59#include <mm/mmu_decl.h>
60 60
@@ -615,86 +615,6 @@ static void __init early_reserve_mem(void)
615 } 615 }
616} 616}
617 617
618#ifdef CONFIG_PHYP_DUMP
619/**
620 * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
621 *
622 * Function to find the largest size we need to reserve
623 * during early boot process.
624 *
625 * It either looks for boot param and returns that OR
626 * returns larger of 256 or 5% rounded down to multiples of 256MB.
627 *
628 */
629static inline unsigned long phyp_dump_calculate_reserve_size(void)
630{
631 unsigned long tmp;
632
633 if (phyp_dump_info->reserve_bootvar)
634 return phyp_dump_info->reserve_bootvar;
635
636 /* divide by 20 to get 5% of value */
637 tmp = memblock_end_of_DRAM();
638 do_div(tmp, 20);
639
640 /* round it down in multiples of 256 */
641 tmp = tmp & ~0x0FFFFFFFUL;
642
643 return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
644}
645
646/**
647 * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
648 *
649 * This routine may reserve memory regions in the kernel only
650 * if the system is supported and a dump was taken in last
651 * boot instance or if the hardware is supported and the
652 * scratch area needs to be setup. In other instances it returns
653 * without reserving anything. The memory in case of dump being
654 * active is freed when the dump is collected (by userland tools).
655 */
656static void __init phyp_dump_reserve_mem(void)
657{
658 unsigned long base, size;
659 unsigned long variable_reserve_size;
660
661 if (!phyp_dump_info->phyp_dump_configured) {
662 printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
663 return;
664 }
665
666 if (!phyp_dump_info->phyp_dump_at_boot) {
667 printk(KERN_INFO "Phyp-dump disabled at boot time\n");
668 return;
669 }
670
671 variable_reserve_size = phyp_dump_calculate_reserve_size();
672
673 if (phyp_dump_info->phyp_dump_is_active) {
674 /* Reserve *everything* above RMR.Area freed by userland tools*/
675 base = variable_reserve_size;
676 size = memblock_end_of_DRAM() - base;
677
678 /* XXX crashed_ram_end is wrong, since it may be beyond
679 * the memory_limit, it will need to be adjusted. */
680 memblock_reserve(base, size);
681
682 phyp_dump_info->init_reserve_start = base;
683 phyp_dump_info->init_reserve_size = size;
684 } else {
685 size = phyp_dump_info->cpu_state_size +
686 phyp_dump_info->hpte_region_size +
687 variable_reserve_size;
688 base = memblock_end_of_DRAM() - size;
689 memblock_reserve(base, size);
690 phyp_dump_info->init_reserve_start = base;
691 phyp_dump_info->init_reserve_size = size;
692 }
693}
694#else
695static inline void __init phyp_dump_reserve_mem(void) {}
696#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
697
698void __init early_init_devtree(void *params) 618void __init early_init_devtree(void *params)
699{ 619{
700 phys_addr_t limit; 620 phys_addr_t limit;
@@ -714,9 +634,9 @@ void __init early_init_devtree(void *params)
714 of_scan_flat_dt(early_init_dt_scan_opal, NULL); 634 of_scan_flat_dt(early_init_dt_scan_opal, NULL);
715#endif 635#endif
716 636
717#ifdef CONFIG_PHYP_DUMP 637#ifdef CONFIG_FA_DUMP
718 /* scan tree to see if dump occurred during last boot */ 638 /* scan tree to see if dump is active during last boot */
719 of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); 639 of_scan_flat_dt(early_init_dt_scan_fw_dump, NULL);
720#endif 640#endif
721 641
722 /* Pre-initialize the cmd_line with the content of boot_commmand_line, 642 /* Pre-initialize the cmd_line with the content of boot_commmand_line,
@@ -750,9 +670,15 @@ void __init early_init_devtree(void *params)
750 if (PHYSICAL_START > MEMORY_START) 670 if (PHYSICAL_START > MEMORY_START)
751 memblock_reserve(MEMORY_START, 0x8000); 671 memblock_reserve(MEMORY_START, 0x8000);
752 reserve_kdump_trampoline(); 672 reserve_kdump_trampoline();
753 reserve_crashkernel(); 673#ifdef CONFIG_FA_DUMP
674 /*
675 * If we fail to reserve memory for firmware-assisted dump then
676 * fallback to kexec based kdump.
677 */
678 if (fadump_reserve_mem() == 0)
679#endif
680 reserve_crashkernel();
754 early_reserve_mem(); 681 early_reserve_mem();
755 phyp_dump_reserve_mem();
756 682
757 /* 683 /*
758 * Ensure that total memory size is page-aligned, because otherwise 684 * Ensure that total memory size is page-aligned, because otherwise
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index eca626ea3f23..e2d599048142 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -48,14 +48,6 @@
48#include <linux/linux_logo.h> 48#include <linux/linux_logo.h>
49 49
50/* 50/*
51 * Properties whose value is longer than this get excluded from our
52 * copy of the device tree. This value does need to be big enough to
53 * ensure that we don't lose things like the interrupt-map property
54 * on a PCI-PCI bridge.
55 */
56#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
57
58/*
59 * Eventually bump that one up 51 * Eventually bump that one up
60 */ 52 */
61#define DEVTREE_CHUNK_SIZE 0x100000 53#define DEVTREE_CHUNK_SIZE 0x100000
@@ -2273,13 +2265,6 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2273 /* sanity checks */ 2265 /* sanity checks */
2274 if (l == PROM_ERROR) 2266 if (l == PROM_ERROR)
2275 continue; 2267 continue;
2276 if (l > MAX_PROPERTY_LENGTH) {
2277 prom_printf("WARNING: ignoring large property ");
2278 /* It seems OF doesn't null-terminate the path :-( */
2279 prom_printf("[%s] ", path);
2280 prom_printf("%s length 0x%x\n", RELOC(pname), l);
2281 continue;
2282 }
2283 2268
2284 /* push property head */ 2269 /* push property head */
2285 dt_push_token(OF_DT_PROP, mem_start, mem_end); 2270 dt_push_token(OF_DT_PROP, mem_start, mem_end);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 6cd8f0196b6d..517bd86bc3f0 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -275,6 +275,9 @@ void __init find_and_init_phbs(void)
275 of_node_put(root); 275 of_node_put(root);
276 pci_devs_phb_init(); 276 pci_devs_phb_init();
277 277
278 /* Create EEH devices for all PHBs */
279 eeh_dev_phb_init();
280
278 /* 281 /*
279 * pci_probe_only and pci_assign_all_buses can be set via properties 282 * pci_probe_only and pci_assign_all_buses can be set via properties
280 * in chosen. 283 * in chosen.
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 77bb77da05c1..b0ebdeab9494 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -61,6 +61,7 @@
61#include <asm/xmon.h> 61#include <asm/xmon.h>
62#include <asm/cputhreads.h> 62#include <asm/cputhreads.h>
63#include <mm/mmu_decl.h> 63#include <mm/mmu_decl.h>
64#include <asm/fadump.h>
64 65
65#include "setup.h" 66#include "setup.h"
66 67
@@ -109,6 +110,14 @@ EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
109/* also used by kexec */ 110/* also used by kexec */
110void machine_shutdown(void) 111void machine_shutdown(void)
111{ 112{
113#ifdef CONFIG_FA_DUMP
114 /*
115 * if fadump is active, cleanup the fadump registration before we
116 * shutdown.
117 */
118 fadump_cleanup();
119#endif
120
112 if (ppc_md.machine_shutdown) 121 if (ppc_md.machine_shutdown)
113 ppc_md.machine_shutdown(); 122 ppc_md.machine_shutdown();
114} 123}
@@ -639,6 +648,11 @@ EXPORT_SYMBOL(check_legacy_ioport);
639static int ppc_panic_event(struct notifier_block *this, 648static int ppc_panic_event(struct notifier_block *this,
640 unsigned long event, void *ptr) 649 unsigned long event, void *ptr)
641{ 650{
651 /*
652 * If firmware-assisted dump has been registered then trigger
653 * firmware-assisted dump and let firmware handle everything else.
654 */
655 crash_fadump(NULL, ptr);
642 ppc_md.panic(ptr); /* May not return */ 656 ppc_md.panic(ptr); /* May not return */
643 return NOTIFY_DONE; 657 return NOTIFY_DONE;
644} 658}
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index ac6e437b1021..7006b7f4267a 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -57,10 +57,7 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
57void restore_sigmask(sigset_t *set) 57void restore_sigmask(sigset_t *set)
58{ 58{
59 sigdelsetmask(set, ~_BLOCKABLE); 59 sigdelsetmask(set, ~_BLOCKABLE);
60 spin_lock_irq(&current->sighand->siglock); 60 set_current_blocked(set);
61 current->blocked = *set;
62 recalc_sigpending();
63 spin_unlock_irq(&current->sighand->siglock);
64} 61}
65 62
66static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, 63static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
@@ -169,13 +166,7 @@ static int do_signal(struct pt_regs *regs)
169 166
170 regs->trap = 0; 167 regs->trap = 0;
171 if (ret) { 168 if (ret) {
172 spin_lock_irq(&current->sighand->siglock); 169 block_sigmask(&ka, signr);
173 sigorsets(&current->blocked, &current->blocked,
174 &ka.sa.sa_mask);
175 if (!(ka.sa.sa_flags & SA_NODEFER))
176 sigaddset(&current->blocked, signr);
177 recalc_sigpending();
178 spin_unlock_irq(&current->sighand->siglock);
179 170
180 /* 171 /*
181 * A signal was successfully delivered; the saved sigmask is in 172 * A signal was successfully delivered; the saved sigmask is in
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 836a5a19eb2c..e061ef5dd449 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -242,12 +242,13 @@ static inline int restore_general_regs(struct pt_regs *regs,
242 */ 242 */
243long sys_sigsuspend(old_sigset_t mask) 243long sys_sigsuspend(old_sigset_t mask)
244{ 244{
245 mask &= _BLOCKABLE; 245 sigset_t blocked;
246 spin_lock_irq(&current->sighand->siglock); 246
247 current->saved_sigmask = current->blocked; 247 current->saved_sigmask = current->blocked;
248 siginitset(&current->blocked, mask); 248
249 recalc_sigpending(); 249 mask &= _BLOCKABLE;
250 spin_unlock_irq(&current->sighand->siglock); 250 siginitset(&blocked, mask);
251 set_current_blocked(&blocked);
251 252
252 current->state = TASK_INTERRUPTIBLE; 253 current->state = TASK_INTERRUPTIBLE;
253 schedule(); 254 schedule();
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 883e74c0d1b3..0c683d376b1c 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -12,7 +12,6 @@
12#include <asm/current.h> 12#include <asm/current.h>
13#include <asm/processor.h> 13#include <asm/processor.h>
14#include <asm/cputable.h> 14#include <asm/cputable.h>
15#include <asm/firmware.h>
16#include <asm/hvcall.h> 15#include <asm/hvcall.h>
17#include <asm/prom.h> 16#include <asm/prom.h>
18#include <asm/machdep.h> 17#include <asm/machdep.h>
@@ -341,8 +340,7 @@ static void __cpuinit register_cpu_online(unsigned int cpu)
341 int i, nattrs; 340 int i, nattrs;
342 341
343#ifdef CONFIG_PPC64 342#ifdef CONFIG_PPC64
344 if (!firmware_has_feature(FW_FEATURE_ISERIES) && 343 if (cpu_has_feature(CPU_FTR_SMT))
345 cpu_has_feature(CPU_FTR_SMT))
346 device_create_file(s, &dev_attr_smt_snooze_delay); 344 device_create_file(s, &dev_attr_smt_snooze_delay);
347#endif 345#endif
348 346
@@ -414,8 +412,7 @@ static void unregister_cpu_online(unsigned int cpu)
414 BUG_ON(!c->hotpluggable); 412 BUG_ON(!c->hotpluggable);
415 413
416#ifdef CONFIG_PPC64 414#ifdef CONFIG_PPC64
417 if (!firmware_has_feature(FW_FEATURE_ISERIES) && 415 if (cpu_has_feature(CPU_FTR_SMT))
418 cpu_has_feature(CPU_FTR_SMT))
419 device_remove_file(s, &dev_attr_smt_snooze_delay); 416 device_remove_file(s, &dev_attr_smt_snooze_delay);
420#endif 417#endif
421 418
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 567dd7c3ac2a..2c42cd72d0f5 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -17,8 +17,7 @@
17 * 17 *
18 * TODO (not necessarily in this file): 18 * TODO (not necessarily in this file):
19 * - improve precision and reproducibility of timebase frequency 19 * - improve precision and reproducibility of timebase frequency
20 * measurement at boot time. (for iSeries, we calibrate the timebase 20 * measurement at boot time.
21 * against the Titan chip's clock.)
22 * - for astronomical applications: add a new function to get 21 * - for astronomical applications: add a new function to get
23 * non ambiguous timestamps even around leap seconds. This needs 22 * non ambiguous timestamps even around leap seconds. This needs
24 * a new timestamp format and a good name. 23 * a new timestamp format and a good name.
@@ -70,10 +69,6 @@
70#include <asm/vdso_datapage.h> 69#include <asm/vdso_datapage.h>
71#include <asm/firmware.h> 70#include <asm/firmware.h>
72#include <asm/cputime.h> 71#include <asm/cputime.h>
73#ifdef CONFIG_PPC_ISERIES
74#include <asm/iseries/it_lp_queue.h>
75#include <asm/iseries/hv_call_xm.h>
76#endif
77 72
78/* powerpc clocksource/clockevent code */ 73/* powerpc clocksource/clockevent code */
79 74
@@ -117,14 +112,6 @@ static struct clock_event_device decrementer_clockevent = {
117DEFINE_PER_CPU(u64, decrementers_next_tb); 112DEFINE_PER_CPU(u64, decrementers_next_tb);
118static DEFINE_PER_CPU(struct clock_event_device, decrementers); 113static DEFINE_PER_CPU(struct clock_event_device, decrementers);
119 114
120#ifdef CONFIG_PPC_ISERIES
121static unsigned long __initdata iSeries_recal_titan;
122static signed long __initdata iSeries_recal_tb;
123
124/* Forward declaration is only needed for iSereis compiles */
125static void __init clocksource_init(void);
126#endif
127
128#define XSEC_PER_SEC (1024*1024) 115#define XSEC_PER_SEC (1024*1024)
129 116
130#ifdef CONFIG_PPC64 117#ifdef CONFIG_PPC64
@@ -259,7 +246,6 @@ void accumulate_stolen_time(void)
259 u64 sst, ust; 246 u64 sst, ust;
260 247
261 u8 save_soft_enabled = local_paca->soft_enabled; 248 u8 save_soft_enabled = local_paca->soft_enabled;
262 u8 save_hard_enabled = local_paca->hard_enabled;
263 249
264 /* We are called early in the exception entry, before 250 /* We are called early in the exception entry, before
265 * soft/hard_enabled are sync'ed to the expected state 251 * soft/hard_enabled are sync'ed to the expected state
@@ -268,7 +254,6 @@ void accumulate_stolen_time(void)
268 * complain 254 * complain
269 */ 255 */
270 local_paca->soft_enabled = 0; 256 local_paca->soft_enabled = 0;
271 local_paca->hard_enabled = 0;
272 257
273 sst = scan_dispatch_log(local_paca->starttime_user); 258 sst = scan_dispatch_log(local_paca->starttime_user);
274 ust = scan_dispatch_log(local_paca->starttime); 259 ust = scan_dispatch_log(local_paca->starttime);
@@ -277,7 +262,6 @@ void accumulate_stolen_time(void)
277 local_paca->stolen_time += ust + sst; 262 local_paca->stolen_time += ust + sst;
278 263
279 local_paca->soft_enabled = save_soft_enabled; 264 local_paca->soft_enabled = save_soft_enabled;
280 local_paca->hard_enabled = save_hard_enabled;
281} 265}
282 266
283static inline u64 calculate_stolen_time(u64 stop_tb) 267static inline u64 calculate_stolen_time(u64 stop_tb)
@@ -426,74 +410,6 @@ unsigned long profile_pc(struct pt_regs *regs)
426EXPORT_SYMBOL(profile_pc); 410EXPORT_SYMBOL(profile_pc);
427#endif 411#endif
428 412
429#ifdef CONFIG_PPC_ISERIES
430
431/*
432 * This function recalibrates the timebase based on the 49-bit time-of-day
433 * value in the Titan chip. The Titan is much more accurate than the value
434 * returned by the service processor for the timebase frequency.
435 */
436
437static int __init iSeries_tb_recal(void)
438{
439 unsigned long titan, tb;
440
441 /* Make sure we only run on iSeries */
442 if (!firmware_has_feature(FW_FEATURE_ISERIES))
443 return -ENODEV;
444
445 tb = get_tb();
446 titan = HvCallXm_loadTod();
447 if ( iSeries_recal_titan ) {
448 unsigned long tb_ticks = tb - iSeries_recal_tb;
449 unsigned long titan_usec = (titan - iSeries_recal_titan) >> 12;
450 unsigned long new_tb_ticks_per_sec = (tb_ticks * USEC_PER_SEC)/titan_usec;
451 unsigned long new_tb_ticks_per_jiffy =
452 DIV_ROUND_CLOSEST(new_tb_ticks_per_sec, HZ);
453 long tick_diff = new_tb_ticks_per_jiffy - tb_ticks_per_jiffy;
454 char sign = '+';
455 /* make sure tb_ticks_per_sec and tb_ticks_per_jiffy are consistent */
456 new_tb_ticks_per_sec = new_tb_ticks_per_jiffy * HZ;
457
458 if ( tick_diff < 0 ) {
459 tick_diff = -tick_diff;
460 sign = '-';
461 }
462 if ( tick_diff ) {
463 if ( tick_diff < tb_ticks_per_jiffy/25 ) {
464 printk( "Titan recalibrate: new tb_ticks_per_jiffy = %lu (%c%ld)\n",
465 new_tb_ticks_per_jiffy, sign, tick_diff );
466 tb_ticks_per_jiffy = new_tb_ticks_per_jiffy;
467 tb_ticks_per_sec = new_tb_ticks_per_sec;
468 calc_cputime_factors();
469 vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
470 setup_cputime_one_jiffy();
471 }
472 else {
473 printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
474 " new tb_ticks_per_jiffy = %lu\n"
475 " old tb_ticks_per_jiffy = %lu\n",
476 new_tb_ticks_per_jiffy, tb_ticks_per_jiffy );
477 }
478 }
479 }
480 iSeries_recal_titan = titan;
481 iSeries_recal_tb = tb;
482
483 /* Called here as now we know accurate values for the timebase */
484 clocksource_init();
485 return 0;
486}
487late_initcall(iSeries_tb_recal);
488
489/* Called from platform early init */
490void __init iSeries_time_init_early(void)
491{
492 iSeries_recal_tb = get_tb();
493 iSeries_recal_titan = HvCallXm_loadTod();
494}
495#endif /* CONFIG_PPC_ISERIES */
496
497#ifdef CONFIG_IRQ_WORK 413#ifdef CONFIG_IRQ_WORK
498 414
499/* 415/*
@@ -550,16 +466,6 @@ void arch_irq_work_raise(void)
550#endif /* CONFIG_IRQ_WORK */ 466#endif /* CONFIG_IRQ_WORK */
551 467
552/* 468/*
553 * For iSeries shared processors, we have to let the hypervisor
554 * set the hardware decrementer. We set a virtual decrementer
555 * in the lppaca and call the hypervisor if the virtual
556 * decrementer is less than the current value in the hardware
557 * decrementer. (almost always the new decrementer value will
558 * be greater than the current hardware decementer so the hypervisor
559 * call will not be needed)
560 */
561
562/*
563 * timer_interrupt - gets called when the decrementer overflows, 469 * timer_interrupt - gets called when the decrementer overflows,
564 * with interrupts disabled. 470 * with interrupts disabled.
565 */ 471 */
@@ -580,6 +486,11 @@ void timer_interrupt(struct pt_regs * regs)
580 if (!cpu_online(smp_processor_id())) 486 if (!cpu_online(smp_processor_id()))
581 return; 487 return;
582 488
489 /* Conditionally hard-enable interrupts now that the DEC has been
490 * bumped to its maximum value
491 */
492 may_hard_irq_enable();
493
583 trace_timer_interrupt_entry(regs); 494 trace_timer_interrupt_entry(regs);
584 495
585 __get_cpu_var(irq_stat).timer_irqs++; 496 __get_cpu_var(irq_stat).timer_irqs++;
@@ -597,20 +508,10 @@ void timer_interrupt(struct pt_regs * regs)
597 irq_work_run(); 508 irq_work_run();
598 } 509 }
599 510
600#ifdef CONFIG_PPC_ISERIES
601 if (firmware_has_feature(FW_FEATURE_ISERIES))
602 get_lppaca()->int_dword.fields.decr_int = 0;
603#endif
604
605 *next_tb = ~(u64)0; 511 *next_tb = ~(u64)0;
606 if (evt->event_handler) 512 if (evt->event_handler)
607 evt->event_handler(evt); 513 evt->event_handler(evt);
608 514
609#ifdef CONFIG_PPC_ISERIES
610 if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
611 process_hvlpevents();
612#endif
613
614#ifdef CONFIG_PPC64 515#ifdef CONFIG_PPC64
615 /* collect purr register values often, for accurate calculations */ 516 /* collect purr register values often, for accurate calculations */
616 if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 517 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
@@ -982,9 +883,8 @@ void __init time_init(void)
982 */ 883 */
983 start_cpu_decrementer(); 884 start_cpu_decrementer();
984 885
985 /* Register the clocksource, if we're not running on iSeries */ 886 /* Register the clocksource */
986 if (!firmware_has_feature(FW_FEATURE_ISERIES)) 887 clocksource_init();
987 clocksource_init();
988 888
989 init_decrementer_clockevent(); 889 init_decrementer_clockevent();
990} 890}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index c091527efd89..a750409ccc4e 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -57,6 +57,7 @@
57#include <asm/kexec.h> 57#include <asm/kexec.h>
58#include <asm/ppc-opcode.h> 58#include <asm/ppc-opcode.h>
59#include <asm/rio.h> 59#include <asm/rio.h>
60#include <asm/fadump.h>
60 61
61#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) 62#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
62int (*__debugger)(struct pt_regs *regs) __read_mostly; 63int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -145,6 +146,8 @@ static void __kprobes oops_end(unsigned long flags, struct pt_regs *regs,
145 arch_spin_unlock(&die_lock); 146 arch_spin_unlock(&die_lock);
146 raw_local_irq_restore(flags); 147 raw_local_irq_restore(flags);
147 148
149 crash_fadump(regs, "die oops");
150
148 /* 151 /*
149 * A system reset (0x100) is a request to dump, so we always send 152 * A system reset (0x100) is a request to dump, so we always send
150 * it through the crashdump code. 153 * it through the crashdump code.
@@ -244,6 +247,9 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
244 addr, regs->nip, regs->link, code); 247 addr, regs->nip, regs->link, code);
245 } 248 }
246 249
250 if (!arch_irq_disabled_regs(regs))
251 local_irq_enable();
252
247 memset(&info, 0, sizeof(info)); 253 memset(&info, 0, sizeof(info));
248 info.si_signo = signr; 254 info.si_signo = signr;
249 info.si_code = code; 255 info.si_code = code;
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 8b086299ba25..bca3fc427b45 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -34,11 +34,6 @@
34#include <asm/abs_addr.h> 34#include <asm/abs_addr.h>
35#include <asm/page.h> 35#include <asm/page.h>
36#include <asm/hvcall.h> 36#include <asm/hvcall.h>
37#include <asm/iseries/vio.h>
38#include <asm/iseries/hv_types.h>
39#include <asm/iseries/hv_lp_config.h>
40#include <asm/iseries/hv_call_xm.h>
41#include <asm/iseries/iommu.h>
42 37
43static struct bus_type vio_bus_type; 38static struct bus_type vio_bus_type;
44 39
@@ -1042,7 +1037,6 @@ static void vio_cmo_sysfs_init(void)
1042 vio_bus_type.bus_attrs = vio_cmo_bus_attrs; 1037 vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
1043} 1038}
1044#else /* CONFIG_PPC_SMLPAR */ 1039#else /* CONFIG_PPC_SMLPAR */
1045/* Dummy functions for iSeries platform */
1046int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; } 1040int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
1047void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {} 1041void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
1048static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; } 1042static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
@@ -1060,9 +1054,6 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
1060 struct iommu_table *tbl; 1054 struct iommu_table *tbl;
1061 unsigned long offset, size; 1055 unsigned long offset, size;
1062 1056
1063 if (firmware_has_feature(FW_FEATURE_ISERIES))
1064 return vio_build_iommu_table_iseries(dev);
1065
1066 dma_window = of_get_property(dev->dev.of_node, 1057 dma_window = of_get_property(dev->dev.of_node,
1067 "ibm,my-dma-window", NULL); 1058 "ibm,my-dma-window", NULL);
1068 if (!dma_window) 1059 if (!dma_window)
@@ -1195,8 +1186,7 @@ static void __devinit vio_dev_release(struct device *dev)
1195{ 1186{
1196 struct iommu_table *tbl = get_iommu_table_base(dev); 1187 struct iommu_table *tbl = get_iommu_table_base(dev);
1197 1188
1198 /* iSeries uses a common table for all vio devices */ 1189 if (tbl)
1199 if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl)
1200 iommu_free_table(tbl, dev->of_node ? 1190 iommu_free_table(tbl, dev->of_node ?
1201 dev->of_node->full_name : dev_name(dev)); 1191 dev->of_node->full_name : dev_name(dev));
1202 of_node_put(dev->of_node); 1192 of_node_put(dev->of_node);
@@ -1244,12 +1234,6 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
1244 viodev->name = of_node->name; 1234 viodev->name = of_node->name;
1245 viodev->type = of_node->type; 1235 viodev->type = of_node->type;
1246 viodev->unit_address = *unit_address; 1236 viodev->unit_address = *unit_address;
1247 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1248 unit_address = of_get_property(of_node,
1249 "linux,unit_address", NULL);
1250 if (unit_address != NULL)
1251 viodev->unit_address = *unit_address;
1252 }
1253 viodev->dev.of_node = of_node_get(of_node); 1237 viodev->dev.of_node = of_node_get(of_node);
1254 1238
1255 if (firmware_has_feature(FW_FEATURE_CMO)) 1239 if (firmware_has_feature(FW_FEATURE_CMO))
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 710a54005dfb..65d1c08cf09e 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -109,11 +109,6 @@ SECTIONS
109 __ptov_table_begin = .; 109 __ptov_table_begin = .;
110 *(.ptov_fixup); 110 *(.ptov_fixup);
111 __ptov_table_end = .; 111 __ptov_table_end = .;
112#ifdef CONFIG_PPC_ISERIES
113 __dt_strings_start = .;
114 *(.dt_strings);
115 __dt_strings_end = .;
116#endif
117 } 112 }
118 113
119 .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { 114 .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 336983da9e72..a7267167a550 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -46,7 +46,6 @@
46#include <asm/page.h> 46#include <asm/page.h>
47#include <asm/hvcall.h> 47#include <asm/hvcall.h>
48#include <linux/gfp.h> 48#include <linux/gfp.h>
49#include <linux/sched.h>
50#include <linux/vmalloc.h> 49#include <linux/vmalloc.h>
51#include <linux/highmem.h> 50#include <linux/highmem.h>
52 51
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index a6ebba56fdd4..bb7cfecf2788 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -19,11 +19,9 @@
19#include <linux/smp.h> 19#include <linux/smp.h>
20 20
21/* waiting for a spinlock... */ 21/* waiting for a spinlock... */
22#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) 22#if defined(CONFIG_PPC_SPLPAR)
23#include <asm/hvcall.h> 23#include <asm/hvcall.h>
24#include <asm/iseries/hv_call.h>
25#include <asm/smp.h> 24#include <asm/smp.h>
26#include <asm/firmware.h>
27 25
28void __spin_yield(arch_spinlock_t *lock) 26void __spin_yield(arch_spinlock_t *lock)
29{ 27{
@@ -40,14 +38,8 @@ void __spin_yield(arch_spinlock_t *lock)
40 rmb(); 38 rmb();
41 if (lock->slock != lock_value) 39 if (lock->slock != lock_value)
42 return; /* something has changed */ 40 return; /* something has changed */
43 if (firmware_has_feature(FW_FEATURE_ISERIES)) 41 plpar_hcall_norets(H_CONFER,
44 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, 42 get_hard_smp_processor_id(holder_cpu), yield_count);
45 ((u64)holder_cpu << 32) | yield_count);
46#ifdef CONFIG_PPC_SPLPAR
47 else
48 plpar_hcall_norets(H_CONFER,
49 get_hard_smp_processor_id(holder_cpu), yield_count);
50#endif
51} 43}
52 44
53/* 45/*
@@ -71,14 +63,8 @@ void __rw_yield(arch_rwlock_t *rw)
71 rmb(); 63 rmb();
72 if (rw->lock != lock_value) 64 if (rw->lock != lock_value)
73 return; /* something has changed */ 65 return; /* something has changed */
74 if (firmware_has_feature(FW_FEATURE_ISERIES)) 66 plpar_hcall_norets(H_CONFER,
75 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc, 67 get_hard_smp_processor_id(holder_cpu), yield_count);
76 ((u64)holder_cpu << 32) | yield_count);
77#ifdef CONFIG_PPC_SPLPAR
78 else
79 plpar_hcall_norets(H_CONFER,
80 get_hard_smp_processor_id(holder_cpu), yield_count);
81#endif
82} 68}
83#endif 69#endif
84 70
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 2f0d1b032a89..19f2f9498b27 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -105,6 +105,82 @@ static int store_updates_sp(struct pt_regs *regs)
105 } 105 }
106 return 0; 106 return 0;
107} 107}
108/*
109 * do_page_fault error handling helpers
110 */
111
112#define MM_FAULT_RETURN 0
113#define MM_FAULT_CONTINUE -1
114#define MM_FAULT_ERR(sig) (sig)
115
116static int out_of_memory(struct pt_regs *regs)
117{
118 /*
119 * We ran out of memory, or some other thing happened to us that made
120 * us unable to handle the page fault gracefully.
121 */
122 up_read(&current->mm->mmap_sem);
123 if (!user_mode(regs))
124 return MM_FAULT_ERR(SIGKILL);
125 pagefault_out_of_memory();
126 return MM_FAULT_RETURN;
127}
128
129static int do_sigbus(struct pt_regs *regs, unsigned long address)
130{
131 siginfo_t info;
132
133 up_read(&current->mm->mmap_sem);
134
135 if (user_mode(regs)) {
136 info.si_signo = SIGBUS;
137 info.si_errno = 0;
138 info.si_code = BUS_ADRERR;
139 info.si_addr = (void __user *)address;
140 force_sig_info(SIGBUS, &info, current);
141 return MM_FAULT_RETURN;
142 }
143 return MM_FAULT_ERR(SIGBUS);
144}
145
146static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
147{
148 /*
149 * Pagefault was interrupted by SIGKILL. We have no reason to
150 * continue the pagefault.
151 */
152 if (fatal_signal_pending(current)) {
153 /*
154 * If we have retry set, the mmap semaphore will have
155 * alrady been released in __lock_page_or_retry(). Else
156 * we release it now.
157 */
158 if (!(fault & VM_FAULT_RETRY))
159 up_read(&current->mm->mmap_sem);
160 /* Coming from kernel, we need to deal with uaccess fixups */
161 if (user_mode(regs))
162 return MM_FAULT_RETURN;
163 return MM_FAULT_ERR(SIGKILL);
164 }
165
166 /* No fault: be happy */
167 if (!(fault & VM_FAULT_ERROR))
168 return MM_FAULT_CONTINUE;
169
170 /* Out of memory */
171 if (fault & VM_FAULT_OOM)
172 return out_of_memory(regs);
173
174 /* Bus error. x86 handles HWPOISON here, we'll add this if/when
175 * we support the feature in HW
176 */
177 if (fault & VM_FAULT_SIGBUS)
178 return do_sigbus(regs, addr);
179
180 /* We don't understand the fault code, this is fatal */
181 BUG();
182 return MM_FAULT_CONTINUE;
183}
108 184
109/* 185/*
110 * For 600- and 800-family processors, the error_code parameter is DSISR 186 * For 600- and 800-family processors, the error_code parameter is DSISR
@@ -124,11 +200,12 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
124{ 200{
125 struct vm_area_struct * vma; 201 struct vm_area_struct * vma;
126 struct mm_struct *mm = current->mm; 202 struct mm_struct *mm = current->mm;
127 siginfo_t info; 203 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
128 int code = SEGV_MAPERR; 204 int code = SEGV_MAPERR;
129 int is_write = 0, ret; 205 int is_write = 0;
130 int trap = TRAP(regs); 206 int trap = TRAP(regs);
131 int is_exec = trap == 0x400; 207 int is_exec = trap == 0x400;
208 int fault;
132 209
133#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) 210#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
134 /* 211 /*
@@ -145,6 +222,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
145 is_write = error_code & ESR_DST; 222 is_write = error_code & ESR_DST;
146#endif /* CONFIG_4xx || CONFIG_BOOKE */ 223#endif /* CONFIG_4xx || CONFIG_BOOKE */
147 224
225 if (is_write)
226 flags |= FAULT_FLAG_WRITE;
227
148#ifdef CONFIG_PPC_ICSWX 228#ifdef CONFIG_PPC_ICSWX
149 /* 229 /*
150 * we need to do this early because this "data storage 230 * we need to do this early because this "data storage
@@ -152,13 +232,11 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
152 * look at it 232 * look at it
153 */ 233 */
154 if (error_code & ICSWX_DSI_UCT) { 234 if (error_code & ICSWX_DSI_UCT) {
155 int ret; 235 int rc = acop_handle_fault(regs, address, error_code);
156 236 if (rc)
157 ret = acop_handle_fault(regs, address, error_code); 237 return rc;
158 if (ret)
159 return ret;
160 } 238 }
161#endif 239#endif /* CONFIG_PPC_ICSWX */
162 240
163 if (notify_page_fault(regs)) 241 if (notify_page_fault(regs))
164 return 0; 242 return 0;
@@ -179,6 +257,10 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
179 } 257 }
180#endif 258#endif
181 259
260 /* We restore the interrupt state now */
261 if (!arch_irq_disabled_regs(regs))
262 local_irq_enable();
263
182 if (in_atomic() || mm == NULL) { 264 if (in_atomic() || mm == NULL) {
183 if (!user_mode(regs)) 265 if (!user_mode(regs))
184 return SIGSEGV; 266 return SIGSEGV;
@@ -212,7 +294,15 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
212 if (!user_mode(regs) && !search_exception_tables(regs->nip)) 294 if (!user_mode(regs) && !search_exception_tables(regs->nip))
213 goto bad_area_nosemaphore; 295 goto bad_area_nosemaphore;
214 296
297retry:
215 down_read(&mm->mmap_sem); 298 down_read(&mm->mmap_sem);
299 } else {
300 /*
301 * The above down_read_trylock() might have succeeded in
302 * which case we'll have missed the might_sleep() from
303 * down_read():
304 */
305 might_sleep();
216 } 306 }
217 307
218 vma = find_vma(mm, address); 308 vma = find_vma(mm, address);
@@ -327,30 +417,43 @@ good_area:
327 * make sure we exit gracefully rather than endlessly redo 417 * make sure we exit gracefully rather than endlessly redo
328 * the fault. 418 * the fault.
329 */ 419 */
330 ret = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); 420 fault = handle_mm_fault(mm, vma, address, flags);
331 if (unlikely(ret & VM_FAULT_ERROR)) { 421 if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
332 if (ret & VM_FAULT_OOM) 422 int rc = mm_fault_error(regs, address, fault);
333 goto out_of_memory; 423 if (rc >= MM_FAULT_RETURN)
334 else if (ret & VM_FAULT_SIGBUS) 424 return rc;
335 goto do_sigbus;
336 BUG();
337 } 425 }
338 if (ret & VM_FAULT_MAJOR) { 426
339 current->maj_flt++; 427 /*
340 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 428 * Major/minor page fault accounting is only done on the
341 regs, address); 429 * initial attempt. If we go through a retry, it is extremely
430 * likely that the page will be found in page cache at that point.
431 */
432 if (flags & FAULT_FLAG_ALLOW_RETRY) {
433 if (fault & VM_FAULT_MAJOR) {
434 current->maj_flt++;
435 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
436 regs, address);
342#ifdef CONFIG_PPC_SMLPAR 437#ifdef CONFIG_PPC_SMLPAR
343 if (firmware_has_feature(FW_FEATURE_CMO)) { 438 if (firmware_has_feature(FW_FEATURE_CMO)) {
344 preempt_disable(); 439 preempt_disable();
345 get_lppaca()->page_ins += (1 << PAGE_FACTOR); 440 get_lppaca()->page_ins += (1 << PAGE_FACTOR);
346 preempt_enable(); 441 preempt_enable();
442 }
443#endif /* CONFIG_PPC_SMLPAR */
444 } else {
445 current->min_flt++;
446 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
447 regs, address);
448 }
449 if (fault & VM_FAULT_RETRY) {
450 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
451 * of starvation. */
452 flags &= ~FAULT_FLAG_ALLOW_RETRY;
453 goto retry;
347 } 454 }
348#endif
349 } else {
350 current->min_flt++;
351 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
352 regs, address);
353 } 455 }
456
354 up_read(&mm->mmap_sem); 457 up_read(&mm->mmap_sem);
355 return 0; 458 return 0;
356 459
@@ -371,28 +474,6 @@ bad_area_nosemaphore:
371 474
372 return SIGSEGV; 475 return SIGSEGV;
373 476
374/*
375 * We ran out of memory, or some other thing happened to us that made
376 * us unable to handle the page fault gracefully.
377 */
378out_of_memory:
379 up_read(&mm->mmap_sem);
380 if (!user_mode(regs))
381 return SIGKILL;
382 pagefault_out_of_memory();
383 return 0;
384
385do_sigbus:
386 up_read(&mm->mmap_sem);
387 if (user_mode(regs)) {
388 info.si_signo = SIGBUS;
389 info.si_errno = 0;
390 info.si_code = BUS_ADRERR;
391 info.si_addr = (void __user *)address;
392 force_sig_info(SIGBUS, &info, current);
393 return 0;
394 }
395 return SIGBUS;
396} 477}
397 478
398/* 479/*
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 66a6fd38e9cd..07ba45b0f07c 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -149,12 +149,19 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
149unsigned long calc_cam_sz(unsigned long ram, unsigned long virt, 149unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
150 phys_addr_t phys) 150 phys_addr_t phys)
151{ 151{
152 unsigned int camsize = __ilog2(ram) & ~1U; 152 unsigned int camsize = __ilog2(ram);
153 unsigned int align = __ffs(virt | phys) & ~1U; 153 unsigned int align = __ffs(virt | phys);
154 unsigned long max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xf; 154 unsigned long max_cam;
155 155
156 /* Convert (4^max) kB to (2^max) bytes */ 156 if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
157 max_cam = max_cam * 2 + 10; 157 /* Convert (4^max) kB to (2^max) bytes */
158 max_cam = ((mfspr(SPRN_TLB1CFG) >> 16) & 0xf) * 2 + 10;
159 camsize &= ~1U;
160 align &= ~1U;
161 } else {
162 /* Convert (2^max) kB to (2^max) bytes */
163 max_cam = __ilog2(mfspr(SPRN_TLB1PS)) + 10;
164 }
158 165
159 if (camsize > align) 166 if (camsize > align)
160 camsize = align; 167 camsize = align;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 2d282186cb45..3e8c37a4e395 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -55,6 +55,8 @@
55#include <asm/spu.h> 55#include <asm/spu.h>
56#include <asm/udbg.h> 56#include <asm/udbg.h>
57#include <asm/code-patching.h> 57#include <asm/code-patching.h>
58#include <asm/fadump.h>
59#include <asm/firmware.h>
58 60
59#ifdef DEBUG 61#ifdef DEBUG
60#define DBG(fmt...) udbg_printf(fmt) 62#define DBG(fmt...) udbg_printf(fmt)
@@ -625,6 +627,16 @@ static void __init htab_initialize(void)
625 /* Using a hypervisor which owns the htab */ 627 /* Using a hypervisor which owns the htab */
626 htab_address = NULL; 628 htab_address = NULL;
627 _SDR1 = 0; 629 _SDR1 = 0;
630#ifdef CONFIG_FA_DUMP
631 /*
632 * If firmware assisted dump is active firmware preserves
633 * the contents of htab along with entire partition memory.
634 * Clear the htab if firmware assisted dump is active so
635 * that we dont end up using old mappings.
636 */
637 if (is_fadump_active() && ppc_md.hpte_clear_all)
638 ppc_md.hpte_clear_all();
639#endif
628 } else { 640 } else {
629 /* Find storage for the HPT. Must be contiguous in 641 /* Find storage for the HPT. Must be contiguous in
630 * the absolute address space. On cell we want it to be 642 * the absolute address space. On cell we want it to be
@@ -745,12 +757,9 @@ void __init early_init_mmu(void)
745 */ 757 */
746 htab_initialize(); 758 htab_initialize();
747 759
748 /* Initialize stab / SLB management except on iSeries 760 /* Initialize stab / SLB management */
749 */
750 if (mmu_has_feature(MMU_FTR_SLB)) 761 if (mmu_has_feature(MMU_FTR_SLB))
751 slb_initialize(); 762 slb_initialize();
752 else if (!firmware_has_feature(FW_FEATURE_ISERIES))
753 stab_initialize(get_paca()->stab_real);
754} 763}
755 764
756#ifdef CONFIG_SMP 765#ifdef CONFIG_SMP
@@ -761,8 +770,7 @@ void __cpuinit early_init_mmu_secondary(void)
761 mtspr(SPRN_SDR1, _SDR1); 770 mtspr(SPRN_SDR1, _SDR1);
762 771
763 /* Initialize STAB/SLB. We use a virtual address as it works 772 /* Initialize STAB/SLB. We use a virtual address as it works
764 * in real mode on pSeries and we want a virtual address on 773 * in real mode on pSeries.
765 * iSeries anyway
766 */ 774 */
767 if (mmu_has_feature(MMU_FTR_SLB)) 775 if (mmu_has_feature(MMU_FTR_SLB))
768 slb_initialize(); 776 slb_initialize();
diff --git a/arch/powerpc/mm/icswx.c b/arch/powerpc/mm/icswx.c
index 5d9a59eaad93..8cdbd8634a58 100644
--- a/arch/powerpc/mm/icswx.c
+++ b/arch/powerpc/mm/icswx.c
@@ -163,7 +163,7 @@ EXPORT_SYMBOL_GPL(drop_cop);
163 163
164static int acop_use_cop(int ct) 164static int acop_use_cop(int ct)
165{ 165{
166 /* todo */ 166 /* There is no alternate policy, yet */
167 return -1; 167 return -1;
168} 168}
169 169
@@ -227,11 +227,30 @@ int acop_handle_fault(struct pt_regs *regs, unsigned long address,
227 ct = (ccw >> 16) & 0x3f; 227 ct = (ccw >> 16) & 0x3f;
228 } 228 }
229 229
230 /*
231 * We could be here because another thread has enabled acop
232 * but the ACOP register has yet to be updated.
233 *
234 * This should have been taken care of by the IPI to sync all
235 * the threads (see smp_call_function(sync_cop, mm, 1)), but
236 * that could take forever if there are a significant amount
237 * of threads.
238 *
239 * Given the number of threads on some of these systems,
240 * perhaps this is the best way to sync ACOP rather than whack
241 * every thread with an IPI.
242 */
243 if ((acop_copro_type_bit(ct) & current->active_mm->context.acop) != 0) {
244 sync_cop(current->active_mm);
245 return 0;
246 }
247
248 /* check for alternate policy */
230 if (!acop_use_cop(ct)) 249 if (!acop_use_cop(ct))
231 return 0; 250 return 0;
232 251
233 /* at this point the CT is unknown to the system */ 252 /* at this point the CT is unknown to the system */
234 pr_warn("%s[%d]: Coprocessor %d is unavailable", 253 pr_warn("%s[%d]: Coprocessor %d is unavailable\n",
235 current->comm, current->pid, ct); 254 current->comm, current->pid, ct);
236 255
237 /* get inst if we don't already have it */ 256 /* get inst if we don't already have it */
diff --git a/arch/powerpc/mm/icswx.h b/arch/powerpc/mm/icswx.h
index 42176bd0884c..6dedc08e62c8 100644
--- a/arch/powerpc/mm/icswx.h
+++ b/arch/powerpc/mm/icswx.h
@@ -59,4 +59,10 @@ extern void free_cop_pid(int free_pid);
59 59
60extern int acop_handle_fault(struct pt_regs *regs, unsigned long address, 60extern int acop_handle_fault(struct pt_regs *regs, unsigned long address,
61 unsigned long error_code); 61 unsigned long error_code);
62
63static inline u64 acop_copro_type_bit(unsigned int type)
64{
65 return 1ULL << (63 - type);
66}
67
62#endif /* !_ARCH_POWERPC_MM_ICSWX_H_ */ 68#endif /* !_ARCH_POWERPC_MM_ICSWX_H_ */
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 51f87956f8f8..0907f92ce309 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -207,7 +207,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
207 */ 207 */
208 if (mem_init_done && (p < virt_to_phys(high_memory)) && 208 if (mem_init_done && (p < virt_to_phys(high_memory)) &&
209 !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) { 209 !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) {
210 printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n", 210 printk("__ioremap(): phys addr 0x%llx is RAM lr %pf\n",
211 (unsigned long long)p, __builtin_return_address(0)); 211 (unsigned long long)p, __builtin_return_address(0));
212 return NULL; 212 return NULL;
213 } 213 }
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index e22276cb67a4..a538c80db2df 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -21,7 +21,6 @@
21#include <asm/cputable.h> 21#include <asm/cputable.h>
22#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
23#include <asm/smp.h> 23#include <asm/smp.h>
24#include <asm/firmware.h>
25#include <linux/compiler.h> 24#include <linux/compiler.h>
26#include <asm/udbg.h> 25#include <asm/udbg.h>
27#include <asm/code-patching.h> 26#include <asm/code-patching.h>
@@ -307,11 +306,6 @@ void slb_initialize(void)
307 306
308 get_paca()->stab_rr = SLB_NUM_BOLTED; 307 get_paca()->stab_rr = SLB_NUM_BOLTED;
309 308
310 /* On iSeries the bolted entries have already been set up by
311 * the hypervisor from the lparMap data in head.S */
312 if (firmware_has_feature(FW_FEATURE_ISERIES))
313 return;
314
315 lflags = SLB_VSID_KERNEL | linear_llp; 309 lflags = SLB_VSID_KERNEL | linear_llp;
316 vflags = SLB_VSID_KERNEL | vmalloc_llp; 310 vflags = SLB_VSID_KERNEL | vmalloc_llp;
317 311
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index ef653dc95b65..b9ee79ce2200 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -217,21 +217,6 @@ slb_finish_load:
217 * free slot first but that took too long. Unfortunately we 217 * free slot first but that took too long. Unfortunately we
218 * dont have any LRU information to help us choose a slot. 218 * dont have any LRU information to help us choose a slot.
219 */ 219 */
220#ifdef CONFIG_PPC_ISERIES
221BEGIN_FW_FTR_SECTION
222 /*
223 * On iSeries, the "bolted" stack segment can be cast out on
224 * shared processor switch so we need to check for a miss on
225 * it and restore it to the right slot.
226 */
227 ld r9,PACAKSAVE(r13)
228 clrrdi r9,r9,28
229 clrrdi r3,r3,28
230 li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */
231 cmpld r9,r3
232 beq 3f
233END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
234#endif /* CONFIG_PPC_ISERIES */
235 220
2367: ld r10,PACASTABRR(r13) 2217: ld r10,PACASTABRR(r13)
237 addi r10,r10,1 222 addi r10,r10,1
@@ -282,7 +267,6 @@ _GLOBAL(slb_compare_rr_to_size)
282 267
283/* 268/*
284 * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return. 269 * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return.
285 * We assume legacy iSeries will never have 1T segments.
286 * 270 *
287 * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9 271 * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9
288 */ 272 */
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 41e31642a86a..9106ebb118f5 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -21,8 +21,6 @@
21#include <asm/cputable.h> 21#include <asm/cputable.h>
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/abs_addr.h> 23#include <asm/abs_addr.h>
24#include <asm/firmware.h>
25#include <asm/iseries/hv_call.h>
26 24
27struct stab_entry { 25struct stab_entry {
28 unsigned long esid_data; 26 unsigned long esid_data;
@@ -285,12 +283,5 @@ void stab_initialize(unsigned long stab)
285 /* Set ASR */ 283 /* Set ASR */
286 stabreal = get_paca()->stab_real | 0x1ul; 284 stabreal = get_paca()->stab_real | 0x1ul;
287 285
288#ifdef CONFIG_PPC_ISERIES
289 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
290 HvCall1(HvCallBaseSetASR, stabreal);
291 return;
292 }
293#endif /* CONFIG_PPC_ISERIES */
294
295 mtspr(SPRN_ASR, stabreal); 286 mtspr(SPRN_ASR, stabreal);
296} 287}
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index d65e68f3cb25..6f01624f317f 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -195,9 +195,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
195 if (!cur_cpu_spec->oprofile_cpu_type) 195 if (!cur_cpu_spec->oprofile_cpu_type)
196 return -ENODEV; 196 return -ENODEV;
197 197
198 if (firmware_has_feature(FW_FEATURE_ISERIES))
199 return -ENODEV;
200
201 switch (cur_cpu_spec->oprofile_type) { 198 switch (cur_cpu_spec->oprofile_type) {
202#ifdef CONFIG_PPC_BOOK3S_64 199#ifdef CONFIG_PPC_BOOK3S_64
203#ifdef CONFIG_OPROFILE_CELL 200#ifdef CONFIG_OPROFILE_CELL
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
new file mode 100644
index 000000000000..af3fac23768c
--- /dev/null
+++ b/arch/powerpc/perf/Makefile
@@ -0,0 +1,14 @@
1subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
2
3obj-$(CONFIG_PERF_EVENTS) += callchain.o
4
5obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o
6obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \
7 power5+-pmu.o power6-pmu.o power7-pmu.o
8obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
9
10obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o
11obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o
12
13obj-$(CONFIG_PPC64) += $(obj64-y)
14obj-$(CONFIG_PPC32) += $(obj32-y)
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/perf/callchain.c
index 564c1d8bdb5c..e8a18d1cc7c9 100644
--- a/arch/powerpc/kernel/perf_callchain.c
+++ b/arch/powerpc/perf/callchain.c
@@ -20,7 +20,7 @@
20#include <asm/ucontext.h> 20#include <asm/ucontext.h>
21#include <asm/vdso.h> 21#include <asm/vdso.h>
22#ifdef CONFIG_PPC64 22#ifdef CONFIG_PPC64
23#include "ppc32.h" 23#include "../kernel/ppc32.h"
24#endif 24#endif
25 25
26 26
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/perf/core-book3s.c
index c2e27ede07ec..c2e27ede07ec 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/perf/core-book3s.c
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/perf/core-fsl-emb.c
index 0a6d2a9d569c..0a6d2a9d569c 100644
--- a/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ b/arch/powerpc/perf/core-fsl-emb.c
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/perf/e500-pmu.c
index cb2e2949c8d1..cb2e2949c8d1 100644
--- a/arch/powerpc/kernel/e500-pmu.c
+++ b/arch/powerpc/perf/e500-pmu.c
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/perf/mpc7450-pmu.c
index fe21b515ca44..fe21b515ca44 100644
--- a/arch/powerpc/kernel/mpc7450-pmu.c
+++ b/arch/powerpc/perf/mpc7450-pmu.c
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/perf/power4-pmu.c
index b4f1dda4d089..b4f1dda4d089 100644
--- a/arch/powerpc/kernel/power4-pmu.c
+++ b/arch/powerpc/perf/power4-pmu.c
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/perf/power5+-pmu.c
index a8757baa28f3..a8757baa28f3 100644
--- a/arch/powerpc/kernel/power5+-pmu.c
+++ b/arch/powerpc/perf/power5+-pmu.c
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/perf/power5-pmu.c
index e7f06eb7a861..e7f06eb7a861 100644
--- a/arch/powerpc/kernel/power5-pmu.c
+++ b/arch/powerpc/perf/power5-pmu.c
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c
index 0bbc901e7efc..31128e086fed 100644
--- a/arch/powerpc/kernel/power6-pmu.c
+++ b/arch/powerpc/perf/power6-pmu.c
@@ -131,7 +131,7 @@ static u32 marked_bus_events[16] = {
131 0x00000022, /* BFP set 2: byte 0 bits 1, 5 */ 131 0x00000022, /* BFP set 2: byte 0 bits 1, 5 */
132 0, 0 132 0, 0
133}; 133};
134 134
135/* 135/*
136 * Returns 1 if event counts things relating to marked instructions 136 * Returns 1 if event counts things relating to marked instructions
137 * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not. 137 * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index 1251e4d7e262..1251e4d7e262 100644
--- a/arch/powerpc/kernel/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c
index 8c2190206964..111eb25bb0b6 100644
--- a/arch/powerpc/kernel/ppc970-pmu.c
+++ b/arch/powerpc/perf/ppc970-pmu.c
@@ -252,7 +252,7 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
252 alt[1] = event ^ 0x1000; 252 alt[1] = event ^ 0x1000;
253 return 2; 253 return 2;
254 } 254 }
255 255
256 return 1; 256 return 1;
257} 257}
258 258
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index fcf6bf2ceee9..2e4e64abfab4 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -23,6 +23,7 @@ config BLUESTONE
23 default n 23 default n
24 select PPC44x_SIMPLE 24 select PPC44x_SIMPLE
25 select APM821xx 25 select APM821xx
26 select PPC4xx_PCI_EXPRESS
26 select IBM_EMAC_RGMII 27 select IBM_EMAC_RGMII
27 help 28 help
28 This option enables support for the APM APM821xx Evaluation board. 29 This option enables support for the APM APM821xx Evaluation board.
diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c
index 3f6229b5dee0..583e67fee37e 100644
--- a/arch/powerpc/platforms/44x/currituck.c
+++ b/arch/powerpc/platforms/44x/currituck.c
@@ -83,7 +83,7 @@ static void __init ppc47x_init_irq(void)
83 * device-tree, just pass 0 to all arguments 83 * device-tree, just pass 0 to all arguments
84 */ 84 */
85 struct mpic *mpic = 85 struct mpic *mpic =
86 mpic_alloc(np, 0, 0, 0, 0, " MPIC "); 86 mpic_alloc(np, 0, MPIC_NO_RESET, 0, 0, " MPIC ");
87 BUG_ON(mpic == NULL); 87 BUG_ON(mpic == NULL);
88 mpic_init(mpic); 88 mpic_init(mpic);
89 ppc_md.get_irq = mpic_get_irq; 89 ppc_md.get_irq = mpic_get_irq;
diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c
index 5b8cdbb82f80..a28a8629727e 100644
--- a/arch/powerpc/platforms/44x/iss4xx.c
+++ b/arch/powerpc/platforms/44x/iss4xx.c
@@ -71,8 +71,7 @@ static void __init iss4xx_init_irq(void)
71 /* The MPIC driver will get everything it needs from the 71 /* The MPIC driver will get everything it needs from the
72 * device-tree, just pass 0 to all arguments 72 * device-tree, just pass 0 to all arguments
73 */ 73 */
74 struct mpic *mpic = mpic_alloc(np, 0, 0, 0, 0, 74 struct mpic *mpic = mpic_alloc(np, 0, MPIC_NO_RESET, 0, 0, " MPIC ");
75 " MPIC ");
76 BUG_ON(mpic == NULL); 75 BUG_ON(mpic == NULL);
77 mpic_init(mpic); 76 mpic_init(mpic);
78 ppc_md.get_irq = mpic_get_irq; 77 ppc_md.get_irq = mpic_get_irq;
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 8d2202763415..3ffb915446e3 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -52,7 +52,7 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe);
52static char *board[] __initdata = { 52static char *board[] __initdata = {
53 "amcc,arches", 53 "amcc,arches",
54 "amcc,bamboo", 54 "amcc,bamboo",
55 "amcc,bluestone", 55 "apm,bluestone",
56 "amcc,glacier", 56 "amcc,glacier",
57 "ibm,ebony", 57 "ibm,ebony",
58 "amcc,eiger", 58 "amcc,eiger",
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index 846b789fb195..c0aa04068d69 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
50 50
51/* list of the supported boards */ 51/* list of the supported boards */
52static const char *board[] __initdata = { 52static const char *board[] __initdata = {
53 "anonymous,a4m072",
53 "anon,charon", 54 "anon,charon",
54 "intercontrol,digsy-mtc", 55 "intercontrol,digsy-mtc",
55 "manroland,mucmc52", 56 "manroland,mucmc52",
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 369fd5457a3f..d7e94f49532a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -98,13 +98,11 @@ struct mpc52xx_gpio_wkup __iomem *wkup_gpio;
98 * of the localplus bus to the of_platform 98 * of the localplus bus to the of_platform
99 * bus. 99 * bus.
100 */ 100 */
101void __init 101void __init mpc52xx_declare_of_platform_devices(void)
102mpc52xx_declare_of_platform_devices(void)
103{ 102{
104 /* Find every child of the SOC node and add it to of_platform */ 103 /* Find all the 'platform' devices and register them. */
105 if (of_platform_bus_probe(NULL, mpc52xx_bus_ids, NULL)) 104 if (of_platform_populate(NULL, mpc52xx_bus_ids, NULL, NULL))
106 printk(KERN_ERR __FILE__ ": " 105 pr_err(__FILE__ ": Error while populating devices from DT\n");
107 "Error while probing of_platform bus\n");
108} 106}
109 107
110/* 108/*
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index d7946be298b6..f000d81c4e31 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -6,6 +6,7 @@ menuconfig FSL_SOC_BOOKE
6 select MPIC 6 select MPIC
7 select PPC_PCI_CHOICE 7 select PPC_PCI_CHOICE
8 select FSL_PCI if PCI 8 select FSL_PCI if PCI
9 select SERIAL_8250_EXTENDED if SERIAL_8250
9 select SERIAL_8250_SHARE_IRQ if SERIAL_8250 10 select SERIAL_8250_SHARE_IRQ if SERIAL_8250
10 default y 11 default y
11 12
@@ -13,6 +14,15 @@ if FSL_SOC_BOOKE
13 14
14if PPC32 15if PPC32
15 16
17config FSL_85XX_CACHE_SRAM
18 bool
19 select PPC_LIB_RHEAP
20 help
21 When selected, this option enables cache-sram support
22 for memory allocation on P1/P2 QorIQ platforms.
23 cache-sram-size and cache-sram-offset kernel boot
24 parameters should be passed when this option is enabled.
25
16config MPC8540_ADS 26config MPC8540_ADS
17 bool "Freescale MPC8540 ADS" 27 bool "Freescale MPC8540 ADS"
18 select DEFAULT_UIMAGE 28 select DEFAULT_UIMAGE
@@ -30,6 +40,7 @@ config MPC85xx_CDS
30 bool "Freescale MPC85xx CDS" 40 bool "Freescale MPC85xx CDS"
31 select DEFAULT_UIMAGE 41 select DEFAULT_UIMAGE
32 select PPC_I8259 42 select PPC_I8259
43 select HAS_RAPIDIO
33 help 44 help
34 This option enables support for the MPC85xx CDS board 45 This option enables support for the MPC85xx CDS board
35 46
@@ -80,7 +91,6 @@ config P1010_RDB
80config P1022_DS 91config P1022_DS
81 bool "Freescale P1022 DS" 92 bool "Freescale P1022 DS"
82 select DEFAULT_UIMAGE 93 select DEFAULT_UIMAGE
83 select PHYS_64BIT # The DTS has 36-bit addresses
84 select SWIOTLB 94 select SWIOTLB
85 help 95 help
86 This option enables support for the Freescale P1022DS reference board. 96 This option enables support for the Freescale P1022DS reference board.
@@ -171,6 +181,21 @@ config SBC8560
171 help 181 help
172 This option enables support for the Wind River SBC8560 board 182 This option enables support for the Wind River SBC8560 board
173 183
184config GE_IMP3A
185 bool "GE Intelligent Platforms IMP3A"
186 select DEFAULT_UIMAGE
187 select SWIOTLB
188 select MMIO_NVRAM
189 select GENERIC_GPIO
190 select ARCH_REQUIRE_GPIOLIB
191 select GE_FPGA
192 help
193 This option enables support for the GE Intelligent Platforms IMP3A
194 board.
195
196 This board is a 3U CompactPCI Single Board Computer with a Freescale
197 P2020 processor.
198
174config P2041_RDB 199config P2041_RDB
175 bool "Freescale P2041 RDB" 200 bool "Freescale P2041 RDB"
176 select DEFAULT_UIMAGE 201 select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 9cb2d4320dcc..2125d4ca068a 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_SBC8548) += sbc8548.o
27obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o 27obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o
28obj-$(CONFIG_KSI8560) += ksi8560.o 28obj-$(CONFIG_KSI8560) += ksi8560.o
29obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o 29obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o
30obj-$(CONFIG_GE_IMP3A) += ge_imp3a.o
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 07e3e6c47371..df69e99e511c 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -36,8 +36,8 @@
36void __init corenet_ds_pic_init(void) 36void __init corenet_ds_pic_init(void)
37{ 37{
38 struct mpic *mpic; 38 struct mpic *mpic;
39 unsigned int flags = MPIC_BIG_ENDIAN | 39 unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
40 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU; 40 MPIC_NO_RESET;
41 41
42 if (ppc_md.get_irq == mpic_get_coreint_irq) 42 if (ppc_md.get_irq == mpic_get_coreint_irq)
43 flags |= MPIC_ENABLE_COREINT; 43 flags |= MPIC_ENABLE_COREINT;
diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c
new file mode 100644
index 000000000000..d50056f424f6
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/ge_imp3a.c
@@ -0,0 +1,246 @@
1/*
2 * GE IMP3A Board Setup
3 *
4 * Author Martyn Welch <martyn.welch@ge.com>
5 *
6 * Copyright 2010 GE Intelligent Platforms Embedded Systems, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Based on: mpc85xx_ds.c (MPC85xx DS Board Setup)
14 * Copyright 2007 Freescale Semiconductor Inc.
15 */
16
17#include <linux/stddef.h>
18#include <linux/kernel.h>
19#include <linux/pci.h>
20#include <linux/kdev_t.h>
21#include <linux/delay.h>
22#include <linux/seq_file.h>
23#include <linux/interrupt.h>
24#include <linux/of_platform.h>
25#include <linux/memblock.h>
26
27#include <asm/system.h>
28#include <asm/time.h>
29#include <asm/machdep.h>
30#include <asm/pci-bridge.h>
31#include <mm/mmu_decl.h>
32#include <asm/prom.h>
33#include <asm/udbg.h>
34#include <asm/mpic.h>
35#include <asm/swiotlb.h>
36#include <asm/nvram.h>
37
38#include <sysdev/fsl_soc.h>
39#include <sysdev/fsl_pci.h>
40#include "smp.h"
41
42#include "mpc85xx.h"
43#include <sysdev/ge/ge_pic.h>
44
45void __iomem *imp3a_regs;
46
47void __init ge_imp3a_pic_init(void)
48{
49 struct mpic *mpic;
50 struct device_node *np;
51 struct device_node *cascade_node = NULL;
52 unsigned long root = of_get_flat_dt_root();
53
54 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
55 mpic = mpic_alloc(NULL, 0,
56 MPIC_NO_RESET |
57 MPIC_BIG_ENDIAN |
58 MPIC_SINGLE_DEST_CPU,
59 0, 256, " OpenPIC ");
60 } else {
61 mpic = mpic_alloc(NULL, 0,
62 MPIC_BIG_ENDIAN |
63 MPIC_SINGLE_DEST_CPU,
64 0, 256, " OpenPIC ");
65 }
66
67 BUG_ON(mpic == NULL);
68 mpic_init(mpic);
69 /*
70 * There is a simple interrupt handler in the main FPGA, this needs
71 * to be cascaded into the MPIC
72 */
73 for_each_node_by_type(np, "interrupt-controller")
74 if (of_device_is_compatible(np, "gef,fpga-pic-1.00")) {
75 cascade_node = np;
76 break;
77 }
78
79 if (cascade_node == NULL) {
80 printk(KERN_WARNING "IMP3A: No FPGA PIC\n");
81 return;
82 }
83
84 gef_pic_init(cascade_node);
85 of_node_put(cascade_node);
86}
87
88#ifdef CONFIG_PCI
89static int primary_phb_addr;
90#endif /* CONFIG_PCI */
91
92/*
93 * Setup the architecture
94 */
95static void __init ge_imp3a_setup_arch(void)
96{
97 struct device_node *regs;
98#ifdef CONFIG_PCI
99 struct device_node *np;
100 struct pci_controller *hose;
101#endif
102 dma_addr_t max = 0xffffffff;
103
104 if (ppc_md.progress)
105 ppc_md.progress("ge_imp3a_setup_arch()", 0);
106
107#ifdef CONFIG_PCI
108 for_each_node_by_type(np, "pci") {
109 if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
110 of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
111 of_device_is_compatible(np, "fsl,p2020-pcie")) {
112 struct resource rsrc;
113 of_address_to_resource(np, 0, &rsrc);
114 if ((rsrc.start & 0xfffff) == primary_phb_addr)
115 fsl_add_bridge(np, 1);
116 else
117 fsl_add_bridge(np, 0);
118
119 hose = pci_find_hose_for_OF_device(np);
120 max = min(max, hose->dma_window_base_cur +
121 hose->dma_window_size);
122 }
123 }
124#endif
125
126 mpc85xx_smp_init();
127
128#ifdef CONFIG_SWIOTLB
129 if (memblock_end_of_DRAM() > max) {
130 ppc_swiotlb_enable = 1;
131 set_pci_dma_ops(&swiotlb_dma_ops);
132 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
133 }
134#endif
135
136 /* Remap basic board registers */
137 regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs");
138 if (regs) {
139 imp3a_regs = of_iomap(regs, 0);
140 if (imp3a_regs == NULL)
141 printk(KERN_WARNING "Unable to map board registers\n");
142 of_node_put(regs);
143 }
144
145#if defined(CONFIG_MMIO_NVRAM)
146 mmio_nvram_init();
147#endif
148
149 printk(KERN_INFO "GE Intelligent Platforms IMP3A 3U cPCI SBC\n");
150}
151
152/* Return the PCB revision */
153static unsigned int ge_imp3a_get_pcb_rev(void)
154{
155 unsigned int reg;
156
157 reg = ioread16(imp3a_regs);
158 return (reg >> 8) & 0xff;
159}
160
161/* Return the board (software) revision */
162static unsigned int ge_imp3a_get_board_rev(void)
163{
164 unsigned int reg;
165
166 reg = ioread16(imp3a_regs + 0x2);
167 return reg & 0xff;
168}
169
170/* Return the FPGA revision */
171static unsigned int ge_imp3a_get_fpga_rev(void)
172{
173 unsigned int reg;
174
175 reg = ioread16(imp3a_regs + 0x2);
176 return (reg >> 8) & 0xff;
177}
178
179/* Return compactPCI Geographical Address */
180static unsigned int ge_imp3a_get_cpci_geo_addr(void)
181{
182 unsigned int reg;
183
184 reg = ioread16(imp3a_regs + 0x6);
185 return (reg & 0x0f00) >> 8;
186}
187
188/* Return compactPCI System Controller Status */
189static unsigned int ge_imp3a_get_cpci_is_syscon(void)
190{
191 unsigned int reg;
192
193 reg = ioread16(imp3a_regs + 0x6);
194 return reg & (1 << 12);
195}
196
197static void ge_imp3a_show_cpuinfo(struct seq_file *m)
198{
199 seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
200
201 seq_printf(m, "Revision\t: %u%c\n", ge_imp3a_get_pcb_rev(),
202 ('A' + ge_imp3a_get_board_rev() - 1));
203
204 seq_printf(m, "FPGA Revision\t: %u\n", ge_imp3a_get_fpga_rev());
205
206 seq_printf(m, "cPCI geo. addr\t: %u\n", ge_imp3a_get_cpci_geo_addr());
207
208 seq_printf(m, "cPCI syscon\t: %s\n",
209 ge_imp3a_get_cpci_is_syscon() ? "yes" : "no");
210}
211
212/*
213 * Called very early, device-tree isn't unflattened
214 */
215static int __init ge_imp3a_probe(void)
216{
217 unsigned long root = of_get_flat_dt_root();
218
219 if (of_flat_dt_is_compatible(root, "ge,IMP3A")) {
220#ifdef CONFIG_PCI
221 primary_phb_addr = 0x9000;
222#endif
223 return 1;
224 }
225
226 return 0;
227}
228
229machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices);
230
231machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
232
233define_machine(ge_imp3a) {
234 .name = "GE_IMP3A",
235 .probe = ge_imp3a_probe,
236 .setup_arch = ge_imp3a_setup_arch,
237 .init_IRQ = ge_imp3a_pic_init,
238 .show_cpuinfo = ge_imp3a_show_cpuinfo,
239#ifdef CONFIG_PCI
240 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
241#endif
242 .get_irq = mpic_get_irq,
243 .restart = fsl_rstcr_restart,
244 .calibrate_decr = generic_calibrate_decr,
245 .progress = udbg_progress,
246};
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index 20f75d7819c6..60120e55da41 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -57,8 +57,7 @@ static void machine_restart(char *cmd)
57 57
58static void __init ksi8560_pic_init(void) 58static void __init ksi8560_pic_init(void)
59{ 59{
60 struct mpic *mpic = mpic_alloc(NULL, 0, 60 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
61 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
62 0, 256, " OpenPIC "); 61 0, 256, " OpenPIC ");
63 BUG_ON(mpic == NULL); 62 BUG_ON(mpic == NULL);
64 mpic_init(mpic); 63 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index cf266826682e..f58872688d8f 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -36,9 +36,7 @@
36 36
37void __init mpc8536_ds_pic_init(void) 37void __init mpc8536_ds_pic_init(void)
38{ 38{
39 struct mpic *mpic = mpic_alloc(NULL, 0, 39 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
40 MPIC_WANTS_RESET |
41 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
42 0, 256, " OpenPIC "); 40 0, 256, " OpenPIC ");
43 BUG_ON(mpic == NULL); 41 BUG_ON(mpic == NULL);
44 mpic_init(mpic); 42 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 3bebb5173bfc..d19f675cb369 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -50,8 +50,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
50 50
51static void __init mpc85xx_ads_pic_init(void) 51static void __init mpc85xx_ads_pic_init(void)
52{ 52{
53 struct mpic *mpic = mpic_alloc(NULL, 0, 53 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
54 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
55 0, 256, " OpenPIC "); 54 0, 256, " OpenPIC ");
56 BUG_ON(mpic == NULL); 55 BUG_ON(mpic == NULL);
57 mpic_init(mpic); 56 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 40f03da616a9..ab5f0bf19454 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information) 4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 * 5 *
6 * Copyright 2005 Freescale Semiconductor Inc. 6 * Copyright 2005, 2011-2012 Freescale Semiconductor Inc.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -48,17 +48,24 @@
48 48
49#include "mpc85xx.h" 49#include "mpc85xx.h"
50 50
51/* CADMUS info */ 51/*
52/* xxx - galak, move into device tree */ 52 * The CDS board contains an FPGA/CPLD called "Cadmus", which collects
53#define CADMUS_BASE (0xf8004000) 53 * various logic and performs system control functions.
54#define CADMUS_SIZE (256) 54 * Here is the FPGA/CPLD register map.
55#define CM_VER (0) 55 */
56#define CM_CSR (1) 56struct cadmus_reg {
57#define CM_RST (2) 57 u8 cm_ver; /* Board version */
58 58 u8 cm_csr; /* General control/status */
59 u8 cm_rst; /* Reset control */
60 u8 cm_hsclk; /* High speed clock */
61 u8 cm_hsxclk; /* High speed clock extended */
62 u8 cm_led; /* LED data */
63 u8 cm_pci; /* PCI control/status */
64 u8 cm_dma; /* DMA control */
65 u8 res[248]; /* Total 256 bytes */
66};
59 67
60static int cds_pci_slot = 2; 68static struct cadmus_reg *cadmus;
61static volatile u8 *cadmus;
62 69
63#ifdef CONFIG_PCI 70#ifdef CONFIG_PCI
64 71
@@ -158,6 +165,33 @@ DECLARE_PCI_FIXUP_EARLY(0x1957, 0x3fff, skip_fake_bridge);
158DECLARE_PCI_FIXUP_EARLY(0x3fff, 0x1957, skip_fake_bridge); 165DECLARE_PCI_FIXUP_EARLY(0x3fff, 0x1957, skip_fake_bridge);
159DECLARE_PCI_FIXUP_EARLY(0xff3f, 0x5719, skip_fake_bridge); 166DECLARE_PCI_FIXUP_EARLY(0xff3f, 0x5719, skip_fake_bridge);
160 167
168#define PCI_DEVICE_ID_IDT_TSI310 0x01a7
169
170/*
171 * Fix Tsi310 PCI-X bridge resource.
172 * Force the bridge to open a window from 0x0000-0x1fff in PCI I/O space.
173 * This allows legacy I/O(i8259, etc) on the VIA southbridge to be accessed.
174 */
175void mpc85xx_cds_fixup_bus(struct pci_bus *bus)
176{
177 struct pci_dev *dev = bus->self;
178 struct resource *res = bus->resource[0];
179
180 if (dev != NULL &&
181 dev->vendor == PCI_VENDOR_ID_IBM &&
182 dev->device == PCI_DEVICE_ID_IDT_TSI310) {
183 if (res) {
184 res->start = 0;
185 res->end = 0x1fff;
186 res->flags = IORESOURCE_IO;
187 pr_info("mpc85xx_cds: PCI bridge resource fixup applied\n");
188 pr_info("mpc85xx_cds: %pR\n", res);
189 }
190 }
191
192 fsl_pcibios_fixup_bus(bus);
193}
194
161#ifdef CONFIG_PPC_I8259 195#ifdef CONFIG_PPC_I8259
162static void mpc85xx_8259_cascade_handler(unsigned int irq, 196static void mpc85xx_8259_cascade_handler(unsigned int irq,
163 struct irq_desc *desc) 197 struct irq_desc *desc)
@@ -188,8 +222,7 @@ static struct irqaction mpc85xxcds_8259_irqaction = {
188static void __init mpc85xx_cds_pic_init(void) 222static void __init mpc85xx_cds_pic_init(void)
189{ 223{
190 struct mpic *mpic; 224 struct mpic *mpic;
191 mpic = mpic_alloc(NULL, 0, 225 mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
192 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
193 0, 256, " OpenPIC "); 226 0, 256, " OpenPIC ");
194 BUG_ON(mpic == NULL); 227 BUG_ON(mpic == NULL);
195 mpic_init(mpic); 228 mpic_init(mpic);
@@ -249,20 +282,30 @@ machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
249 */ 282 */
250static void __init mpc85xx_cds_setup_arch(void) 283static void __init mpc85xx_cds_setup_arch(void)
251{ 284{
252#ifdef CONFIG_PCI
253 struct device_node *np; 285 struct device_node *np;
254#endif 286 int cds_pci_slot;
255 287
256 if (ppc_md.progress) 288 if (ppc_md.progress)
257 ppc_md.progress("mpc85xx_cds_setup_arch()", 0); 289 ppc_md.progress("mpc85xx_cds_setup_arch()", 0);
258 290
259 cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); 291 np = of_find_compatible_node(NULL, NULL, "fsl,mpc8548cds-fpga");
260 cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; 292 if (!np) {
293 pr_err("Could not find FPGA node.\n");
294 return;
295 }
296
297 cadmus = of_iomap(np, 0);
298 of_node_put(np);
299 if (!cadmus) {
300 pr_err("Fail to map FPGA area.\n");
301 return;
302 }
261 303
262 if (ppc_md.progress) { 304 if (ppc_md.progress) {
263 char buf[40]; 305 char buf[40];
306 cds_pci_slot = ((in_8(&cadmus->cm_csr) >> 6) & 0x3) + 1;
264 snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", 307 snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",
265 cadmus[CM_VER], cds_pci_slot); 308 in_8(&cadmus->cm_ver), cds_pci_slot);
266 ppc_md.progress(buf, 0); 309 ppc_md.progress(buf, 0);
267 } 310 }
268 311
@@ -292,7 +335,8 @@ static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
292 svid = mfspr(SPRN_SVR); 335 svid = mfspr(SPRN_SVR);
293 336
294 seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); 337 seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
295 seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]); 338 seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n",
339 in_8(&cadmus->cm_ver));
296 seq_printf(m, "PVR\t\t: 0x%x\n", pvid); 340 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
297 seq_printf(m, "SVR\t\t: 0x%x\n", svid); 341 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
298 342
@@ -323,7 +367,7 @@ define_machine(mpc85xx_cds) {
323 .get_irq = mpic_get_irq, 367 .get_irq = mpic_get_irq,
324#ifdef CONFIG_PCI 368#ifdef CONFIG_PCI
325 .restart = mpc85xx_cds_restart, 369 .restart = mpc85xx_cds_restart,
326 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 370 .pcibios_fixup_bus = mpc85xx_cds_fixup_bus,
327#else 371#else
328 .restart = fsl_rstcr_restart, 372 .restart = fsl_rstcr_restart,
329#endif 373#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index eefbb91e1d61..6e23e3e34bd9 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -72,13 +72,13 @@ void __init mpc85xx_ds_pic_init(void)
72 72
73 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) { 73 if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
74 mpic = mpic_alloc(NULL, 0, 74 mpic = mpic_alloc(NULL, 0,
75 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | 75 MPIC_NO_RESET |
76 MPIC_BIG_ENDIAN |
76 MPIC_SINGLE_DEST_CPU, 77 MPIC_SINGLE_DEST_CPU,
77 0, 256, " OpenPIC "); 78 0, 256, " OpenPIC ");
78 } else { 79 } else {
79 mpic = mpic_alloc(NULL, 0, 80 mpic = mpic_alloc(NULL, 0,
80 MPIC_WANTS_RESET | 81 MPIC_BIG_ENDIAN |
81 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
82 MPIC_SINGLE_DEST_CPU, 82 MPIC_SINGLE_DEST_CPU,
83 0, 256, " OpenPIC "); 83 0, 256, " OpenPIC ");
84 } 84 }
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 1d15a0cd2c82..f33662b46b8d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved. 2 * Copyright (C) 2006-2010, 2012 Freescale Semicondutor, Inc.
3 * All rights reserved.
3 * 4 *
4 * Author: Andy Fleming <afleming@freescale.com> 5 * Author: Andy Fleming <afleming@freescale.com>
5 * 6 *
@@ -51,6 +52,7 @@
51#include <asm/qe_ic.h> 52#include <asm/qe_ic.h>
52#include <asm/mpic.h> 53#include <asm/mpic.h>
53#include <asm/swiotlb.h> 54#include <asm/swiotlb.h>
55#include <asm/fsl_guts.h>
54#include "smp.h" 56#include "smp.h"
55 57
56#include "mpc85xx.h" 58#include "mpc85xx.h"
@@ -268,34 +270,27 @@ static void __init mpc85xx_mds_qe_init(void)
268 mpc85xx_mds_reset_ucc_phys(); 270 mpc85xx_mds_reset_ucc_phys();
269 271
270 if (machine_is(p1021_mds)) { 272 if (machine_is(p1021_mds)) {
271#define MPC85xx_PMUXCR_OFFSET 0x60
272#define MPC85xx_PMUXCR_QE0 0x00008000
273#define MPC85xx_PMUXCR_QE3 0x00001000
274#define MPC85xx_PMUXCR_QE9 0x00000040
275#define MPC85xx_PMUXCR_QE12 0x00000008
276 static __be32 __iomem *pmuxcr;
277 273
278 np = of_find_node_by_name(NULL, "global-utilities"); 274 struct ccsr_guts_85xx __iomem *guts;
279 275
276 np = of_find_node_by_name(NULL, "global-utilities");
280 if (np) { 277 if (np) {
281 pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET; 278 guts = of_iomap(np, 0);
282 279 if (!guts)
283 if (!pmuxcr) 280 pr_err("mpc85xx-rdb: could not map global utilities register\n");
284 printk(KERN_EMERG "Error: Alternate function" 281 else{
285 " signal multiplex control register not"
286 " mapped!\n");
287 else
288 /* P1021 has pins muxed for QE and other functions. To 282 /* P1021 has pins muxed for QE and other functions. To
289 * enable QE UEC mode, we need to set bit QE0 for UCC1 283 * enable QE UEC mode, we need to set bit QE0 for UCC1
290 * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9 284 * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
291 * and QE12 for QE MII management signals in PMUXCR 285 * and QE12 for QE MII management signals in PMUXCR
292 * register. 286 * register.
293 */ 287 */
294 setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 | 288 setbits32(&guts->pmuxcr, MPC85xx_PMUXCR_QE(0) |
295 MPC85xx_PMUXCR_QE3 | 289 MPC85xx_PMUXCR_QE(3) |
296 MPC85xx_PMUXCR_QE9 | 290 MPC85xx_PMUXCR_QE(9) |
297 MPC85xx_PMUXCR_QE12); 291 MPC85xx_PMUXCR_QE(12));
298 292 iounmap(guts);
293 }
299 of_node_put(np); 294 of_node_put(np);
300 } 295 }
301 296
@@ -434,9 +429,8 @@ machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
434 429
435static void __init mpc85xx_mds_pic_init(void) 430static void __init mpc85xx_mds_pic_init(void)
436{ 431{
437 struct mpic *mpic = mpic_alloc(NULL, 0, 432 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
438 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | 433 MPIC_SINGLE_DEST_CPU,
439 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
440 0, 256, " OpenPIC "); 434 0, 256, " OpenPIC ");
441 BUG_ON(mpic == NULL); 435 BUG_ON(mpic == NULL);
442 436
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index ccf520e890be..db214cd4c822 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * MPC85xx RDB Board Setup 2 * MPC85xx RDB Board Setup
3 * 3 *
4 * Copyright 2009 Freescale Semiconductor Inc. 4 * Copyright 2009,2012 Freescale Semiconductor Inc.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -26,6 +26,9 @@
26#include <asm/prom.h> 26#include <asm/prom.h>
27#include <asm/udbg.h> 27#include <asm/udbg.h>
28#include <asm/mpic.h> 28#include <asm/mpic.h>
29#include <asm/qe.h>
30#include <asm/qe_ic.h>
31#include <asm/fsl_guts.h>
29 32
30#include <sysdev/fsl_soc.h> 33#include <sysdev/fsl_soc.h>
31#include <sysdev/fsl_pci.h> 34#include <sysdev/fsl_pci.h>
@@ -47,21 +50,36 @@ void __init mpc85xx_rdb_pic_init(void)
47 struct mpic *mpic; 50 struct mpic *mpic;
48 unsigned long root = of_get_flat_dt_root(); 51 unsigned long root = of_get_flat_dt_root();
49 52
53#ifdef CONFIG_QUICC_ENGINE
54 struct device_node *np;
55#endif
56
50 if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) { 57 if (of_flat_dt_is_compatible(root, "fsl,MPC85XXRDB-CAMP")) {
51 mpic = mpic_alloc(NULL, 0, 58 mpic = mpic_alloc(NULL, 0, MPIC_NO_RESET |
52 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | 59 MPIC_BIG_ENDIAN |
53 MPIC_SINGLE_DEST_CPU, 60 MPIC_SINGLE_DEST_CPU,
54 0, 256, " OpenPIC "); 61 0, 256, " OpenPIC ");
55 } else { 62 } else {
56 mpic = mpic_alloc(NULL, 0, 63 mpic = mpic_alloc(NULL, 0,
57 MPIC_WANTS_RESET | 64 MPIC_BIG_ENDIAN |
58 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
59 MPIC_SINGLE_DEST_CPU, 65 MPIC_SINGLE_DEST_CPU,
60 0, 256, " OpenPIC "); 66 0, 256, " OpenPIC ");
61 } 67 }
62 68
63 BUG_ON(mpic == NULL); 69 BUG_ON(mpic == NULL);
64 mpic_init(mpic); 70 mpic_init(mpic);
71
72#ifdef CONFIG_QUICC_ENGINE
73 np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
74 if (np) {
75 qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
76 qe_ic_cascade_high_mpic);
77 of_node_put(np);
78
79 } else
80 pr_err("%s: Could not find qe-ic node\n", __func__);
81#endif
82
65} 83}
66 84
67/* 85/*
@@ -69,7 +87,7 @@ void __init mpc85xx_rdb_pic_init(void)
69 */ 87 */
70static void __init mpc85xx_rdb_setup_arch(void) 88static void __init mpc85xx_rdb_setup_arch(void)
71{ 89{
72#ifdef CONFIG_PCI 90#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
73 struct device_node *np; 91 struct device_node *np;
74#endif 92#endif
75 93
@@ -85,11 +103,73 @@ static void __init mpc85xx_rdb_setup_arch(void)
85#endif 103#endif
86 104
87 mpc85xx_smp_init(); 105 mpc85xx_smp_init();
106
107#ifdef CONFIG_QUICC_ENGINE
108 np = of_find_compatible_node(NULL, NULL, "fsl,qe");
109 if (!np) {
110 pr_err("%s: Could not find Quicc Engine node\n", __func__);
111 goto qe_fail;
112 }
113
114 qe_reset();
115 of_node_put(np);
116
117 np = of_find_node_by_name(NULL, "par_io");
118 if (np) {
119 struct device_node *ucc;
120
121 par_io_init(np);
122 of_node_put(np);
123
124 for_each_node_by_name(ucc, "ucc")
125 par_io_of_config(ucc);
126
127 }
128#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
129 if (machine_is(p1025_rdb)) {
130
131 struct ccsr_guts_85xx __iomem *guts;
132
133 np = of_find_node_by_name(NULL, "global-utilities");
134 if (np) {
135 guts = of_iomap(np, 0);
136 if (!guts) {
137
138 pr_err("mpc85xx-rdb: could not map global utilities register\n");
139
140 } else {
141 /* P1025 has pins muxed for QE and other functions. To
142 * enable QE UEC mode, we need to set bit QE0 for UCC1
143 * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
144 * and QE12 for QE MII management singals in PMUXCR
145 * register.
146 */
147 setbits32(&guts->pmuxcr, MPC85xx_PMUXCR_QE(0) |
148 MPC85xx_PMUXCR_QE(3) |
149 MPC85xx_PMUXCR_QE(9) |
150 MPC85xx_PMUXCR_QE(12));
151 iounmap(guts);
152 }
153 of_node_put(np);
154 }
155
156 }
157#endif
158
159qe_fail:
160#endif /* CONFIG_QUICC_ENGINE */
161
88 printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n"); 162 printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
89} 163}
90 164
91machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices); 165machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices);
166machine_device_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
167machine_device_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
92machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices); 168machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices);
169machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
170machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
171machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
172machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
93 173
94/* 174/*
95 * Called very early, device-tree isn't unflattened 175 * Called very early, device-tree isn't unflattened
@@ -112,6 +192,52 @@ static int __init p1020_rdb_probe(void)
112 return 0; 192 return 0;
113} 193}
114 194
195static int __init p1020_rdb_pc_probe(void)
196{
197 unsigned long root = of_get_flat_dt_root();
198
199 return of_flat_dt_is_compatible(root, "fsl,P1020RDB-PC");
200}
201
202static int __init p1021_rdb_pc_probe(void)
203{
204 unsigned long root = of_get_flat_dt_root();
205
206 if (of_flat_dt_is_compatible(root, "fsl,P1021RDB-PC"))
207 return 1;
208 return 0;
209}
210
211static int __init p2020_rdb_pc_probe(void)
212{
213 unsigned long root = of_get_flat_dt_root();
214
215 if (of_flat_dt_is_compatible(root, "fsl,P2020RDB-PC"))
216 return 1;
217 return 0;
218}
219
220static int __init p1025_rdb_probe(void)
221{
222 unsigned long root = of_get_flat_dt_root();
223
224 return of_flat_dt_is_compatible(root, "fsl,P1025RDB");
225}
226
227static int __init p1020_mbg_pc_probe(void)
228{
229 unsigned long root = of_get_flat_dt_root();
230
231 return of_flat_dt_is_compatible(root, "fsl,P1020MBG-PC");
232}
233
234static int __init p1020_utm_pc_probe(void)
235{
236 unsigned long root = of_get_flat_dt_root();
237
238 return of_flat_dt_is_compatible(root, "fsl,P1020UTM-PC");
239}
240
115define_machine(p2020_rdb) { 241define_machine(p2020_rdb) {
116 .name = "P2020 RDB", 242 .name = "P2020 RDB",
117 .probe = p2020_rdb_probe, 243 .probe = p2020_rdb_probe,
@@ -139,3 +265,87 @@ define_machine(p1020_rdb) {
139 .calibrate_decr = generic_calibrate_decr, 265 .calibrate_decr = generic_calibrate_decr,
140 .progress = udbg_progress, 266 .progress = udbg_progress,
141}; 267};
268
269define_machine(p1021_rdb_pc) {
270 .name = "P1021 RDB-PC",
271 .probe = p1021_rdb_pc_probe,
272 .setup_arch = mpc85xx_rdb_setup_arch,
273 .init_IRQ = mpc85xx_rdb_pic_init,
274#ifdef CONFIG_PCI
275 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
276#endif
277 .get_irq = mpic_get_irq,
278 .restart = fsl_rstcr_restart,
279 .calibrate_decr = generic_calibrate_decr,
280 .progress = udbg_progress,
281};
282
283define_machine(p2020_rdb_pc) {
284 .name = "P2020RDB-PC",
285 .probe = p2020_rdb_pc_probe,
286 .setup_arch = mpc85xx_rdb_setup_arch,
287 .init_IRQ = mpc85xx_rdb_pic_init,
288#ifdef CONFIG_PCI
289 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
290#endif
291 .get_irq = mpic_get_irq,
292 .restart = fsl_rstcr_restart,
293 .calibrate_decr = generic_calibrate_decr,
294 .progress = udbg_progress,
295};
296
297define_machine(p1025_rdb) {
298 .name = "P1025 RDB",
299 .probe = p1025_rdb_probe,
300 .setup_arch = mpc85xx_rdb_setup_arch,
301 .init_IRQ = mpc85xx_rdb_pic_init,
302#ifdef CONFIG_PCI
303 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
304#endif
305 .get_irq = mpic_get_irq,
306 .restart = fsl_rstcr_restart,
307 .calibrate_decr = generic_calibrate_decr,
308 .progress = udbg_progress,
309};
310
311define_machine(p1020_mbg_pc) {
312 .name = "P1020 MBG-PC",
313 .probe = p1020_mbg_pc_probe,
314 .setup_arch = mpc85xx_rdb_setup_arch,
315 .init_IRQ = mpc85xx_rdb_pic_init,
316#ifdef CONFIG_PCI
317 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
318#endif
319 .get_irq = mpic_get_irq,
320 .restart = fsl_rstcr_restart,
321 .calibrate_decr = generic_calibrate_decr,
322 .progress = udbg_progress,
323};
324
325define_machine(p1020_utm_pc) {
326 .name = "P1020 UTM-PC",
327 .probe = p1020_utm_pc_probe,
328 .setup_arch = mpc85xx_rdb_setup_arch,
329 .init_IRQ = mpc85xx_rdb_pic_init,
330#ifdef CONFIG_PCI
331 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
332#endif
333 .get_irq = mpic_get_irq,
334 .restart = fsl_rstcr_restart,
335 .calibrate_decr = generic_calibrate_decr,
336 .progress = udbg_progress,
337};
338
339define_machine(p1020_rdb_pc) {
340 .name = "P1020RDB-PC",
341 .probe = p1020_rdb_pc_probe,
342 .setup_arch = mpc85xx_rdb_setup_arch,
343 .init_IRQ = mpc85xx_rdb_pic_init,
344#ifdef CONFIG_PCI
345 .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
346#endif
347 .get_irq = mpic_get_irq,
348 .restart = fsl_rstcr_restart,
349 .calibrate_decr = generic_calibrate_decr,
350 .progress = udbg_progress,
351};
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index 538bc3f57e9d..d8bd6563d9ca 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -32,9 +32,8 @@
32 32
33void __init p1010_rdb_pic_init(void) 33void __init p1010_rdb_pic_init(void)
34{ 34{
35 struct mpic *mpic = mpic_alloc(NULL, 0, 35 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
36 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | 36 MPIC_SINGLE_DEST_CPU,
37 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
38 0, 256, " OpenPIC "); 37 0, 256, " OpenPIC ");
39 38
40 BUG_ON(mpic == NULL); 39 BUG_ON(mpic == NULL);
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index b0984ada3f83..0fe88e39945e 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -33,6 +33,10 @@
33 33
34#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 34#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
35 35
36#define PMUXCR_ELBCDIU_MASK 0xc0000000
37#define PMUXCR_ELBCDIU_NOR16 0x80000000
38#define PMUXCR_ELBCDIU_DIU 0x40000000
39
36/* 40/*
37 * Board-specific initialization of the DIU. This code should probably be 41 * Board-specific initialization of the DIU. This code should probably be
38 * executed when the DIU is opened, rather than in arch code, but the DIU 42 * executed when the DIU is opened, rather than in arch code, but the DIU
@@ -50,11 +54,22 @@
50#define CLKDVDR_PXCLK_MASK 0x00FF0000 54#define CLKDVDR_PXCLK_MASK 0x00FF0000
51 55
52/* Some ngPIXIS register definitions */ 56/* Some ngPIXIS register definitions */
57#define PX_CTL 3
58#define PX_BRDCFG0 8
59#define PX_BRDCFG1 9
60
61#define PX_BRDCFG0_ELBC_SPI_MASK 0xc0
62#define PX_BRDCFG0_ELBC_SPI_ELBC 0x00
63#define PX_BRDCFG0_ELBC_SPI_NULL 0xc0
64#define PX_BRDCFG0_ELBC_DIU 0x02
65
53#define PX_BRDCFG1_DVIEN 0x80 66#define PX_BRDCFG1_DVIEN 0x80
54#define PX_BRDCFG1_DFPEN 0x40 67#define PX_BRDCFG1_DFPEN 0x40
55#define PX_BRDCFG1_BACKLIGHT 0x20 68#define PX_BRDCFG1_BACKLIGHT 0x20
56#define PX_BRDCFG1_DDCEN 0x10 69#define PX_BRDCFG1_DDCEN 0x10
57 70
71#define PX_CTL_ALTACC 0x80
72
58/* 73/*
59 * DIU Area Descriptor 74 * DIU Area Descriptor
60 * 75 *
@@ -133,44 +148,117 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
133 */ 148 */
134static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) 149static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
135{ 150{
136 struct device_node *np; 151 struct device_node *guts_node;
137 void __iomem *pixis; 152 struct device_node *indirect_node = NULL;
138 u8 __iomem *brdcfg1; 153 struct ccsr_guts_85xx __iomem *guts;
139 154 u8 __iomem *lbc_lcs0_ba = NULL;
140 np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); 155 u8 __iomem *lbc_lcs1_ba = NULL;
141 if (!np) 156 u8 b;
142 /* older device trees used "fsl,p1022ds-pixis" */ 157
143 np = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis"); 158 /* Map the global utilities registers. */
144 if (!np) { 159 guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
145 pr_err("p1022ds: missing ngPIXIS node\n"); 160 if (!guts_node) {
161 pr_err("p1022ds: missing global utilties device node\n");
146 return; 162 return;
147 } 163 }
148 164
149 pixis = of_iomap(np, 0); 165 guts = of_iomap(guts_node, 0);
150 if (!pixis) { 166 if (!guts) {
151 pr_err("p1022ds: could not map ngPIXIS registers\n"); 167 pr_err("p1022ds: could not map global utilties device\n");
152 return; 168 goto exit;
153 } 169 }
154 brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */ 170
171 indirect_node = of_find_compatible_node(NULL, NULL,
172 "fsl,p1022ds-indirect-pixis");
173 if (!indirect_node) {
174 pr_err("p1022ds: missing pixis indirect mode node\n");
175 goto exit;
176 }
177
178 lbc_lcs0_ba = of_iomap(indirect_node, 0);
179 if (!lbc_lcs0_ba) {
180 pr_err("p1022ds: could not map localbus chip select 0\n");
181 goto exit;
182 }
183
184 lbc_lcs1_ba = of_iomap(indirect_node, 1);
185 if (!lbc_lcs1_ba) {
186 pr_err("p1022ds: could not map localbus chip select 1\n");
187 goto exit;
188 }
189
190 /* Make sure we're in indirect mode first. */
191 if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
192 PMUXCR_ELBCDIU_DIU) {
193 struct device_node *pixis_node;
194 void __iomem *pixis;
195
196 pixis_node =
197 of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
198 if (!pixis_node) {
199 pr_err("p1022ds: missing pixis node\n");
200 goto exit;
201 }
202
203 pixis = of_iomap(pixis_node, 0);
204 of_node_put(pixis_node);
205 if (!pixis) {
206 pr_err("p1022ds: could not map pixis registers\n");
207 goto exit;
208 }
209
210 /* Enable indirect PIXIS mode. */
211 setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
212 iounmap(pixis);
213
214 /* Switch the board mux to the DIU */
215 out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */
216 b = in_8(lbc_lcs1_ba);
217 b |= PX_BRDCFG0_ELBC_DIU;
218 out_8(lbc_lcs1_ba, b);
219
220 /* Set the chip mux to DIU mode. */
221 clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
222 PMUXCR_ELBCDIU_DIU);
223 in_be32(&guts->pmuxcr);
224 }
225
155 226
156 switch (port) { 227 switch (port) {
157 case FSL_DIU_PORT_DVI: 228 case FSL_DIU_PORT_DVI:
158 printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
159 /* Enable the DVI port, disable the DFP and the backlight */ 229 /* Enable the DVI port, disable the DFP and the backlight */
160 clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT, 230 out_8(lbc_lcs0_ba, PX_BRDCFG1);
161 PX_BRDCFG1_DVIEN); 231 b = in_8(lbc_lcs1_ba);
232 b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
233 b |= PX_BRDCFG1_DVIEN;
234 out_8(lbc_lcs1_ba, b);
162 break; 235 break;
163 case FSL_DIU_PORT_LVDS: 236 case FSL_DIU_PORT_LVDS:
164 printk(KERN_INFO "%s:%u\n", __func__, __LINE__); 237 /*
238 * LVDS also needs backlight enabled, otherwise the display
239 * will be blank.
240 */
165 /* Enable the DFP port, disable the DVI and the backlight */ 241 /* Enable the DFP port, disable the DVI and the backlight */
166 clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT, 242 out_8(lbc_lcs0_ba, PX_BRDCFG1);
167 PX_BRDCFG1_DFPEN); 243 b = in_8(lbc_lcs1_ba);
244 b &= ~PX_BRDCFG1_DVIEN;
245 b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
246 out_8(lbc_lcs1_ba, b);
168 break; 247 break;
169 default: 248 default:
170 pr_err("p1022ds: unsupported monitor port %i\n", port); 249 pr_err("p1022ds: unsupported monitor port %i\n", port);
171 } 250 }
172 251
173 iounmap(pixis); 252exit:
253 if (lbc_lcs1_ba)
254 iounmap(lbc_lcs1_ba);
255 if (lbc_lcs0_ba)
256 iounmap(lbc_lcs0_ba);
257 if (guts)
258 iounmap(guts);
259
260 of_node_put(indirect_node);
261 of_node_put(guts_node);
174} 262}
175 263
176/** 264/**
@@ -242,15 +330,56 @@ p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
242 330
243void __init p1022_ds_pic_init(void) 331void __init p1022_ds_pic_init(void)
244{ 332{
245 struct mpic *mpic = mpic_alloc(NULL, 0, 333 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
246 MPIC_WANTS_RESET |
247 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
248 MPIC_SINGLE_DEST_CPU, 334 MPIC_SINGLE_DEST_CPU,
249 0, 256, " OpenPIC "); 335 0, 256, " OpenPIC ");
250 BUG_ON(mpic == NULL); 336 BUG_ON(mpic == NULL);
251 mpic_init(mpic); 337 mpic_init(mpic);
252} 338}
253 339
340#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
341
342/*
343 * Disables a node in the device tree.
344 *
345 * This function is called before kmalloc() is available, so the 'new' object
346 * should be allocated in the global area. The easiest way is to do that is
347 * to allocate one static local variable for each call to this function.
348 */
349static void __init disable_one_node(struct device_node *np, struct property *new)
350{
351 struct property *old;
352
353 old = of_find_property(np, new->name, NULL);
354 if (old)
355 prom_update_property(np, new, old);
356 else
357 prom_add_property(np, new);
358}
359
360/* TRUE if there is a "video=fslfb" command-line parameter. */
361static bool fslfb;
362
363/*
364 * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to
365 * true if we find it.
366 *
367 * We need to use early_param() instead of __setup() because the normal
368 * __setup() gets called to late. However, early_param() gets called very
369 * early, before the device tree is unflattened, so all we can do now is set a
370 * global variable. Later on, p1022_ds_setup_arch() will use that variable
371 * to determine if we need to update the device tree.
372 */
373static int __init early_video_setup(char *options)
374{
375 fslfb = (strncmp(options, "fslfb:", 6) == 0);
376
377 return 0;
378}
379early_param("video", early_video_setup);
380
381#endif
382
254/* 383/*
255 * Setup the architecture 384 * Setup the architecture
256 */ 385 */
@@ -288,6 +417,34 @@ static void __init p1022_ds_setup_arch(void)
288 diu_ops.set_monitor_port = p1022ds_set_monitor_port; 417 diu_ops.set_monitor_port = p1022ds_set_monitor_port;
289 diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; 418 diu_ops.set_pixel_clock = p1022ds_set_pixel_clock;
290 diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; 419 diu_ops.valid_monitor_port = p1022ds_valid_monitor_port;
420
421 /*
422 * Disable the NOR flash node if there is video=fslfb... command-line
423 * parameter. When the DIU is active, NOR flash is unavailable, so we
424 * have to disable the node before the MTD driver loads.
425 */
426 if (fslfb) {
427 struct device_node *np =
428 of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
429
430 if (np) {
431 np = of_find_compatible_node(np, NULL, "cfi-flash");
432 if (np) {
433 static struct property nor_status = {
434 .name = "status",
435 .value = "disabled",
436 .length = sizeof("disabled"),
437 };
438
439 pr_info("p1022ds: disabling %s node",
440 np->full_name);
441 disable_one_node(np, &nor_status);
442 of_node_put(np);
443 }
444 }
445
446 }
447
291#endif 448#endif
292 449
293 mpc85xx_smp_init(); 450 mpc85xx_smp_init();
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
index d951e7027bb6..6b07398e4369 100644
--- a/arch/powerpc/platforms/85xx/p1023_rds.c
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -93,9 +93,8 @@ machine_device_initcall(p1023_rds, mpc85xx_common_publish_devices);
93 93
94static void __init mpc85xx_rds_pic_init(void) 94static void __init mpc85xx_rds_pic_init(void)
95{ 95{
96 struct mpic *mpic = mpic_alloc(NULL, 0, 96 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
97 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | 97 MPIC_SINGLE_DEST_CPU,
98 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
99 0, 256, " OpenPIC "); 98 0, 256, " OpenPIC ");
100 99
101 BUG_ON(mpic == NULL); 100 BUG_ON(mpic == NULL);
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index 184a50784617..1677b8a22677 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -54,8 +54,7 @@ static int sbc_rev;
54 54
55static void __init sbc8548_pic_init(void) 55static void __init sbc8548_pic_init(void)
56{ 56{
57 struct mpic *mpic = mpic_alloc(NULL, 0, 57 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
58 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
59 0, 256, " OpenPIC "); 58 0, 256, " OpenPIC ");
60 BUG_ON(mpic == NULL); 59 BUG_ON(mpic == NULL);
61 mpic_init(mpic); 60 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index 940752e93051..3c3bbcc27566 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -41,8 +41,7 @@
41 41
42static void __init sbc8560_pic_init(void) 42static void __init sbc8560_pic_init(void)
43{ 43{
44 struct mpic *mpic = mpic_alloc(NULL, 0, 44 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
45 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
46 0, 256, " OpenPIC "); 45 0, 256, " OpenPIC ");
47 BUG_ON(mpic == NULL); 46 BUG_ON(mpic == NULL);
48 mpic_init(mpic); 47 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index 18f635906b27..b71919217756 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -48,8 +48,7 @@ static void __init socrates_pic_init(void)
48{ 48{
49 struct device_node *np; 49 struct device_node *np;
50 50
51 struct mpic *mpic = mpic_alloc(NULL, 0, 51 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
52 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
53 0, 256, " OpenPIC "); 52 0, 256, " OpenPIC ");
54 BUG_ON(mpic == NULL); 53 BUG_ON(mpic == NULL);
55 mpic_init(mpic); 54 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index e9e5234b4e76..27ca3a7b04ab 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -48,8 +48,7 @@
48 48
49static void __init stx_gp3_pic_init(void) 49static void __init stx_gp3_pic_init(void)
50{ 50{
51 struct mpic *mpic = mpic_alloc(NULL, 0, 51 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
52 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
53 0, 256, " OpenPIC "); 52 0, 256, " OpenPIC ");
54 BUG_ON(mpic == NULL); 53 BUG_ON(mpic == NULL);
55 mpic_init(mpic); 54 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index bf7c89fb75bb..d7504cefe016 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -47,7 +47,7 @@
47static void __init tqm85xx_pic_init(void) 47static void __init tqm85xx_pic_init(void)
48{ 48{
49 struct mpic *mpic = mpic_alloc(NULL, 0, 49 struct mpic *mpic = mpic_alloc(NULL, 0,
50 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, 50 MPIC_BIG_ENDIAN,
51 0, 256, " OpenPIC "); 51 0, 256, " OpenPIC ");
52 BUG_ON(mpic == NULL); 52 BUG_ON(mpic == NULL);
53 mpic_init(mpic); 53 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 3a69f8b77de6..503c21596c63 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -43,9 +43,7 @@
43 43
44void __init xes_mpc85xx_pic_init(void) 44void __init xes_mpc85xx_pic_init(void)
45{ 45{
46 struct mpic *mpic = mpic_alloc(NULL, 0, 46 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
47 MPIC_WANTS_RESET |
48 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
49 0, 256, " OpenPIC "); 47 0, 256, " OpenPIC ");
50 BUG_ON(mpic == NULL); 48 BUG_ON(mpic == NULL);
51 mpic_init(mpic); 49 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 8d6599d54ea6..7a6279e38213 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -39,6 +39,7 @@ config GEF_PPC9A
39 select MMIO_NVRAM 39 select MMIO_NVRAM
40 select GENERIC_GPIO 40 select GENERIC_GPIO
41 select ARCH_REQUIRE_GPIOLIB 41 select ARCH_REQUIRE_GPIOLIB
42 select GE_FPGA
42 help 43 help
43 This option enables support for the GE PPC9A. 44 This option enables support for the GE PPC9A.
44 45
@@ -48,6 +49,7 @@ config GEF_SBC310
48 select MMIO_NVRAM 49 select MMIO_NVRAM
49 select GENERIC_GPIO 50 select GENERIC_GPIO
50 select ARCH_REQUIRE_GPIOLIB 51 select ARCH_REQUIRE_GPIOLIB
52 select GE_FPGA
51 help 53 help
52 This option enables support for the GE SBC310. 54 This option enables support for the GE SBC310.
53 55
@@ -57,6 +59,7 @@ config GEF_SBC610
57 select MMIO_NVRAM 59 select MMIO_NVRAM
58 select GENERIC_GPIO 60 select GENERIC_GPIO
59 select ARCH_REQUIRE_GPIOLIB 61 select ARCH_REQUIRE_GPIOLIB
62 select GE_FPGA
60 select HAS_RAPIDIO 63 select HAS_RAPIDIO
61 help 64 help
62 This option enables support for the GE SBC610. 65 This option enables support for the GE SBC610.
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 4b0d7b1aa005..ede815d6489d 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o
7obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o 7obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
8obj-$(CONFIG_SBC8641D) += sbc8641d.o 8obj-$(CONFIG_SBC8641D) += sbc8641d.o
9obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o 9obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
10gef-gpio-$(CONFIG_GPIOLIB) += gef_gpio.o 10obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o
11obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o gef_pic.o $(gef-gpio-y) 11obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o
12obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o gef_pic.o $(gef-gpio-y) 12obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o
13obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o gef_pic.o $(gef-gpio-y)
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index 60ce07e39100..ed58b6cfd60c 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -37,9 +37,9 @@
37 37
38#include <sysdev/fsl_pci.h> 38#include <sysdev/fsl_pci.h>
39#include <sysdev/fsl_soc.h> 39#include <sysdev/fsl_soc.h>
40#include <sysdev/ge/ge_pic.h>
40 41
41#include "mpc86xx.h" 42#include "mpc86xx.h"
42#include "gef_pic.h"
43 43
44#undef DEBUG 44#undef DEBUG
45 45
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index 3ecee25bf3ed..710db69bd523 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -37,9 +37,9 @@
37 37
38#include <sysdev/fsl_pci.h> 38#include <sysdev/fsl_pci.h>
39#include <sysdev/fsl_soc.h> 39#include <sysdev/fsl_soc.h>
40#include <sysdev/ge/ge_pic.h>
40 41
41#include "mpc86xx.h" 42#include "mpc86xx.h"
42#include "gef_pic.h"
43 43
44#undef DEBUG 44#undef DEBUG
45 45
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index 5090d608d9ee..4a13d2f4ac20 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -37,9 +37,9 @@
37 37
38#include <sysdev/fsl_pci.h> 38#include <sysdev/fsl_pci.h>
39#include <sysdev/fsl_soc.h> 39#include <sysdev/fsl_soc.h>
40#include <sysdev/ge/ge_pic.h>
40 41
41#include "mpc86xx.h" 42#include "mpc86xx.h"
42#include "gef_pic.h"
43 43
44#undef DEBUG 44#undef DEBUG
45 45
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c
index 52bbfa031531..22cc3571ae19 100644
--- a/arch/powerpc/platforms/86xx/pic.c
+++ b/arch/powerpc/platforms/86xx/pic.c
@@ -37,9 +37,8 @@ void __init mpc86xx_init_irq(void)
37 int cascade_irq; 37 int cascade_irq;
38#endif 38#endif
39 39
40 struct mpic *mpic = mpic_alloc(NULL, 0, 40 struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
41 MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | 41 MPIC_SINGLE_DEST_CPU,
42 MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
43 0, 256, " MPIC "); 42 0, 256, " MPIC ");
44 BUG_ON(mpic == NULL); 43 BUG_ON(mpic == NULL);
45 44
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 0cfb46d54b8c..a35ca44ade66 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -2,7 +2,6 @@ menu "Platform support"
2 2
3source "arch/powerpc/platforms/powernv/Kconfig" 3source "arch/powerpc/platforms/powernv/Kconfig"
4source "arch/powerpc/platforms/pseries/Kconfig" 4source "arch/powerpc/platforms/pseries/Kconfig"
5source "arch/powerpc/platforms/iseries/Kconfig"
6source "arch/powerpc/platforms/chrp/Kconfig" 5source "arch/powerpc/platforms/chrp/Kconfig"
7source "arch/powerpc/platforms/512x/Kconfig" 6source "arch/powerpc/platforms/512x/Kconfig"
8source "arch/powerpc/platforms/52xx/Kconfig" 7source "arch/powerpc/platforms/52xx/Kconfig"
@@ -87,6 +86,14 @@ config MPIC_WEIRD
87 bool 86 bool
88 default n 87 default n
89 88
89config MPIC_MSGR
90 bool "MPIC message register support"
91 depends on MPIC
92 default n
93 help
94 Enables support for the MPIC message registers. These
95 registers are used for inter-processor communication.
96
90config PPC_I8259 97config PPC_I8259
91 bool 98 bool
92 default n 99 default n
@@ -138,7 +145,7 @@ config MPIC_BROKEN_REGREAD
138 of the register contents in software. 145 of the register contents in software.
139 146
140config IBMVIO 147config IBMVIO
141 depends on PPC_PSERIES || PPC_ISERIES 148 depends on PPC_PSERIES
142 bool 149 bool
143 default y 150 default y
144 151
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 2635a22bade2..879b4a448498 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_FSL_SOC_BOOKE) += 85xx/
16obj-$(CONFIG_PPC_86xx) += 86xx/ 16obj-$(CONFIG_PPC_86xx) += 86xx/
17obj-$(CONFIG_PPC_POWERNV) += powernv/ 17obj-$(CONFIG_PPC_POWERNV) += powernv/
18obj-$(CONFIG_PPC_PSERIES) += pseries/ 18obj-$(CONFIG_PPC_PSERIES) += pseries/
19obj-$(CONFIG_PPC_ISERIES) += iseries/
20obj-$(CONFIG_PPC_MAPLE) += maple/ 19obj-$(CONFIG_PPC_MAPLE) += maple/
21obj-$(CONFIG_PPC_PASEMI) += pasemi/ 20obj-$(CONFIG_PPC_PASEMI) += pasemi/
22obj-$(CONFIG_PPC_CELL) += cell/ 21obj-$(CONFIG_PPC_CELL) += cell/
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 62002a7edfed..fa3e294fd343 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -197,7 +197,8 @@ static void __init mpic_init_IRQ(void)
197 /* The MPIC driver will get everything it needs from the 197 /* The MPIC driver will get everything it needs from the
198 * device-tree, just pass 0 to all arguments 198 * device-tree, just pass 0 to all arguments
199 */ 199 */
200 mpic = mpic_alloc(dn, 0, MPIC_SECONDARY, 0, 0, " MPIC "); 200 mpic = mpic_alloc(dn, 0, MPIC_SECONDARY | MPIC_NO_RESET,
201 0, 0, " MPIC ");
201 if (mpic == NULL) 202 if (mpic == NULL)
202 continue; 203 continue;
203 mpic_init(mpic); 204 mpic_init(mpic);
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 4a3d90e0d426..1d75c92ea8fb 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -646,6 +646,7 @@ long spufs_create(struct path *path, struct dentry *dentry,
646 646
647out: 647out:
648 mutex_unlock(&path->dentry->d_inode->i_mutex); 648 mutex_unlock(&path->dentry->d_inode->i_mutex);
649 dput(dentry);
649 return ret; 650 return ret;
650} 651}
651 652
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 8591bb62d7fc..5665dcc382c7 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -70,8 +70,6 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
70 ret = PTR_ERR(dentry); 70 ret = PTR_ERR(dentry);
71 if (!IS_ERR(dentry)) { 71 if (!IS_ERR(dentry)) {
72 ret = spufs_create(&path, dentry, flags, mode, neighbor); 72 ret = spufs_create(&path, dentry, flags, mode, neighbor);
73 mutex_unlock(&path.dentry->d_inode->i_mutex);
74 dput(dentry);
75 path_put(&path); 73 path_put(&path);
76 } 74 }
77 75
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index f1f17bb2c33c..c665d7de6c99 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -435,7 +435,8 @@ static void __init chrp_find_openpic(void)
435 if (len > 1) 435 if (len > 1)
436 isu_size = iranges[3]; 436 isu_size = iranges[3];
437 437
438 chrp_mpic = mpic_alloc(np, opaddr, 0, isu_size, 0, " MPIC "); 438 chrp_mpic = mpic_alloc(np, opaddr, MPIC_NO_RESET,
439 isu_size, 0, " MPIC ");
439 if (chrp_mpic == NULL) { 440 if (chrp_mpic == NULL) {
440 printk(KERN_ERR "Failed to allocate MPIC structure\n"); 441 printk(KERN_ERR "Failed to allocate MPIC structure\n");
441 goto bail; 442 goto bail;
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index 9cfcf20c0560..ab51b21b4bd7 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -154,11 +154,9 @@ static void __init holly_init_IRQ(void)
154 struct device_node *cascade_node = NULL; 154 struct device_node *cascade_node = NULL;
155#endif 155#endif
156 156
157 mpic = mpic_alloc(NULL, 0, 157 mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
158 MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
159 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, 158 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
160 24, 159 24, 0,
161 NR_IRQS-4, /* num_sources used */
162 "Tsi108_PIC"); 160 "Tsi108_PIC");
163 161
164 BUG_ON(mpic == NULL); 162 BUG_ON(mpic == NULL);
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index bcfad92c9cec..455e7c087422 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -82,8 +82,7 @@ static void __init linkstation_init_IRQ(void)
82{ 82{
83 struct mpic *mpic; 83 struct mpic *mpic;
84 84
85 mpic = mpic_alloc(NULL, 0, MPIC_WANTS_RESET, 85 mpic = mpic_alloc(NULL, 0, 0, 4, 0, " EPIC ");
86 4, 32, " EPIC ");
87 BUG_ON(mpic == NULL); 86 BUG_ON(mpic == NULL);
88 87
89 /* PCI IRQs */ 88 /* PCI IRQs */
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index f3350d786f5b..74ccce36baed 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -108,11 +108,9 @@ static void __init mpc7448_hpc2_init_IRQ(void)
108 struct device_node *cascade_node = NULL; 108 struct device_node *cascade_node = NULL;
109#endif 109#endif
110 110
111 mpic = mpic_alloc(NULL, 0, 111 mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
112 MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
113 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, 112 MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
114 24, 113 24, 0,
115 NR_IRQS-4, /* num_sources used */
116 "Tsi108_PIC"); 114 "Tsi108_PIC");
117 115
118 BUG_ON(mpic == NULL); 116 BUG_ON(mpic == NULL);
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c
index afa638834965..e0ed3c71d69b 100644
--- a/arch/powerpc/platforms/embedded6xx/storcenter.c
+++ b/arch/powerpc/platforms/embedded6xx/storcenter.c
@@ -84,8 +84,7 @@ static void __init storcenter_init_IRQ(void)
84{ 84{
85 struct mpic *mpic; 85 struct mpic *mpic;
86 86
87 mpic = mpic_alloc(NULL, 0, MPIC_WANTS_RESET, 87 mpic = mpic_alloc(NULL, 0, 0, 16, 0, " OpenPIC ");
88 16, 32, " OpenPIC ");
89 BUG_ON(mpic == NULL); 88 BUG_ON(mpic == NULL);
90 89
91 /* 90 /*
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
deleted file mode 100644
index 63835e09e5cc..000000000000
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
1config PPC_ISERIES
2 bool "IBM Legacy iSeries"
3 depends on PPC64 && PPC_BOOK3S
4 select OF_DYNAMIC
5 select PPC_SMP_MUXED_IPI
6 select PPC_INDIRECT_PIO
7 select PPC_INDIRECT_MMIO
8 select PPC_PCI_CHOICE if EXPERT
9
10menu "iSeries device drivers"
11 depends on PPC_ISERIES
12
13config VIODASD
14 tristate "iSeries Virtual I/O disk support"
15 depends on BLOCK
16 select VIOPATH
17 help
18 If you are running on an iSeries system and you want to use
19 virtual disks created and managed by OS/400, say Y.
20
21config VIOCD
22 tristate "iSeries Virtual I/O CD support"
23 depends on BLOCK
24 select VIOPATH
25 help
26 If you are running Linux on an IBM iSeries system and you want to
27 read a CD drive owned by OS/400, say Y here.
28
29config VIOTAPE
30 tristate "iSeries Virtual Tape Support"
31 select VIOPATH
32 help
33 If you are running Linux on an iSeries system and you want Linux
34 to read and/or write a tape drive owned by OS/400, say Y here.
35
36endmenu
37
38config VIOPATH
39 bool
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
deleted file mode 100644
index a7602b11ed9d..000000000000
--- a/arch/powerpc/platforms/iseries/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
1ccflags-y := -mno-minimal-toc
2
3obj-y += exception.o
4obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
5 hvcall.o proc.o htab.o iommu.o misc.o irq.o
6obj-$(CONFIG_PCI) += pci.o
7obj-$(CONFIG_SMP) += smp.o
8obj-$(CONFIG_VIOPATH) += viopath.o vio.o
9obj-$(CONFIG_MODULES) += ksyms.o
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h
deleted file mode 100644
index 8d95fe4b554e..000000000000
--- a/arch/powerpc/platforms/iseries/call_hpt.h
+++ /dev/null
@@ -1,102 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _PLATFORMS_ISERIES_CALL_HPT_H
19#define _PLATFORMS_ISERIES_CALL_HPT_H
20
21/*
22 * This file contains the "hypervisor call" interface which is used to
23 * drive the hypervisor from the OS.
24 */
25
26#include <asm/iseries/hv_call_sc.h>
27#include <asm/iseries/hv_types.h>
28#include <asm/mmu.h>
29
30#define HvCallHptGetHptAddress HvCallHpt + 0
31#define HvCallHptGetHptPages HvCallHpt + 1
32#define HvCallHptSetPp HvCallHpt + 5
33#define HvCallHptSetSwBits HvCallHpt + 6
34#define HvCallHptUpdate HvCallHpt + 7
35#define HvCallHptInvalidateNoSyncICache HvCallHpt + 8
36#define HvCallHptGet HvCallHpt + 11
37#define HvCallHptFindNextValid HvCallHpt + 12
38#define HvCallHptFindValid HvCallHpt + 13
39#define HvCallHptAddValidate HvCallHpt + 16
40#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
41
42
43static inline u64 HvCallHpt_getHptAddress(void)
44{
45 return HvCall0(HvCallHptGetHptAddress);
46}
47
48static inline u64 HvCallHpt_getHptPages(void)
49{
50 return HvCall0(HvCallHptGetHptPages);
51}
52
53static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
54{
55 HvCall2(HvCallHptSetPp, hpteIndex, value);
56}
57
58static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
59{
60 HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
61}
62
63static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
64{
65 HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
66}
67
68static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
69 u8 bitsoff)
70{
71 u64 compressedStatus;
72
73 compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
74 hpteIndex, bitson, bitsoff, 1);
75 HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
76 return compressedStatus;
77}
78
79static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn)
80{
81 return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
82}
83
84static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex,
85 u8 bitson, u8 bitsoff)
86{
87 return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
88 bitson, bitsoff);
89}
90
91static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex)
92{
93 HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
94}
95
96static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit,
97 struct hash_pte *hpte)
98{
99 HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r);
100}
101
102#endif /* _PLATFORMS_ISERIES_CALL_HPT_H */
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
deleted file mode 100644
index dbdf69850ed9..000000000000
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ /dev/null
@@ -1,309 +0,0 @@
1/*
2 * Provides the Hypervisor PCI calls for iSeries Linux Parition.
3 * Copyright (C) 2001 <Wayne G Holm> <IBM Corporation>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the:
17 * Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307 USA
20 *
21 * Change Activity:
22 * Created, Jan 9, 2001
23 */
24
25#ifndef _PLATFORMS_ISERIES_CALL_PCI_H
26#define _PLATFORMS_ISERIES_CALL_PCI_H
27
28#include <asm/iseries/hv_call_sc.h>
29#include <asm/iseries/hv_types.h>
30
31/*
32 * DSA == Direct Select Address
33 * this struct must be 64 bits in total
34 */
35struct HvCallPci_DsaAddr {
36 u16 busNumber; /* PHB index? */
37 u8 subBusNumber; /* PCI bus number? */
38 u8 deviceId; /* device and function? */
39 u8 barNumber;
40 u8 reserved[3];
41};
42
43union HvDsaMap {
44 u64 DsaAddr;
45 struct HvCallPci_DsaAddr Dsa;
46};
47
48struct HvCallPci_LoadReturn {
49 u64 rc;
50 u64 value;
51};
52
53enum HvCallPci_DeviceType {
54 HvCallPci_NodeDevice = 1,
55 HvCallPci_SpDevice = 2,
56 HvCallPci_IopDevice = 3,
57 HvCallPci_BridgeDevice = 4,
58 HvCallPci_MultiFunctionDevice = 5,
59 HvCallPci_IoaDevice = 6
60};
61
62
63struct HvCallPci_DeviceInfo {
64 u32 deviceType; /* See DeviceType enum for values */
65};
66
67struct HvCallPci_BusUnitInfo {
68 u32 sizeReturned; /* length of data returned */
69 u32 deviceType; /* see DeviceType enum for values */
70};
71
72struct HvCallPci_BridgeInfo {
73 struct HvCallPci_BusUnitInfo busUnitInfo; /* Generic bus unit info */
74 u8 subBusNumber; /* Bus number of secondary bus */
75 u8 maxAgents; /* Max idsels on secondary bus */
76 u8 maxSubBusNumber; /* Max Sub Bus */
77 u8 logicalSlotNumber; /* Logical Slot Number for IOA */
78};
79
80
81/*
82 * Maximum BusUnitInfo buffer size. Provided for clients so
83 * they can allocate a buffer big enough for any type of bus
84 * unit. Increase as needed.
85 */
86enum {HvCallPci_MaxBusUnitInfoSize = 128};
87
88struct HvCallPci_BarParms {
89 u64 vaddr;
90 u64 raddr;
91 u64 size;
92 u64 protectStart;
93 u64 protectEnd;
94 u64 relocationOffset;
95 u64 pciAddress;
96 u64 reserved[3];
97};
98
99enum HvCallPci_VpdType {
100 HvCallPci_BusVpd = 1,
101 HvCallPci_BusAdapterVpd = 2
102};
103
104#define HvCallPciConfigLoad8 HvCallPci + 0
105#define HvCallPciConfigLoad16 HvCallPci + 1
106#define HvCallPciConfigLoad32 HvCallPci + 2
107#define HvCallPciConfigStore8 HvCallPci + 3
108#define HvCallPciConfigStore16 HvCallPci + 4
109#define HvCallPciConfigStore32 HvCallPci + 5
110#define HvCallPciEoi HvCallPci + 16
111#define HvCallPciGetBarParms HvCallPci + 18
112#define HvCallPciMaskFisr HvCallPci + 20
113#define HvCallPciUnmaskFisr HvCallPci + 21
114#define HvCallPciSetSlotReset HvCallPci + 25
115#define HvCallPciGetDeviceInfo HvCallPci + 27
116#define HvCallPciGetCardVpd HvCallPci + 28
117#define HvCallPciBarLoad8 HvCallPci + 40
118#define HvCallPciBarLoad16 HvCallPci + 41
119#define HvCallPciBarLoad32 HvCallPci + 42
120#define HvCallPciBarLoad64 HvCallPci + 43
121#define HvCallPciBarStore8 HvCallPci + 44
122#define HvCallPciBarStore16 HvCallPci + 45
123#define HvCallPciBarStore32 HvCallPci + 46
124#define HvCallPciBarStore64 HvCallPci + 47
125#define HvCallPciMaskInterrupts HvCallPci + 48
126#define HvCallPciUnmaskInterrupts HvCallPci + 49
127#define HvCallPciGetBusUnitInfo HvCallPci + 50
128
129static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
130 u8 deviceId, u32 offset, u16 *value)
131{
132 struct HvCallPci_DsaAddr dsa;
133 struct HvCallPci_LoadReturn retVal;
134
135 *((u64*)&dsa) = 0;
136
137 dsa.busNumber = busNumber;
138 dsa.subBusNumber = subBusNumber;
139 dsa.deviceId = deviceId;
140
141 HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
142
143 *value = retVal.value;
144
145 return retVal.rc;
146}
147
148static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
149 u8 deviceId, u32 offset, u32 *value)
150{
151 struct HvCallPci_DsaAddr dsa;
152 struct HvCallPci_LoadReturn retVal;
153
154 *((u64*)&dsa) = 0;
155
156 dsa.busNumber = busNumber;
157 dsa.subBusNumber = subBusNumber;
158 dsa.deviceId = deviceId;
159
160 HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
161
162 *value = retVal.value;
163
164 return retVal.rc;
165}
166
167static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
168 u8 deviceId, u32 offset, u8 value)
169{
170 struct HvCallPci_DsaAddr dsa;
171
172 *((u64*)&dsa) = 0;
173
174 dsa.busNumber = busNumber;
175 dsa.subBusNumber = subBusNumber;
176 dsa.deviceId = deviceId;
177
178 return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
179}
180
181static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
182 u8 deviceIdParm)
183{
184 struct HvCallPci_DsaAddr dsa;
185 struct HvCallPci_LoadReturn retVal;
186
187 *((u64*)&dsa) = 0;
188
189 dsa.busNumber = busNumberParm;
190 dsa.subBusNumber = subBusParm;
191 dsa.deviceId = deviceIdParm;
192
193 HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
194
195 return retVal.rc;
196}
197
198static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
199 u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
200{
201 struct HvCallPci_DsaAddr dsa;
202
203 *((u64*)&dsa) = 0;
204
205 dsa.busNumber = busNumberParm;
206 dsa.subBusNumber = subBusParm;
207 dsa.deviceId = deviceIdParm;
208 dsa.barNumber = barNumberParm;
209
210 return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
211}
212
213static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
214 u8 deviceIdParm, u64 fisrMask)
215{
216 struct HvCallPci_DsaAddr dsa;
217
218 *((u64*)&dsa) = 0;
219
220 dsa.busNumber = busNumberParm;
221 dsa.subBusNumber = subBusParm;
222 dsa.deviceId = deviceIdParm;
223
224 return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
225}
226
227static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
228 u8 deviceIdParm, u64 fisrMask)
229{
230 struct HvCallPci_DsaAddr dsa;
231
232 *((u64*)&dsa) = 0;
233
234 dsa.busNumber = busNumberParm;
235 dsa.subBusNumber = subBusParm;
236 dsa.deviceId = deviceIdParm;
237
238 return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
239}
240
241static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
242 u8 deviceNumberParm, u64 parms, u32 sizeofParms)
243{
244 struct HvCallPci_DsaAddr dsa;
245
246 *((u64*)&dsa) = 0;
247
248 dsa.busNumber = busNumberParm;
249 dsa.subBusNumber = subBusParm;
250 dsa.deviceId = deviceNumberParm << 4;
251
252 return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
253}
254
255static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
256 u8 deviceIdParm, u64 interruptMask)
257{
258 struct HvCallPci_DsaAddr dsa;
259
260 *((u64*)&dsa) = 0;
261
262 dsa.busNumber = busNumberParm;
263 dsa.subBusNumber = subBusParm;
264 dsa.deviceId = deviceIdParm;
265
266 return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
267}
268
269static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
270 u8 deviceIdParm, u64 interruptMask)
271{
272 struct HvCallPci_DsaAddr dsa;
273
274 *((u64*)&dsa) = 0;
275
276 dsa.busNumber = busNumberParm;
277 dsa.subBusNumber = subBusParm;
278 dsa.deviceId = deviceIdParm;
279
280 return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
281}
282
283static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
284 u8 deviceIdParm, u64 parms, u32 sizeofParms)
285{
286 struct HvCallPci_DsaAddr dsa;
287
288 *((u64*)&dsa) = 0;
289
290 dsa.busNumber = busNumberParm;
291 dsa.subBusNumber = subBusParm;
292 dsa.deviceId = deviceIdParm;
293
294 return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
295 sizeofParms);
296}
297
298static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
299 u16 sizeParm)
300{
301 u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
302 sizeParm, HvCallPci_BusVpd);
303 if (xRc == -1)
304 return -1;
305 else
306 return xRc & 0xFFFF;
307}
308
309#endif /* _PLATFORMS_ISERIES_CALL_PCI_H */
diff --git a/arch/powerpc/platforms/iseries/call_sm.h b/arch/powerpc/platforms/iseries/call_sm.h
deleted file mode 100644
index c7e251619f48..000000000000
--- a/arch/powerpc/platforms/iseries/call_sm.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISERIES_CALL_SM_H
19#define _ISERIES_CALL_SM_H
20
21/*
22 * This file contains the "hypervisor call" interface which is used to
23 * drive the hypervisor from the OS.
24 */
25
26#include <asm/iseries/hv_call_sc.h>
27#include <asm/iseries/hv_types.h>
28
29#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
30
31static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
32 u64 indexIntoBitMap)
33{
34 return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
35}
36
37#endif /* _ISERIES_CALL_SM_H */
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
deleted file mode 100644
index f0491cc28900..000000000000
--- a/arch/powerpc/platforms/iseries/dt.c
+++ /dev/null
@@ -1,643 +0,0 @@
1/*
2 * Copyright (C) 2005-2006 Michael Ellerman, IBM Corporation
3 * Copyright (C) 2000-2004, IBM Corporation
4 *
5 * Description:
6 * This file contains all the routines to build a flattened device
7 * tree for a legacy iSeries machine.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#undef DEBUG
16
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/pci.h>
20#include <linux/pci_regs.h>
21#include <linux/pci_ids.h>
22#include <linux/threads.h>
23#include <linux/bitops.h>
24#include <linux/string.h>
25#include <linux/kernel.h>
26#include <linux/if_ether.h> /* ETH_ALEN */
27
28#include <asm/machdep.h>
29#include <asm/prom.h>
30#include <asm/lppaca.h>
31#include <asm/cputable.h>
32#include <asm/abs_addr.h>
33#include <asm/system.h>
34#include <asm/iseries/hv_types.h>
35#include <asm/iseries/hv_lp_config.h>
36#include <asm/iseries/hv_call_xm.h>
37#include <asm/udbg.h>
38
39#include "processor_vpd.h"
40#include "call_hpt.h"
41#include "call_pci.h"
42#include "pci.h"
43#include "it_exp_vpd_panel.h"
44#include "naca.h"
45
46#ifdef DEBUG
47#define DBG(fmt...) udbg_printf(fmt)
48#else
49#define DBG(fmt...)
50#endif
51
52/*
53 * These are created by the linker script at the start and end
54 * of the section containing all the strings marked with the DS macro.
55 */
56extern char __dt_strings_start[];
57extern char __dt_strings_end[];
58
59#define DS(s) ({ \
60 static const char __s[] __attribute__((section(".dt_strings"))) = s; \
61 __s; \
62})
63
64struct iseries_flat_dt {
65 struct boot_param_header header;
66 u64 reserve_map[2];
67};
68
69static void * __initdata dt_data;
70
71/*
72 * Putting these strings here keeps them out of the .dt_strings section
73 * that we capture for the strings blob of the flattened device tree.
74 */
75static char __initdata device_type_cpu[] = "cpu";
76static char __initdata device_type_memory[] = "memory";
77static char __initdata device_type_serial[] = "serial";
78static char __initdata device_type_network[] = "network";
79static char __initdata device_type_pci[] = "pci";
80static char __initdata device_type_vdevice[] = "vdevice";
81static char __initdata device_type_vscsi[] = "vscsi";
82
83
84/* EBCDIC to ASCII conversion routines */
85
86static unsigned char __init e2a(unsigned char x)
87{
88 switch (x) {
89 case 0x81 ... 0x89:
90 return x - 0x81 + 'a';
91 case 0x91 ... 0x99:
92 return x - 0x91 + 'j';
93 case 0xA2 ... 0xA9:
94 return x - 0xA2 + 's';
95 case 0xC1 ... 0xC9:
96 return x - 0xC1 + 'A';
97 case 0xD1 ... 0xD9:
98 return x - 0xD1 + 'J';
99 case 0xE2 ... 0xE9:
100 return x - 0xE2 + 'S';
101 case 0xF0 ... 0xF9:
102 return x - 0xF0 + '0';
103 }
104 return ' ';
105}
106
107static unsigned char * __init strne2a(unsigned char *dest,
108 const unsigned char *src, size_t n)
109{
110 int i;
111
112 n = strnlen(src, n);
113
114 for (i = 0; i < n; i++)
115 dest[i] = e2a(src[i]);
116
117 return dest;
118}
119
120static struct iseries_flat_dt * __init dt_init(void)
121{
122 struct iseries_flat_dt *dt;
123 unsigned long str_len;
124
125 str_len = __dt_strings_end - __dt_strings_start;
126 dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
127 dt->header.off_mem_rsvmap =
128 offsetof(struct iseries_flat_dt, reserve_map);
129 dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
130 dt->header.off_dt_struct = dt->header.off_dt_strings
131 + ALIGN(str_len, 8);
132 dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
133 dt->header.dt_strings_size = str_len;
134
135 /* There is no notion of hardware cpu id on iSeries */
136 dt->header.boot_cpuid_phys = smp_processor_id();
137
138 memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
139 str_len);
140
141 dt->header.magic = OF_DT_HEADER;
142 dt->header.version = 0x10;
143 dt->header.last_comp_version = 0x10;
144
145 dt->reserve_map[0] = 0;
146 dt->reserve_map[1] = 0;
147
148 return dt;
149}
150
151static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
152{
153 *((u32 *)dt_data) = value;
154 dt_data += sizeof(u32);
155}
156
157#ifdef notyet
158static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
159{
160 *((u64 *)dt_data) = value;
161 dt_data += sizeof(u64);
162}
163#endif
164
165static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
166 int len)
167{
168 memcpy(dt_data, data, len);
169 dt_data += ALIGN(len, 4);
170}
171
172static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
173{
174 dt_push_u32(dt, OF_DT_BEGIN_NODE);
175 dt_push_bytes(dt, name, strlen(name) + 1);
176}
177
178#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
179
180static void __init __dt_prop(struct iseries_flat_dt *dt, const char *name,
181 const void *data, int len)
182{
183 unsigned long offset;
184
185 dt_push_u32(dt, OF_DT_PROP);
186
187 /* Length of the data */
188 dt_push_u32(dt, len);
189
190 offset = name - __dt_strings_start;
191
192 /* The offset of the properties name in the string blob. */
193 dt_push_u32(dt, (u32)offset);
194
195 /* The actual data. */
196 dt_push_bytes(dt, data, len);
197}
198#define dt_prop(dt, name, data, len) __dt_prop((dt), DS(name), (data), (len))
199
200#define dt_prop_str(dt, name, data) \
201 dt_prop((dt), name, (data), strlen((data)) + 1); /* + 1 for NULL */
202
203static void __init __dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
204 u32 data)
205{
206 __dt_prop(dt, name, &data, sizeof(u32));
207}
208#define dt_prop_u32(dt, name, data) __dt_prop_u32((dt), DS(name), (data))
209
210static void __init __maybe_unused __dt_prop_u64(struct iseries_flat_dt *dt,
211 const char *name, u64 data)
212{
213 __dt_prop(dt, name, &data, sizeof(u64));
214}
215#define dt_prop_u64(dt, name, data) __dt_prop_u64((dt), DS(name), (data))
216
217#define dt_prop_u64_list(dt, name, data, n) \
218 dt_prop((dt), name, (data), sizeof(u64) * (n))
219
220#define dt_prop_u32_list(dt, name, data, n) \
221 dt_prop((dt), name, (data), sizeof(u32) * (n))
222
223#define dt_prop_empty(dt, name) dt_prop((dt), name, NULL, 0)
224
225static void __init dt_cpus(struct iseries_flat_dt *dt)
226{
227 unsigned char buf[32];
228 unsigned char *p;
229 unsigned int i, index;
230 struct IoHriProcessorVpd *d;
231 u32 pft_size[2];
232
233 /* yuck */
234 snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
235 p = strchr(buf, ' ');
236 if (!p) p = buf + strlen(buf);
237
238 dt_start_node(dt, "cpus");
239 dt_prop_u32(dt, "#address-cells", 1);
240 dt_prop_u32(dt, "#size-cells", 0);
241
242 pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
243 pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
244
245 for (i = 0; i < NR_LPPACAS; i++) {
246 if (lppaca[i].dyn_proc_status >= 2)
247 continue;
248
249 snprintf(p, 32 - (p - buf), "@%d", i);
250 dt_start_node(dt, buf);
251
252 dt_prop_str(dt, "device_type", device_type_cpu);
253
254 index = lppaca[i].dyn_hv_phys_proc_index;
255 d = &xIoHriProcessorVpd[index];
256
257 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
258 dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
259
260 dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
261 dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
262
263 /* magic conversions to Hz copied from old code */
264 dt_prop_u32(dt, "clock-frequency",
265 ((1UL << 34) * 1000000) / d->xProcFreq);
266 dt_prop_u32(dt, "timebase-frequency",
267 ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
268
269 dt_prop_u32(dt, "reg", i);
270
271 dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
272
273 dt_end_node(dt);
274 }
275
276 dt_end_node(dt);
277}
278
279static void __init dt_model(struct iseries_flat_dt *dt)
280{
281 char buf[16] = "IBM,";
282
283 /* N.B. lparcfg.c knows about the "IBM," prefixes ... */
284 /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
285 strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
286 strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
287 buf[11] = '\0';
288 dt_prop_str(dt, "system-id", buf);
289
290 /* "IBM," + machineType[0:4] */
291 strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
292 buf[8] = '\0';
293 dt_prop_str(dt, "model", buf);
294
295 dt_prop_str(dt, "compatible", "IBM,iSeries");
296 dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
297}
298
299static void __init dt_initrd(struct iseries_flat_dt *dt)
300{
301#ifdef CONFIG_BLK_DEV_INITRD
302 if (naca.xRamDisk) {
303 dt_prop_u64(dt, "linux,initrd-start", (u64)naca.xRamDisk);
304 dt_prop_u64(dt, "linux,initrd-end",
305 (u64)naca.xRamDisk + naca.xRamDiskSize * HW_PAGE_SIZE);
306 }
307#endif
308}
309
310static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
311 const char *name, u32 reg, int unit,
312 const char *type, const char *compat, int end)
313{
314 char buf[32];
315
316 snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
317 dt_start_node(dt, buf);
318 dt_prop_str(dt, "device_type", type);
319 if (compat)
320 dt_prop_str(dt, "compatible", compat);
321 dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
322 if (unit >= 0)
323 dt_prop_u32(dt, "linux,unit_address", unit);
324 if (end)
325 dt_end_node(dt);
326}
327
328static void __init dt_vdevices(struct iseries_flat_dt *dt)
329{
330 u32 reg = 0;
331 HvLpIndexMap vlan_map;
332 int i;
333
334 dt_start_node(dt, "vdevice");
335 dt_prop_str(dt, "device_type", device_type_vdevice);
336 dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
337 dt_prop_u32(dt, "#address-cells", 1);
338 dt_prop_u32(dt, "#size-cells", 0);
339
340 dt_do_vdevice(dt, "vty", reg, -1, device_type_serial,
341 "IBM,iSeries-vty", 1);
342 reg++;
343
344 dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
345 "IBM,v-scsi", 1);
346 reg++;
347
348 vlan_map = HvLpConfig_getVirtualLanIndexMap();
349 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
350 unsigned char mac_addr[ETH_ALEN];
351
352 if ((vlan_map & (0x8000 >> i)) == 0)
353 continue;
354 dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
355 "IBM,iSeries-l-lan", 0);
356 mac_addr[0] = 0x02;
357 mac_addr[1] = 0x01;
358 mac_addr[2] = 0xff;
359 mac_addr[3] = i;
360 mac_addr[4] = 0xff;
361 mac_addr[5] = HvLpConfig_getLpIndex_outline();
362 dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
363 dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
364 dt_prop_u32(dt, "max-frame-size", 9000);
365 dt_prop_u32(dt, "address-bits", 48);
366
367 dt_end_node(dt);
368 }
369
370 dt_end_node(dt);
371}
372
373struct pci_class_name {
374 u16 code;
375 const char *name;
376 const char *type;
377};
378
379static struct pci_class_name __initdata pci_class_name[] = {
380 { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
381};
382
383static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
384{
385 struct pci_class_name *cp;
386
387 for (cp = pci_class_name;
388 cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
389 if (cp->code == class_code)
390 return cp;
391 return NULL;
392}
393
394/*
395 * This assumes that the node slot is always on the primary bus!
396 */
397static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
398 HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
399{
400 HvSubBusNumber sub_bus = bridge_info->subBusNumber;
401 u16 vendor_id;
402 u16 device_id;
403 u32 class_id;
404 int err;
405 char buf[32];
406 u32 reg[5];
407 int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
408 int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
409 HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
410 u8 devfn;
411 struct pci_class_name *cp;
412
413 /*
414 * Connect all functions of any device found.
415 */
416 for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
417 for (function = 0; function < 8; function++) {
418 HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
419 function);
420 err = HvCallXm_connectBusUnit(bus, sub_bus,
421 agent_id, 0);
422 if (err) {
423 if (err != 0x302)
424 DBG("connectBusUnit(%x, %x, %x) %x\n",
425 bus, sub_bus, agent_id, err);
426 continue;
427 }
428
429 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
430 PCI_VENDOR_ID, &vendor_id);
431 if (err) {
432 DBG("ReadVendor(%x, %x, %x) %x\n",
433 bus, sub_bus, agent_id, err);
434 continue;
435 }
436 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
437 PCI_DEVICE_ID, &device_id);
438 if (err) {
439 DBG("ReadDevice(%x, %x, %x) %x\n",
440 bus, sub_bus, agent_id, err);
441 continue;
442 }
443 err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
444 PCI_CLASS_REVISION , &class_id);
445 if (err) {
446 DBG("ReadClass(%x, %x, %x) %x\n",
447 bus, sub_bus, agent_id, err);
448 continue;
449 }
450
451 devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
452 function);
453 cp = dt_find_pci_class_name(class_id >> 16);
454 if (cp && cp->name)
455 strncpy(buf, cp->name, sizeof(buf) - 1);
456 else
457 snprintf(buf, sizeof(buf), "pci%x,%x",
458 vendor_id, device_id);
459 buf[sizeof(buf) - 1] = '\0';
460 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
461 "@%x", PCI_SLOT(devfn));
462 buf[sizeof(buf) - 1] = '\0';
463 if (function != 0)
464 snprintf(buf + strlen(buf),
465 sizeof(buf) - strlen(buf),
466 ",%x", function);
467 dt_start_node(dt, buf);
468 reg[0] = (bus << 16) | (devfn << 8);
469 reg[1] = 0;
470 reg[2] = 0;
471 reg[3] = 0;
472 reg[4] = 0;
473 dt_prop_u32_list(dt, "reg", reg, 5);
474 if (cp && (cp->type || cp->name))
475 dt_prop_str(dt, "device_type",
476 cp->type ? cp->type : cp->name);
477 dt_prop_u32(dt, "vendor-id", vendor_id);
478 dt_prop_u32(dt, "device-id", device_id);
479 dt_prop_u32(dt, "class-code", class_id >> 8);
480 dt_prop_u32(dt, "revision-id", class_id & 0xff);
481 dt_prop_u32(dt, "linux,subbus", sub_bus);
482 dt_prop_u32(dt, "linux,agent-id", agent_id);
483 dt_prop_u32(dt, "linux,logical-slot-number",
484 bridge_info->logicalSlotNumber);
485 dt_end_node(dt);
486
487 }
488 }
489}
490
491static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
492 HvSubBusNumber sub_bus, int id_sel)
493{
494 struct HvCallPci_BridgeInfo bridge_info;
495 HvAgentId agent_id;
496 int function;
497 int ret;
498
499 /* Note: hvSubBus and irq is always be 0 at this level! */
500 for (function = 0; function < 8; ++function) {
501 agent_id = ISERIES_PCI_AGENTID(id_sel, function);
502 ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
503 if (ret != 0) {
504 if (ret != 0xb)
505 DBG("connectBusUnit(%x, %x, %x) %x\n",
506 bus, sub_bus, agent_id, ret);
507 continue;
508 }
509 DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
510 bus, id_sel, function, agent_id);
511 ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
512 iseries_hv_addr(&bridge_info),
513 sizeof(struct HvCallPci_BridgeInfo));
514 if (ret != 0)
515 continue;
516 DBG("bridge info: type %x subbus %x "
517 "maxAgents %x maxsubbus %x logslot %x\n",
518 bridge_info.busUnitInfo.deviceType,
519 bridge_info.subBusNumber,
520 bridge_info.maxAgents,
521 bridge_info.maxSubBusNumber,
522 bridge_info.logicalSlotNumber);
523 if (bridge_info.busUnitInfo.deviceType ==
524 HvCallPci_BridgeDevice)
525 scan_bridge_slot(dt, bus, &bridge_info);
526 else
527 DBG("PCI: Invalid Bridge Configuration(0x%02X)",
528 bridge_info.busUnitInfo.deviceType);
529 }
530}
531
532static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
533{
534 struct HvCallPci_DeviceInfo dev_info;
535 const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
536 int err;
537 int id_sel;
538 const int max_agents = 8;
539
540 /*
541 * Probe for EADs Bridges
542 */
543 for (id_sel = 1; id_sel < max_agents; ++id_sel) {
544 err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
545 iseries_hv_addr(&dev_info),
546 sizeof(struct HvCallPci_DeviceInfo));
547 if (err) {
548 if (err != 0x302)
549 DBG("getDeviceInfo(%x, %x, %x) %x\n",
550 bus, sub_bus, id_sel, err);
551 continue;
552 }
553 if (dev_info.deviceType != HvCallPci_NodeDevice) {
554 DBG("PCI: Invalid System Configuration"
555 "(0x%02X) for bus 0x%02x id 0x%02x.\n",
556 dev_info.deviceType, bus, id_sel);
557 continue;
558 }
559 scan_bridge(dt, bus, sub_bus, id_sel);
560 }
561}
562
563static void __init dt_pci_devices(struct iseries_flat_dt *dt)
564{
565 HvBusNumber bus;
566 char buf[32];
567 u32 buses[2];
568 int phb_num = 0;
569
570 /* Check all possible buses. */
571 for (bus = 0; bus < 256; bus++) {
572 int err = HvCallXm_testBus(bus);
573
574 if (err) {
575 /*
576 * Check for Unexpected Return code, a clue that
577 * something has gone wrong.
578 */
579 if (err != 0x0301)
580 DBG("Unexpected Return on Probe(0x%02X) "
581 "0x%04X\n", bus, err);
582 continue;
583 }
584 DBG("bus %d appears to exist\n", bus);
585 snprintf(buf, 32, "pci@%d", phb_num);
586 dt_start_node(dt, buf);
587 dt_prop_str(dt, "device_type", device_type_pci);
588 dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
589 dt_prop_u32(dt, "#address-cells", 3);
590 dt_prop_u32(dt, "#size-cells", 2);
591 buses[0] = buses[1] = bus;
592 dt_prop_u32_list(dt, "bus-range", buses, 2);
593 scan_phb(dt, bus);
594 dt_end_node(dt);
595 phb_num++;
596 }
597}
598
599static void dt_finish(struct iseries_flat_dt *dt)
600{
601 dt_push_u32(dt, OF_DT_END);
602 dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
603 klimit = ALIGN((unsigned long)dt_data, 8);
604}
605
606void * __init build_flat_dt(unsigned long phys_mem_size)
607{
608 struct iseries_flat_dt *iseries_dt;
609 u64 tmp[2];
610
611 iseries_dt = dt_init();
612
613 dt_start_node(iseries_dt, "");
614
615 dt_prop_u32(iseries_dt, "#address-cells", 2);
616 dt_prop_u32(iseries_dt, "#size-cells", 2);
617 dt_model(iseries_dt);
618
619 /* /memory */
620 dt_start_node(iseries_dt, "memory@0");
621 dt_prop_str(iseries_dt, "device_type", device_type_memory);
622 tmp[0] = 0;
623 tmp[1] = phys_mem_size;
624 dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
625 dt_end_node(iseries_dt);
626
627 /* /chosen */
628 dt_start_node(iseries_dt, "chosen");
629 dt_prop_str(iseries_dt, "bootargs", cmd_line);
630 dt_initrd(iseries_dt);
631 dt_end_node(iseries_dt);
632
633 dt_cpus(iseries_dt);
634
635 dt_vdevices(iseries_dt);
636 dt_pci_devices(iseries_dt);
637
638 dt_end_node(iseries_dt);
639
640 dt_finish(iseries_dt);
641
642 return iseries_dt;
643}
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
deleted file mode 100644
index f519ee17ff7d..000000000000
--- a/arch/powerpc/platforms/iseries/exception.S
+++ /dev/null
@@ -1,311 +0,0 @@
1/*
2 * Low level routines for legacy iSeries support.
3 *
4 * Extracted from head_64.S
5 *
6 * PowerPC version
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 *
9 * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
10 * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
11 * Adapted for Power Macintosh by Paul Mackerras.
12 * Low-level exception handlers and MMU support
13 * rewritten by Paul Mackerras.
14 * Copyright (C) 1996 Paul Mackerras.
15 *
16 * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
17 * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
18 *
19 * This file contains the low-level support and setup for the
20 * PowerPC-64 platform, including trap and interrupt dispatch.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version
25 * 2 of the License, or (at your option) any later version.
26 */
27
28#include <asm/reg.h>
29#include <asm/ppc_asm.h>
30#include <asm/asm-offsets.h>
31#include <asm/thread_info.h>
32#include <asm/ptrace.h>
33#include <asm/cputable.h>
34#include <asm/mmu.h>
35
36#include "exception.h"
37
38 .text
39
40 .globl system_reset_iSeries
41system_reset_iSeries:
42 bl .relative_toc
43 mfspr r13,SPRN_SPRG3 /* Get alpaca address */
44 LOAD_REG_ADDR(r23, alpaca)
45 li r0,ALPACA_SIZE
46 sub r23,r13,r23
47 divdu r24,r23,r0 /* r24 has cpu number */
48 cmpwi 0,r24,0 /* Are we processor 0? */
49 bne 1f
50 LOAD_REG_ADDR(r13, boot_paca)
51 mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
52 mfmsr r23
53 ori r23,r23,MSR_RI
54 mtmsrd r23 /* RI on */
55 b .__start_initialization_iSeries /* Start up the first processor */
561: mfspr r4,SPRN_CTRLF
57 li r5,CTRL_RUNLATCH /* Turn off the run light */
58 andc r4,r4,r5
59 mtspr SPRN_CTRLT,r4
60
61/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
62/* In the UP case we'll yield() later, and we will not access the paca anyway */
63#ifdef CONFIG_SMP
64iSeries_secondary_wait_paca:
65 HMT_LOW
66 LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
67 ld r23,0(r23)
68
69 cmpdi 0,r23,0
70 bne 2f /* go on when the master is ready */
71
72 /* Keep poking the Hypervisor until we're released */
73 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
74 lis r3,0x8002
75 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
76 li r0,-1 /* r0=-1 indicates a Hypervisor call */
77 sc /* Invoke the hypervisor via a system call */
78 b iSeries_secondary_wait_paca
79
802:
81 HMT_MEDIUM
82 sync
83
84 LOAD_REG_ADDR(r3, nr_cpu_ids) /* get number of pacas allocated */
85 lwz r3,0(r3) /* nr_cpus= or NR_CPUS can limit */
86 cmpld 0,r24,r3 /* is our cpu number allocated? */
87 bge iSeries_secondary_yield /* no, yield forever */
88
89 /* Load our paca now that it's been allocated */
90 LOAD_REG_ADDR(r13, paca)
91 ld r13,0(r13)
92 mulli r0,r24,PACA_SIZE
93 add r13,r13,r0
94 mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */
95 mfmsr r23
96 ori r23,r23,MSR_RI
97 mtmsrd r23 /* RI on */
98
99iSeries_secondary_smp_loop:
100 lbz r23,PACAPROCSTART(r13) /* Test if this processor
101 * should start */
102 cmpwi 0,r23,0
103 bne 3f /* go on when we are told */
104
105 HMT_LOW
106 /* Let the Hypervisor know we are alive */
107 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
108 lis r3,0x8002
109 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
110 li r0,-1 /* r0=-1 indicates a Hypervisor call */
111 sc /* Invoke the hypervisor via a system call */
112 mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
113 b iSeries_secondary_smp_loop /* wait for signal to start */
114
1153:
116 HMT_MEDIUM
117 sync
118 LOAD_REG_ADDR(r3,current_set)
119 sldi r28,r24,3 /* get current_set[cpu#] */
120 ldx r3,r3,r28
121 addi r1,r3,THREAD_SIZE
122 subi r1,r1,STACK_FRAME_OVERHEAD
123
124 b __secondary_start /* Loop until told to go */
125#endif /* CONFIG_SMP */
126
127iSeries_secondary_yield:
128 /* Yield the processor. This is required for non-SMP kernels
129 which are running on multi-threaded machines. */
130 HMT_LOW
131 lis r3,0x8000
132 rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
133 addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
134 li r4,0 /* "yield timed" */
135 li r5,-1 /* "yield forever" */
136 li r0,-1 /* r0=-1 indicates a Hypervisor call */
137 sc /* Invoke the hypervisor via a system call */
138 mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
139 b iSeries_secondary_yield /* If SMP not configured, secondaries
140 * loop forever */
141
142/*** ISeries-LPAR interrupt handlers ***/
143
144 STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC)
145
146 .globl data_access_iSeries
147data_access_iSeries:
148 mtspr SPRN_SPRG_SCRATCH0,r13
149BEGIN_FTR_SECTION
150 mfspr r13,SPRN_SPRG_PACA
151 std r9,PACA_EXSLB+EX_R9(r13)
152 std r10,PACA_EXSLB+EX_R10(r13)
153 mfspr r10,SPRN_DAR
154 mfspr r9,SPRN_DSISR
155 srdi r10,r10,60
156 rlwimi r10,r9,16,0x20
157 mfcr r9
158 cmpwi r10,0x2c
159 beq .do_stab_bolted_iSeries
160 ld r10,PACA_EXSLB+EX_R10(r13)
161 std r11,PACA_EXGEN+EX_R11(r13)
162 ld r11,PACA_EXSLB+EX_R9(r13)
163 std r12,PACA_EXGEN+EX_R12(r13)
164 mfspr r12,SPRN_SPRG_SCRATCH0
165 std r10,PACA_EXGEN+EX_R10(r13)
166 std r11,PACA_EXGEN+EX_R9(r13)
167 std r12,PACA_EXGEN+EX_R13(r13)
168 EXCEPTION_PROLOG_ISERIES_1
169FTR_SECTION_ELSE
170 EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
171 EXCEPTION_PROLOG_ISERIES_1
172ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
173 b data_access_common
174
175.do_stab_bolted_iSeries:
176 std r11,PACA_EXSLB+EX_R11(r13)
177 std r12,PACA_EXSLB+EX_R12(r13)
178 mfspr r10,SPRN_SPRG_SCRATCH0
179 std r10,PACA_EXSLB+EX_R13(r13)
180 EXCEPTION_PROLOG_ISERIES_1
181 b .do_stab_bolted
182
183 .globl data_access_slb_iSeries
184data_access_slb_iSeries:
185 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
186 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
187 std r3,PACA_EXSLB+EX_R3(r13)
188 mfspr r3,SPRN_DAR
189 std r9,PACA_EXSLB+EX_R9(r13)
190 mfcr r9
191#ifdef __DISABLED__
192 cmpdi r3,0
193 bge slb_miss_user_iseries
194#endif
195 std r10,PACA_EXSLB+EX_R10(r13)
196 std r11,PACA_EXSLB+EX_R11(r13)
197 std r12,PACA_EXSLB+EX_R12(r13)
198 mfspr r10,SPRN_SPRG_SCRATCH0
199 std r10,PACA_EXSLB+EX_R13(r13)
200 ld r12,PACALPPACAPTR(r13)
201 ld r12,LPPACASRR1(r12)
202 b .slb_miss_realmode
203
204 STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN)
205
206 .globl instruction_access_slb_iSeries
207instruction_access_slb_iSeries:
208 mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */
209 mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */
210 std r3,PACA_EXSLB+EX_R3(r13)
211 ld r3,PACALPPACAPTR(r13)
212 ld r3,LPPACASRR0(r3) /* get SRR0 value */
213 std r9,PACA_EXSLB+EX_R9(r13)
214 mfcr r9
215#ifdef __DISABLED__
216 cmpdi r3,0
217 bge slb_miss_user_iseries
218#endif
219 std r10,PACA_EXSLB+EX_R10(r13)
220 std r11,PACA_EXSLB+EX_R11(r13)
221 std r12,PACA_EXSLB+EX_R12(r13)
222 mfspr r10,SPRN_SPRG_SCRATCH0
223 std r10,PACA_EXSLB+EX_R13(r13)
224 ld r12,PACALPPACAPTR(r13)
225 ld r12,LPPACASRR1(r12)
226 b .slb_miss_realmode
227
228#ifdef __DISABLED__
229slb_miss_user_iseries:
230 std r10,PACA_EXGEN+EX_R10(r13)
231 std r11,PACA_EXGEN+EX_R11(r13)
232 std r12,PACA_EXGEN+EX_R12(r13)
233 mfspr r10,SPRG_SCRATCH0
234 ld r11,PACA_EXSLB+EX_R9(r13)
235 ld r12,PACA_EXSLB+EX_R3(r13)
236 std r10,PACA_EXGEN+EX_R13(r13)
237 std r11,PACA_EXGEN+EX_R9(r13)
238 std r12,PACA_EXGEN+EX_R3(r13)
239 EXCEPTION_PROLOG_ISERIES_1
240 b slb_miss_user_common
241#endif
242
243 MASKABLE_EXCEPTION_ISERIES(hardware_interrupt)
244 STD_EXCEPTION_ISERIES(alignment, PACA_EXGEN)
245 STD_EXCEPTION_ISERIES(program_check, PACA_EXGEN)
246 STD_EXCEPTION_ISERIES(fp_unavailable, PACA_EXGEN)
247 MASKABLE_EXCEPTION_ISERIES(decrementer)
248 STD_EXCEPTION_ISERIES(trap_0a, PACA_EXGEN)
249 STD_EXCEPTION_ISERIES(trap_0b, PACA_EXGEN)
250
251 .globl system_call_iSeries
252system_call_iSeries:
253 mr r9,r13
254 mfspr r13,SPRN_SPRG_PACA
255 EXCEPTION_PROLOG_ISERIES_1
256 b system_call_common
257
258 STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN)
259 STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN)
260 STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN)
261
262decrementer_iSeries_masked:
263 /* We may not have a valid TOC pointer in here. */
264 li r11,1
265 ld r12,PACALPPACAPTR(r13)
266 stb r11,LPPACADECRINT(r12)
267 li r12,-1
268 clrldi r12,r12,33 /* set DEC to 0x7fffffff */
269 mtspr SPRN_DEC,r12
270 /* fall through */
271
272hardware_interrupt_iSeries_masked:
273 mtcrf 0x80,r9 /* Restore regs */
274 ld r12,PACALPPACAPTR(r13)
275 ld r11,LPPACASRR0(r12)
276 ld r12,LPPACASRR1(r12)
277 mtspr SPRN_SRR0,r11
278 mtspr SPRN_SRR1,r12
279 ld r9,PACA_EXGEN+EX_R9(r13)
280 ld r10,PACA_EXGEN+EX_R10(r13)
281 ld r11,PACA_EXGEN+EX_R11(r13)
282 ld r12,PACA_EXGEN+EX_R12(r13)
283 ld r13,PACA_EXGEN+EX_R13(r13)
284 rfid
285 b . /* prevent speculative execution */
286
287_INIT_STATIC(__start_initialization_iSeries)
288 /* Clear out the BSS */
289 LOAD_REG_ADDR(r11,__bss_stop)
290 LOAD_REG_ADDR(r8,__bss_start)
291 sub r11,r11,r8 /* bss size */
292 addi r11,r11,7 /* round up to an even double word */
293 rldicl. r11,r11,61,3 /* shift right by 3 */
294 beq 4f
295 addi r8,r8,-8
296 li r0,0
297 mtctr r11 /* zero this many doublewords */
2983: stdu r0,8(r8)
299 bdnz 3b
3004:
301 LOAD_REG_ADDR(r1,init_thread_union)
302 addi r1,r1,THREAD_SIZE
303 li r0,0
304 stdu r0,-STACK_FRAME_OVERHEAD(r1)
305
306 bl .iSeries_early_setup
307 bl .early_setup
308
309 /* relocation is on at this point */
310
311 b .start_here_common
diff --git a/arch/powerpc/platforms/iseries/exception.h b/arch/powerpc/platforms/iseries/exception.h
deleted file mode 100644
index 50271b550a99..000000000000
--- a/arch/powerpc/platforms/iseries/exception.h
+++ /dev/null
@@ -1,58 +0,0 @@
1#ifndef _ASM_POWERPC_ISERIES_EXCEPTION_H
2#define _ASM_POWERPC_ISERIES_EXCEPTION_H
3/*
4 * Extracted from head_64.S
5 *
6 * PowerPC version
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 *
9 * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
10 * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
11 * Adapted for Power Macintosh by Paul Mackerras.
12 * Low-level exception handlers and MMU support
13 * rewritten by Paul Mackerras.
14 * Copyright (C) 1996 Paul Mackerras.
15 *
16 * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
17 * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
18 *
19 * This file contains the low-level support and setup for the
20 * PowerPC-64 platform, including trap and interrupt dispatch.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version
25 * 2 of the License, or (at your option) any later version.
26 */
27#include <asm/exception-64s.h>
28
29#define EXCEPTION_PROLOG_ISERIES_1 \
30 mfmsr r10; \
31 ld r12,PACALPPACAPTR(r13); \
32 ld r11,LPPACASRR0(r12); \
33 ld r12,LPPACASRR1(r12); \
34 ori r10,r10,MSR_RI; \
35 mtmsrd r10,1
36
37#define STD_EXCEPTION_ISERIES(label, area) \
38 .globl label##_iSeries; \
39label##_iSeries: \
40 HMT_MEDIUM; \
41 mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
42 EXCEPTION_PROLOG_1(area, NOTEST, 0); \
43 EXCEPTION_PROLOG_ISERIES_1; \
44 b label##_common
45
46#define MASKABLE_EXCEPTION_ISERIES(label) \
47 .globl label##_iSeries; \
48label##_iSeries: \
49 HMT_MEDIUM; \
50 mtspr SPRN_SPRG_SCRATCH0,r13; /* save r13 */ \
51 EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0); \
52 lbz r10,PACASOFTIRQEN(r13); \
53 cmpwi 0,r10,0; \
54 beq- label##_iSeries_masked; \
55 EXCEPTION_PROLOG_ISERIES_1; \
56 b label##_common; \
57
58#endif /* _ASM_POWERPC_ISERIES_EXCEPTION_H */
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c
deleted file mode 100644
index 3ae66ab9d5e7..000000000000
--- a/arch/powerpc/platforms/iseries/htab.c
+++ /dev/null
@@ -1,257 +0,0 @@
1/*
2 * iSeries hashtable management.
3 * Derived from pSeries_htab.c
4 *
5 * SMP scalability work:
6 * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <asm/machdep.h>
14#include <asm/pgtable.h>
15#include <asm/mmu.h>
16#include <asm/mmu_context.h>
17#include <asm/abs_addr.h>
18#include <linux/spinlock.h>
19
20#include "call_hpt.h"
21
22static spinlock_t iSeries_hlocks[64] __cacheline_aligned_in_smp;
23
24/*
25 * Very primitive algorithm for picking up a lock
26 */
27static inline void iSeries_hlock(unsigned long slot)
28{
29 if (slot & 0x8)
30 slot = ~slot;
31 spin_lock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
32}
33
34static inline void iSeries_hunlock(unsigned long slot)
35{
36 if (slot & 0x8)
37 slot = ~slot;
38 spin_unlock(&iSeries_hlocks[(slot >> 4) & 0x3f]);
39}
40
41static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
42 unsigned long pa, unsigned long rflags,
43 unsigned long vflags, int psize, int ssize)
44{
45 long slot;
46 struct hash_pte lhpte;
47 int secondary = 0;
48
49 BUG_ON(psize != MMU_PAGE_4K);
50
51 /*
52 * The hypervisor tries both primary and secondary.
53 * If we are being called to insert in the secondary,
54 * it means we have already tried both primary and secondary,
55 * so we return failure immediately.
56 */
57 if (vflags & HPTE_V_SECONDARY)
58 return -1;
59
60 iSeries_hlock(hpte_group);
61
62 slot = HvCallHpt_findValid(&lhpte, va >> HW_PAGE_SHIFT);
63 if (unlikely(lhpte.v & HPTE_V_VALID)) {
64 if (vflags & HPTE_V_BOLTED) {
65 HvCallHpt_setSwBits(slot, 0x10, 0);
66 HvCallHpt_setPp(slot, PP_RWXX);
67 iSeries_hunlock(hpte_group);
68 if (slot < 0)
69 return 0x8 | (slot & 7);
70 else
71 return slot & 7;
72 }
73 BUG();
74 }
75
76 if (slot == -1) { /* No available entry found in either group */
77 iSeries_hunlock(hpte_group);
78 return -1;
79 }
80
81 if (slot < 0) { /* MSB set means secondary group */
82 vflags |= HPTE_V_SECONDARY;
83 secondary = 1;
84 slot &= 0x7fffffffffffffff;
85 }
86
87
88 lhpte.v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M) |
89 vflags | HPTE_V_VALID;
90 lhpte.r = hpte_encode_r(phys_to_abs(pa), MMU_PAGE_4K) | rflags;
91
92 /* Now fill in the actual HPTE */
93 HvCallHpt_addValidate(slot, secondary, &lhpte);
94
95 iSeries_hunlock(hpte_group);
96
97 return (secondary << 3) | (slot & 7);
98}
99
100static unsigned long iSeries_hpte_getword0(unsigned long slot)
101{
102 struct hash_pte hpte;
103
104 HvCallHpt_get(&hpte, slot);
105 return hpte.v;
106}
107
108static long iSeries_hpte_remove(unsigned long hpte_group)
109{
110 unsigned long slot_offset;
111 int i;
112 unsigned long hpte_v;
113
114 /* Pick a random slot to start at */
115 slot_offset = mftb() & 0x7;
116
117 iSeries_hlock(hpte_group);
118
119 for (i = 0; i < HPTES_PER_GROUP; i++) {
120 hpte_v = iSeries_hpte_getword0(hpte_group + slot_offset);
121
122 if (! (hpte_v & HPTE_V_BOLTED)) {
123 HvCallHpt_invalidateSetSwBitsGet(hpte_group +
124 slot_offset, 0, 0);
125 iSeries_hunlock(hpte_group);
126 return i;
127 }
128
129 slot_offset++;
130 slot_offset &= 0x7;
131 }
132
133 iSeries_hunlock(hpte_group);
134
135 return -1;
136}
137
138/*
139 * The HyperVisor expects the "flags" argument in this form:
140 * bits 0..59 : reserved
141 * bit 60 : N
142 * bits 61..63 : PP2,PP1,PP0
143 */
144static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
145 unsigned long va, int psize, int ssize, int local)
146{
147 struct hash_pte hpte;
148 unsigned long want_v;
149
150 iSeries_hlock(slot);
151
152 HvCallHpt_get(&hpte, slot);
153 want_v = hpte_encode_v(va, MMU_PAGE_4K, MMU_SEGSIZE_256M);
154
155 if (HPTE_V_COMPARE(hpte.v, want_v) && (hpte.v & HPTE_V_VALID)) {
156 /*
157 * Hypervisor expects bits as NPPP, which is
158 * different from how they are mapped in our PP.
159 */
160 HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
161 iSeries_hunlock(slot);
162 return 0;
163 }
164 iSeries_hunlock(slot);
165
166 return -1;
167}
168
169/*
170 * Functions used to find the PTE for a particular virtual address.
171 * Only used during boot when bolting pages.
172 *
173 * Input : vpn : virtual page number
174 * Output: PTE index within the page table of the entry
175 * -1 on failure
176 */
177static long iSeries_hpte_find(unsigned long vpn)
178{
179 struct hash_pte hpte;
180 long slot;
181
182 /*
183 * The HvCallHpt_findValid interface is as follows:
184 * 0xffffffffffffffff : No entry found.
185 * 0x00000000xxxxxxxx : Entry found in primary group, slot x
186 * 0x80000000xxxxxxxx : Entry found in secondary group, slot x
187 */
188 slot = HvCallHpt_findValid(&hpte, vpn);
189 if (hpte.v & HPTE_V_VALID) {
190 if (slot < 0) {
191 slot &= 0x7fffffffffffffff;
192 slot = -slot;
193 }
194 } else
195 slot = -1;
196 return slot;
197}
198
199/*
200 * Update the page protection bits. Intended to be used to create
201 * guard pages for kernel data structures on pages which are bolted
202 * in the HPT. Assumes pages being operated on will not be stolen.
203 * Does not work on large pages.
204 *
205 * No need to lock here because we should be the only user.
206 */
207static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
208 int psize, int ssize)
209{
210 unsigned long vsid,va,vpn;
211 long slot;
212
213 BUG_ON(psize != MMU_PAGE_4K);
214
215 vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
216 va = (vsid << 28) | (ea & 0x0fffffff);
217 vpn = va >> HW_PAGE_SHIFT;
218 slot = iSeries_hpte_find(vpn);
219 if (slot == -1)
220 panic("updateboltedpp: Could not find page to bolt\n");
221 HvCallHpt_setPp(slot, newpp);
222}
223
224static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
225 int psize, int ssize, int local)
226{
227 unsigned long hpte_v;
228 unsigned long avpn = va >> 23;
229 unsigned long flags;
230
231 local_irq_save(flags);
232
233 iSeries_hlock(slot);
234
235 hpte_v = iSeries_hpte_getword0(slot);
236
237 if ((HPTE_V_AVPN_VAL(hpte_v) == avpn) && (hpte_v & HPTE_V_VALID))
238 HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0);
239
240 iSeries_hunlock(slot);
241
242 local_irq_restore(flags);
243}
244
245void __init hpte_init_iSeries(void)
246{
247 int i;
248
249 for (i = 0; i < ARRAY_SIZE(iSeries_hlocks); i++)
250 spin_lock_init(&iSeries_hlocks[i]);
251
252 ppc_md.hpte_invalidate = iSeries_hpte_invalidate;
253 ppc_md.hpte_updatepp = iSeries_hpte_updatepp;
254 ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
255 ppc_md.hpte_insert = iSeries_hpte_insert;
256 ppc_md.hpte_remove = iSeries_hpte_remove;
257}
diff --git a/arch/powerpc/platforms/iseries/hvcall.S b/arch/powerpc/platforms/iseries/hvcall.S
deleted file mode 100644
index 07ae6ad5f49f..000000000000
--- a/arch/powerpc/platforms/iseries/hvcall.S
+++ /dev/null
@@ -1,94 +0,0 @@
1/*
2 * This file contains the code to perform calls to the
3 * iSeries LPAR hypervisor
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include <asm/ppc_asm.h>
12#include <asm/processor.h>
13#include <asm/ptrace.h> /* XXX for STACK_FRAME_OVERHEAD */
14
15 .text
16
17/*
18 * Hypervisor call
19 *
20 * Invoke the iSeries hypervisor via the System Call instruction
21 * Parameters are passed to this routine in registers r3 - r10
22 *
23 * r3 contains the HV function to be called
24 * r4-r10 contain the operands to the hypervisor function
25 *
26 */
27
28_GLOBAL(HvCall)
29_GLOBAL(HvCall0)
30_GLOBAL(HvCall1)
31_GLOBAL(HvCall2)
32_GLOBAL(HvCall3)
33_GLOBAL(HvCall4)
34_GLOBAL(HvCall5)
35_GLOBAL(HvCall6)
36_GLOBAL(HvCall7)
37
38
39 mfcr r0
40 std r0,-8(r1)
41 stdu r1,-(STACK_FRAME_OVERHEAD+16)(r1)
42
43 /* r0 = 0xffffffffffffffff indicates a hypervisor call */
44
45 li r0,-1
46
47 /* Invoke the hypervisor */
48
49 sc
50
51 ld r1,0(r1)
52 ld r0,-8(r1)
53 mtcrf 0xff,r0
54
55 /* return to caller, return value in r3 */
56
57 blr
58
59_GLOBAL(HvCall0Ret16)
60_GLOBAL(HvCall1Ret16)
61_GLOBAL(HvCall2Ret16)
62_GLOBAL(HvCall3Ret16)
63_GLOBAL(HvCall4Ret16)
64_GLOBAL(HvCall5Ret16)
65_GLOBAL(HvCall6Ret16)
66_GLOBAL(HvCall7Ret16)
67
68 mfcr r0
69 std r0,-8(r1)
70 std r31,-16(r1)
71 stdu r1,-(STACK_FRAME_OVERHEAD+32)(r1)
72
73 mr r31,r4
74 li r0,-1
75 mr r4,r5
76 mr r5,r6
77 mr r6,r7
78 mr r7,r8
79 mr r8,r9
80 mr r9,r10
81
82 sc
83
84 std r3,0(r31)
85 std r4,8(r31)
86
87 mr r3,r5
88
89 ld r1,0(r1)
90 ld r0,-8(r1)
91 mtcrf 0xff,r0
92 ld r31,-16(r1)
93
94 blr
diff --git a/arch/powerpc/platforms/iseries/hvlog.c b/arch/powerpc/platforms/iseries/hvlog.c
deleted file mode 100644
index f476d71194fa..000000000000
--- a/arch/powerpc/platforms/iseries/hvlog.c
+++ /dev/null
@@ -1,35 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <asm/page.h>
11#include <asm/abs_addr.h>
12#include <asm/iseries/hv_call.h>
13#include <asm/iseries/hv_call_sc.h>
14#include <asm/iseries/hv_types.h>
15
16
17void HvCall_writeLogBuffer(const void *buffer, u64 len)
18{
19 struct HvLpBufferList hv_buf;
20 u64 left_this_page;
21 u64 cur = virt_to_abs(buffer);
22
23 while (len) {
24 hv_buf.addr = cur;
25 left_this_page = ((cur & HW_PAGE_MASK) + HW_PAGE_SIZE) - cur;
26 if (left_this_page > len)
27 left_this_page = len;
28 hv_buf.len = left_this_page;
29 len -= left_this_page;
30 HvCall2(HvCallBaseWriteLogBuffer,
31 virt_to_abs(&hv_buf),
32 left_this_page);
33 cur = (cur & HW_PAGE_MASK) + HW_PAGE_SIZE;
34 }
35}
diff --git a/arch/powerpc/platforms/iseries/hvlpconfig.c b/arch/powerpc/platforms/iseries/hvlpconfig.c
deleted file mode 100644
index f62a0c5fa670..000000000000
--- a/arch/powerpc/platforms/iseries/hvlpconfig.c
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 * Copyright (C) 2001 Kyle A. Lucke, IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/export.h>
20#include <asm/iseries/hv_lp_config.h>
21#include "it_lp_naca.h"
22
23HvLpIndex HvLpConfig_getLpIndex_outline(void)
24{
25 return HvLpConfig_getLpIndex();
26}
27EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
28
29HvLpIndex HvLpConfig_getLpIndex(void)
30{
31 return itLpNaca.xLpIndex;
32}
33EXPORT_SYMBOL(HvLpConfig_getLpIndex);
34
35HvLpIndex HvLpConfig_getPrimaryLpIndex(void)
36{
37 return itLpNaca.xPrimaryLpIndex;
38}
39EXPORT_SYMBOL_GPL(HvLpConfig_getPrimaryLpIndex);
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
deleted file mode 100644
index 2f3d9110248c..000000000000
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ /dev/null
@@ -1,260 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
3 *
4 * Rewrite, cleanup:
5 *
6 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
7 * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
8 *
9 * Dynamic DMA mapping support, iSeries-specific parts.
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/types.h>
28#include <linux/dma-mapping.h>
29#include <linux/list.h>
30#include <linux/pci.h>
31#include <linux/export.h>
32#include <linux/slab.h>
33
34#include <asm/iommu.h>
35#include <asm/vio.h>
36#include <asm/tce.h>
37#include <asm/machdep.h>
38#include <asm/abs_addr.h>
39#include <asm/prom.h>
40#include <asm/pci-bridge.h>
41#include <asm/iseries/hv_call_xm.h>
42#include <asm/iseries/hv_call_event.h>
43#include <asm/iseries/iommu.h>
44
45static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
46 unsigned long uaddr, enum dma_data_direction direction,
47 struct dma_attrs *attrs)
48{
49 u64 rc;
50 u64 tce, rpn;
51
52 while (npages--) {
53 rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
54 tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
55
56 if (tbl->it_type == TCE_VB) {
57 /* Virtual Bus */
58 tce |= TCE_VALID|TCE_ALLIO;
59 if (direction != DMA_TO_DEVICE)
60 tce |= TCE_VB_WRITE;
61 } else {
62 /* PCI Bus */
63 tce |= TCE_PCI_READ; /* Read allowed */
64 if (direction != DMA_TO_DEVICE)
65 tce |= TCE_PCI_WRITE;
66 }
67
68 rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
69 if (rc)
70 panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
71 rc);
72 index++;
73 uaddr += TCE_PAGE_SIZE;
74 }
75 return 0;
76}
77
78static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
79{
80 u64 rc;
81
82 while (npages--) {
83 rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
84 if (rc)
85 panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
86 rc);
87 index++;
88 }
89}
90
91/*
92 * Structure passed to HvCallXm_getTceTableParms
93 */
94struct iommu_table_cb {
95 unsigned long itc_busno; /* Bus number for this tce table */
96 unsigned long itc_start; /* Will be NULL for secondary */
97 unsigned long itc_totalsize; /* Size (in pages) of whole table */
98 unsigned long itc_offset; /* Index into real tce table of the
99 start of our section */
100 unsigned long itc_size; /* Size (in pages) of our section */
101 unsigned long itc_index; /* Index of this tce table */
102 unsigned short itc_maxtables; /* Max num of tables for partition */
103 unsigned char itc_virtbus; /* Flag to indicate virtual bus */
104 unsigned char itc_slotno; /* IOA Tce Slot Index */
105 unsigned char itc_rsvd[4];
106};
107
108/*
109 * Call Hv with the architected data structure to get TCE table info.
110 * info. Put the returned data into the Linux representation of the
111 * TCE table data.
112 * The Hardware Tce table comes in three flavors.
113 * 1. TCE table shared between Buses.
114 * 2. TCE table per Bus.
115 * 3. TCE Table per IOA.
116 */
117void iommu_table_getparms_iSeries(unsigned long busno,
118 unsigned char slotno,
119 unsigned char virtbus,
120 struct iommu_table* tbl)
121{
122 struct iommu_table_cb *parms;
123
124 parms = kzalloc(sizeof(*parms), GFP_KERNEL);
125 if (parms == NULL)
126 panic("PCI_DMA: TCE Table Allocation failed.");
127
128 parms->itc_busno = busno;
129 parms->itc_slotno = slotno;
130 parms->itc_virtbus = virtbus;
131
132 HvCallXm_getTceTableParms(iseries_hv_addr(parms));
133
134 if (parms->itc_size == 0)
135 panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms);
136
137 /* itc_size is in pages worth of table, it_size is in # of entries */
138 tbl->it_size = (parms->itc_size * TCE_PAGE_SIZE) / TCE_ENTRY_SIZE;
139 tbl->it_busno = parms->itc_busno;
140 tbl->it_offset = parms->itc_offset;
141 tbl->it_index = parms->itc_index;
142 tbl->it_blocksize = 1;
143 tbl->it_type = virtbus ? TCE_VB : TCE_PCI;
144
145 kfree(parms);
146}
147
148
149#ifdef CONFIG_PCI
150/*
151 * This function compares the known tables to find an iommu_table
152 * that has already been built for hardware TCEs.
153 */
154static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
155{
156 struct device_node *node;
157
158 for (node = NULL; (node = of_find_all_nodes(node)); ) {
159 struct pci_dn *pdn = PCI_DN(node);
160 struct iommu_table *it;
161
162 if (pdn == NULL)
163 continue;
164 it = pdn->iommu_table;
165 if ((it != NULL) &&
166 (it->it_type == TCE_PCI) &&
167 (it->it_offset == tbl->it_offset) &&
168 (it->it_index == tbl->it_index) &&
169 (it->it_size == tbl->it_size)) {
170 of_node_put(node);
171 return it;
172 }
173 }
174 return NULL;
175}
176
177
178static void pci_dma_dev_setup_iseries(struct pci_dev *pdev)
179{
180 struct iommu_table *tbl;
181 struct device_node *dn = pci_device_to_OF_node(pdev);
182 struct pci_dn *pdn = PCI_DN(dn);
183 const u32 *lsn = of_get_property(dn, "linux,logical-slot-number", NULL);
184
185 BUG_ON(lsn == NULL);
186
187 tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
188
189 iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
190
191 /* Look for existing tce table */
192 pdn->iommu_table = iommu_table_find(tbl);
193 if (pdn->iommu_table == NULL)
194 pdn->iommu_table = iommu_init_table(tbl, -1);
195 else
196 kfree(tbl);
197 set_iommu_table_base(&pdev->dev, pdn->iommu_table);
198}
199#else
200#define pci_dma_dev_setup_iseries NULL
201#endif
202
203static struct iommu_table veth_iommu_table;
204static struct iommu_table vio_iommu_table;
205
206void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
207{
208 return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
209 DMA_BIT_MASK(32), flag, -1);
210}
211EXPORT_SYMBOL_GPL(iseries_hv_alloc);
212
213void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
214{
215 iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
216}
217EXPORT_SYMBOL_GPL(iseries_hv_free);
218
219dma_addr_t iseries_hv_map(void *vaddr, size_t size,
220 enum dma_data_direction direction)
221{
222 return iommu_map_page(NULL, &vio_iommu_table, virt_to_page(vaddr),
223 (unsigned long)vaddr % PAGE_SIZE, size,
224 DMA_BIT_MASK(32), direction, NULL);
225}
226
227void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
228 enum dma_data_direction direction)
229{
230 iommu_unmap_page(&vio_iommu_table, dma_handle, size, direction, NULL);
231}
232
233void __init iommu_vio_init(void)
234{
235 iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
236 veth_iommu_table.it_size /= 2;
237 vio_iommu_table = veth_iommu_table;
238 vio_iommu_table.it_offset += veth_iommu_table.it_size;
239
240 if (!iommu_init_table(&veth_iommu_table, -1))
241 printk("Virtual Bus VETH TCE table failed.\n");
242 if (!iommu_init_table(&vio_iommu_table, -1))
243 printk("Virtual Bus VIO TCE table failed.\n");
244}
245
246struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
247{
248 if (strcmp(dev->type, "network") == 0)
249 return &veth_iommu_table;
250 return &vio_iommu_table;
251}
252
253void iommu_init_early_iSeries(void)
254{
255 ppc_md.tce_build = tce_build_iSeries;
256 ppc_md.tce_free = tce_free_iSeries;
257
258 ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_iseries;
259 set_pci_dma_ops(&dma_iommu_ops);
260}
diff --git a/arch/powerpc/platforms/iseries/ipl_parms.h b/arch/powerpc/platforms/iseries/ipl_parms.h
deleted file mode 100644
index 83e4ca42fc57..000000000000
--- a/arch/powerpc/platforms/iseries/ipl_parms.h
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISERIES_IPL_PARMS_H
19#define _ISERIES_IPL_PARMS_H
20
21/*
22 * This struct maps the IPL Parameters DMA'd from the SP.
23 *
24 * Warning:
25 * This data must map in exactly 64 bytes and match the architecture for
26 * the IPL parms
27 */
28
29#include <asm/types.h>
30
31struct ItIplParmsReal {
32 u8 xFormat; // Defines format of IplParms x00-x00
33 u8 xRsvd01:6; // Reserved x01-x01
34 u8 xAlternateSearch:1; // Alternate search indicator ...
35 u8 xUaSupplied:1; // UA Supplied on programmed IPL...
36 u8 xLsUaFormat; // Format byte for UA x02-x02
37 u8 xRsvd02; // Reserved x03-x03
38 u32 xLsUa; // LS UA x04-x07
39 u32 xUnusedLsLid; // First OS LID to load x08-x0B
40 u16 xLsBusNumber; // LS Bus Number x0C-x0D
41 u8 xLsCardAdr; // LS Card Address x0E-x0E
42 u8 xLsBoardAdr; // LS Board Address x0F-x0F
43 u32 xRsvd03; // Reserved x10-x13
44 u8 xSpcnPresent:1; // SPCN present x14-x14
45 u8 xCpmPresent:1; // CPM present ...
46 u8 xRsvd04:6; // Reserved ...
47 u8 xRsvd05:4; // Reserved x15-x15
48 u8 xKeyLock:4; // Keylock setting ...
49 u8 xRsvd06:6; // Reserved x16-x16
50 u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
51 u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
52 u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19
53 u16 xPowerOnResetIpl:1; // Indicate POR condition ...
54 u16 xMainStorePreserved:1; // Main Storage is preserved ...
55 u16 xRsvd07:13; // Reserved ...
56 u16 xIplSource:16; // Ipl source x1A-x1B
57 u8 xIplReason:8; // Reason for this IPL x1C-x1C
58 u8 xRsvd08; // Reserved x1D-x1D
59 u16 xRsvd09; // Reserved x1E-x1F
60 u16 xSysBoxType; // System Box Type x20-x21
61 u16 xSysProcType; // System Processor Type x22-x23
62 u32 xRsvd10; // Reserved x24-x27
63 u64 xRsvd11; // Reserved x28-x2F
64 u64 xRsvd12; // Reserved x30-x37
65 u64 xRsvd13; // Reserved x38-x3F
66};
67
68#endif /* _ISERIES_IPL_PARMS_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
deleted file mode 100644
index 05ce5164cafc..000000000000
--- a/arch/powerpc/platforms/iseries/irq.c
+++ /dev/null
@@ -1,399 +0,0 @@
1/*
2 * This module supports the iSeries PCI bus interrupt handling
3 * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
4 * Copyright (C) 2004-2005 IBM Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the:
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307 USA
21 *
22 * Change Activity:
23 * Created, December 13, 2000 by Wayne Holm
24 * End Change Activity
25 */
26#include <linux/pci.h>
27#include <linux/init.h>
28#include <linux/threads.h>
29#include <linux/smp.h>
30#include <linux/param.h>
31#include <linux/string.h>
32#include <linux/bootmem.h>
33#include <linux/irq.h>
34#include <linux/spinlock.h>
35
36#include <asm/paca.h>
37#include <asm/iseries/hv_types.h>
38#include <asm/iseries/hv_lp_event.h>
39#include <asm/iseries/hv_call_xm.h>
40#include <asm/iseries/it_lp_queue.h>
41
42#include "irq.h"
43#include "pci.h"
44#include "call_pci.h"
45
46#ifdef CONFIG_PCI
47
48enum pci_event_type {
49 pe_bus_created = 0, /* PHB has been created */
50 pe_bus_error = 1, /* PHB has failed */
51 pe_bus_failed = 2, /* Msg to Secondary, Primary failed bus */
52 pe_node_failed = 4, /* Multi-adapter bridge has failed */
53 pe_node_recovered = 5, /* Multi-adapter bridge has recovered */
54 pe_bus_recovered = 12, /* PHB has been recovered */
55 pe_unquiese_bus = 18, /* Secondary bus unqiescing */
56 pe_bridge_error = 21, /* Bridge Error */
57 pe_slot_interrupt = 22 /* Slot interrupt */
58};
59
60struct pci_event {
61 struct HvLpEvent event;
62 union {
63 u64 __align; /* Align on an 8-byte boundary */
64 struct {
65 u32 fisr;
66 HvBusNumber bus_number;
67 HvSubBusNumber sub_bus_number;
68 HvAgentId dev_id;
69 } slot;
70 struct {
71 HvBusNumber bus_number;
72 HvSubBusNumber sub_bus_number;
73 } bus;
74 struct {
75 HvBusNumber bus_number;
76 HvSubBusNumber sub_bus_number;
77 HvAgentId dev_id;
78 } node;
79 } data;
80};
81
82static DEFINE_SPINLOCK(pending_irqs_lock);
83static int num_pending_irqs;
84static int pending_irqs[NR_IRQS];
85
86static void int_received(struct pci_event *event)
87{
88 int irq;
89
90 switch (event->event.xSubtype) {
91 case pe_slot_interrupt:
92 irq = event->event.xCorrelationToken;
93 if (irq < NR_IRQS) {
94 spin_lock(&pending_irqs_lock);
95 pending_irqs[irq]++;
96 num_pending_irqs++;
97 spin_unlock(&pending_irqs_lock);
98 } else {
99 printk(KERN_WARNING "int_received: bad irq number %d\n",
100 irq);
101 HvCallPci_eoi(event->data.slot.bus_number,
102 event->data.slot.sub_bus_number,
103 event->data.slot.dev_id);
104 }
105 break;
106 /* Ignore error recovery events for now */
107 case pe_bus_created:
108 printk(KERN_INFO "int_received: system bus %d created\n",
109 event->data.bus.bus_number);
110 break;
111 case pe_bus_error:
112 case pe_bus_failed:
113 printk(KERN_INFO "int_received: system bus %d failed\n",
114 event->data.bus.bus_number);
115 break;
116 case pe_bus_recovered:
117 case pe_unquiese_bus:
118 printk(KERN_INFO "int_received: system bus %d recovered\n",
119 event->data.bus.bus_number);
120 break;
121 case pe_node_failed:
122 case pe_bridge_error:
123 printk(KERN_INFO
124 "int_received: multi-adapter bridge %d/%d/%d failed\n",
125 event->data.node.bus_number,
126 event->data.node.sub_bus_number,
127 event->data.node.dev_id);
128 break;
129 case pe_node_recovered:
130 printk(KERN_INFO
131 "int_received: multi-adapter bridge %d/%d/%d recovered\n",
132 event->data.node.bus_number,
133 event->data.node.sub_bus_number,
134 event->data.node.dev_id);
135 break;
136 default:
137 printk(KERN_ERR
138 "int_received: unrecognized event subtype 0x%x\n",
139 event->event.xSubtype);
140 break;
141 }
142}
143
144static void pci_event_handler(struct HvLpEvent *event)
145{
146 if (event && (event->xType == HvLpEvent_Type_PciIo)) {
147 if (hvlpevent_is_int(event))
148 int_received((struct pci_event *)event);
149 else
150 printk(KERN_ERR
151 "pci_event_handler: unexpected ack received\n");
152 } else if (event)
153 printk(KERN_ERR
154 "pci_event_handler: Unrecognized PCI event type 0x%x\n",
155 (int)event->xType);
156 else
157 printk(KERN_ERR "pci_event_handler: NULL event received\n");
158}
159
160#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
161#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
162#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
163#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
164
165/*
166 * This will be called by device drivers (via enable_IRQ)
167 * to enable INTA in the bridge interrupt status register.
168 */
169static void iseries_enable_IRQ(struct irq_data *d)
170{
171 u32 bus, dev_id, function, mask;
172 const u32 sub_bus = 0;
173 unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
174
175 /* The IRQ has already been locked by the caller */
176 bus = REAL_IRQ_TO_BUS(rirq);
177 function = REAL_IRQ_TO_FUNC(rirq);
178 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
179
180 /* Unmask secondary INTA */
181 mask = 0x80000000;
182 HvCallPci_unmaskInterrupts(bus, sub_bus, dev_id, mask);
183}
184
185/* This is called by iseries_activate_IRQs */
186static unsigned int iseries_startup_IRQ(struct irq_data *d)
187{
188 u32 bus, dev_id, function, mask;
189 const u32 sub_bus = 0;
190 unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
191
192 bus = REAL_IRQ_TO_BUS(rirq);
193 function = REAL_IRQ_TO_FUNC(rirq);
194 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
195
196 /* Link the IRQ number to the bridge */
197 HvCallXm_connectBusUnit(bus, sub_bus, dev_id, d->irq);
198
199 /* Unmask bridge interrupts in the FISR */
200 mask = 0x01010000 << function;
201 HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
202 iseries_enable_IRQ(d);
203 return 0;
204}
205
206/*
207 * This is called out of iSeries_fixup to activate interrupt
208 * generation for usable slots
209 */
210void __init iSeries_activate_IRQs()
211{
212 int irq;
213 unsigned long flags;
214
215 for_each_irq (irq) {
216 struct irq_desc *desc = irq_to_desc(irq);
217 struct irq_chip *chip;
218
219 if (!desc)
220 continue;
221
222 chip = irq_desc_get_chip(desc);
223 if (chip && chip->irq_startup) {
224 raw_spin_lock_irqsave(&desc->lock, flags);
225 chip->irq_startup(&desc->irq_data);
226 raw_spin_unlock_irqrestore(&desc->lock, flags);
227 }
228 }
229}
230
231/* this is not called anywhere currently */
232static void iseries_shutdown_IRQ(struct irq_data *d)
233{
234 u32 bus, dev_id, function, mask;
235 const u32 sub_bus = 0;
236 unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
237
238 /* irq should be locked by the caller */
239 bus = REAL_IRQ_TO_BUS(rirq);
240 function = REAL_IRQ_TO_FUNC(rirq);
241 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
242
243 /* Invalidate the IRQ number in the bridge */
244 HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0);
245
246 /* Mask bridge interrupts in the FISR */
247 mask = 0x01010000 << function;
248 HvCallPci_maskFisr(bus, sub_bus, dev_id, mask);
249}
250
251/*
252 * This will be called by device drivers (via disable_IRQ)
253 * to disable INTA in the bridge interrupt status register.
254 */
255static void iseries_disable_IRQ(struct irq_data *d)
256{
257 u32 bus, dev_id, function, mask;
258 const u32 sub_bus = 0;
259 unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
260
261 /* The IRQ has already been locked by the caller */
262 bus = REAL_IRQ_TO_BUS(rirq);
263 function = REAL_IRQ_TO_FUNC(rirq);
264 dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
265
266 /* Mask secondary INTA */
267 mask = 0x80000000;
268 HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
269}
270
271static void iseries_end_IRQ(struct irq_data *d)
272{
273 unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
274
275 HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
276 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
277}
278
279static struct irq_chip iseries_pic = {
280 .name = "iSeries",
281 .irq_startup = iseries_startup_IRQ,
282 .irq_shutdown = iseries_shutdown_IRQ,
283 .irq_unmask = iseries_enable_IRQ,
284 .irq_mask = iseries_disable_IRQ,
285 .irq_eoi = iseries_end_IRQ
286};
287
288/*
289 * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
290 * It calculates the irq value for the slot.
291 * Note that sub_bus is always 0 (at the moment at least).
292 */
293int __init iSeries_allocate_IRQ(HvBusNumber bus,
294 HvSubBusNumber sub_bus, u32 bsubbus)
295{
296 unsigned int realirq;
297 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
298 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
299
300 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
301 + function;
302
303 return irq_create_mapping(NULL, realirq);
304}
305
306#endif /* CONFIG_PCI */
307
308/*
309 * Get the next pending IRQ.
310 */
311unsigned int iSeries_get_irq(void)
312{
313 int irq = NO_IRQ_IGNORE;
314
315#ifdef CONFIG_SMP
316 if (get_lppaca()->int_dword.fields.ipi_cnt) {
317 get_lppaca()->int_dword.fields.ipi_cnt = 0;
318 smp_ipi_demux();
319 }
320#endif /* CONFIG_SMP */
321 if (hvlpevent_is_pending())
322 process_hvlpevents();
323
324#ifdef CONFIG_PCI
325 if (num_pending_irqs) {
326 spin_lock(&pending_irqs_lock);
327 for (irq = 0; irq < NR_IRQS; irq++) {
328 if (pending_irqs[irq]) {
329 pending_irqs[irq]--;
330 num_pending_irqs--;
331 break;
332 }
333 }
334 spin_unlock(&pending_irqs_lock);
335 if (irq >= NR_IRQS)
336 irq = NO_IRQ_IGNORE;
337 }
338#endif
339
340 return irq;
341}
342
343#ifdef CONFIG_PCI
344
345static int iseries_irq_host_map(struct irq_domain *h, unsigned int virq,
346 irq_hw_number_t hw)
347{
348 irq_set_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
349
350 return 0;
351}
352
353static int iseries_irq_host_match(struct irq_domain *h, struct device_node *np)
354{
355 /* Match all */
356 return 1;
357}
358
359static const struct irq_domain_ops iseries_irq_domain_ops = {
360 .map = iseries_irq_host_map,
361 .match = iseries_irq_host_match,
362};
363
364/*
365 * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
366 * It must be called before the bus walk.
367 */
368void __init iSeries_init_IRQ(void)
369{
370 /* Register PCI event handler and open an event path */
371 struct irq_domain *host;
372 int ret;
373
374 /*
375 * The Hypervisor only allows us up to 256 interrupt
376 * sources (the irq number is passed in a u8).
377 */
378 irq_set_virq_count(256);
379
380 /* Create irq host. No need for a revmap since HV will give us
381 * back our virtual irq number
382 */
383 host = irq_domain_add_nomap(NULL, &iseries_irq_domain_ops, NULL);
384 BUG_ON(host == NULL);
385 irq_set_default_host(host);
386
387 ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
388 &pci_event_handler);
389 if (ret == 0) {
390 ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
391 if (ret != 0)
392 printk(KERN_ERR "iseries_init_IRQ: open event path "
393 "failed with rc 0x%x\n", ret);
394 } else
395 printk(KERN_ERR "iseries_init_IRQ: register handler "
396 "failed with rc 0x%x\n", ret);
397}
398
399#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
deleted file mode 100644
index a1c236074034..000000000000
--- a/arch/powerpc/platforms/iseries/irq.h
+++ /dev/null
@@ -1,13 +0,0 @@
1#ifndef _ISERIES_IRQ_H
2#define _ISERIES_IRQ_H
3
4#ifdef CONFIG_PCI
5extern void iSeries_init_IRQ(void);
6extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
7extern void iSeries_activate_IRQs(void);
8#else
9#define iSeries_init_IRQ NULL
10#endif
11extern unsigned int iSeries_get_irq(void);
12
13#endif /* _ISERIES_IRQ_H */
diff --git a/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h b/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h
deleted file mode 100644
index 6de9097b7f57..000000000000
--- a/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/*
2 * Copyright (C) 2002 Dave Boutcher IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H
19#define _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H
20
21/*
22 * This struct maps the panel information
23 *
24 * Warning:
25 * This data must match the architecture for the panel information
26 */
27
28#include <asm/types.h>
29
30struct ItExtVpdPanel {
31 /* Definition of the Extended Vpd On Panel Data Area */
32 char systemSerial[8];
33 char mfgID[4];
34 char reserved1[24];
35 char machineType[4];
36 char systemID[6];
37 char somUniqueCnt[4];
38 char serialNumberCount;
39 char reserved2[7];
40 u16 bbu3;
41 u16 bbu2;
42 u16 bbu1;
43 char xLocationLabel[8];
44 u8 xRsvd1[6];
45 u16 xFrameId;
46 u8 xRsvd2[48];
47};
48
49extern struct ItExtVpdPanel xItExtVpdPanel;
50
51#endif /* _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H */
diff --git a/arch/powerpc/platforms/iseries/it_lp_naca.h b/arch/powerpc/platforms/iseries/it_lp_naca.h
deleted file mode 100644
index cf6dcf6ef07b..000000000000
--- a/arch/powerpc/platforms/iseries/it_lp_naca.h
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _PLATFORMS_ISERIES_IT_LP_NACA_H
19#define _PLATFORMS_ISERIES_IT_LP_NACA_H
20
21#include <linux/types.h>
22
23/*
24 * This control block contains the data that is shared between the
25 * hypervisor (PLIC) and the OS.
26 */
27
28struct ItLpNaca {
29// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
30 u32 xDesc; // Eye catcher x00-x03
31 u16 xSize; // Size of this class x04-x05
32 u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07
33 u8 xMaxIntHdlrEntries; // Number of entries in array x08-x08
34 u8 xPrimaryLpIndex; // LP Index of Primary x09-x09
35 u8 xServiceLpIndex; // LP Ind of Service Focal Pointx0A-x0A
36 u8 xLpIndex; // LP Index x0B-x0B
37 u16 xMaxLpQueues; // Number of allocated queues x0C-x0D
38 u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F
39 u8 xPirEnvironMode; // Piranha or hardware x10-x10
40 u8 xPirConsoleMode; // Piranha console indicator x11-x11
41 u8 xPirDasdMode; // Piranha dasd indicator x12-x12
42 u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17
43 u8 flags; // flags, see below x18-x1F
44 u8 xSpVpdFormat; // VPD areas are in CSP format ...
45 u8 xIntProcRatio; // Ratio of int procs to procs ...
46 u8 xRsvd1_2[5]; // Reserved ...
47 u16 xRsvd1_3; // Reserved x20-x21
48 u16 xPlicVrmIndex; // VRM index of PLIC x22-x23
49 u16 xMinSupportedSlicVrmInd;// Min supported OS VRM index x24-x25
50 u16 xMinCompatableSlicVrmInd;// Min compatible OS VRM index x26-x27
51 u64 xLoadAreaAddr; // ER address of load area x28-x2F
52 u32 xLoadAreaChunks; // Chunks for the load area x30-x33
53 u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37
54 // doing an ASR switch on PASE
55 // system call.
56 u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f
57 u8 xRsvd1_4[64]; // x40-x7F
58
59// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
60 u8 xRsvd2_0[128]; // Reserved x00-x7F
61
62// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators
63// NB: Padding required to keep xInterruptHdlr at x300 which is required
64// for v4r4 PLIC.
65 u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F
66 u8 xRsvd3_0[384]; // Reserved 180-2FF
67
68// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt
69// handlers
70 u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF
71};
72
73extern struct ItLpNaca itLpNaca;
74
75#define ITLPNACA_LPAR 0x80 /* Is LPAR installed on the system */
76#define ITLPNACA_PARTITIONED 0x40 /* Is the system partitioned */
77#define ITLPNACA_HWSYNCEDTBS 0x20 /* Hardware synced TBs */
78#define ITLPNACA_HMTINT 0x10 /* Utilize MHT for interrupts */
79
80#endif /* _PLATFORMS_ISERIES_IT_LP_NACA_H */
diff --git a/arch/powerpc/platforms/iseries/ksyms.c b/arch/powerpc/platforms/iseries/ksyms.c
deleted file mode 100644
index 997e234fb8b7..000000000000
--- a/arch/powerpc/platforms/iseries/ksyms.c
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * (C) 2001-2005 PPC 64 Team, IBM Corp
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/export.h>
10
11#include <asm/hw_irq.h>
12#include <asm/iseries/hv_call_sc.h>
13
14EXPORT_SYMBOL(HvCall0);
15EXPORT_SYMBOL(HvCall1);
16EXPORT_SYMBOL(HvCall2);
17EXPORT_SYMBOL(HvCall3);
18EXPORT_SYMBOL(HvCall4);
19EXPORT_SYMBOL(HvCall5);
20EXPORT_SYMBOL(HvCall6);
21EXPORT_SYMBOL(HvCall7);
diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
deleted file mode 100644
index 00e0ec813a1c..000000000000
--- a/arch/powerpc/platforms/iseries/lpardata.c
+++ /dev/null
@@ -1,318 +0,0 @@
1/*
2 * Copyright 2001 Mike Corrigan, IBM Corp
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/types.h>
10#include <linux/threads.h>
11#include <linux/bitops.h>
12#include <asm/processor.h>
13#include <asm/ptrace.h>
14#include <asm/abs_addr.h>
15#include <asm/lppaca.h>
16#include <asm/paca.h>
17#include <asm/iseries/lpar_map.h>
18#include <asm/iseries/it_lp_queue.h>
19#include <asm/iseries/alpaca.h>
20
21#include "naca.h"
22#include "vpd_areas.h"
23#include "spcomm_area.h"
24#include "ipl_parms.h"
25#include "processor_vpd.h"
26#include "release_data.h"
27#include "it_exp_vpd_panel.h"
28#include "it_lp_naca.h"
29
30/* The HvReleaseData is the root of the information shared between
31 * the hypervisor and Linux.
32 */
33const struct HvReleaseData hvReleaseData = {
34 .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */
35 .xSize = sizeof(struct HvReleaseData),
36 .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
37 .xSlicNacaAddr = &naca, /* 64-bit Naca address */
38 .xMsNucDataOffset = LPARMAP_PHYS,
39 .xFlags = HVREL_TAGSINACTIVE /* tags inactive */
40 /* 64 bit */
41 /* shared processors */
42 /* HMT allowed */
43 | 6, /* TEMP: This allows non-GA driver */
44 .xVrmIndex = 4, /* We are v5r2m0 */
45 .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */
46 .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */
47 .xVrmName = { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4.64" ebcdic */
48 0xa7, 0x40, 0xf2, 0x4b,
49 0xf4, 0x4b, 0xf6, 0xf4 },
50};
51
52/*
53 * The NACA. The first dword of the naca is required by the iSeries
54 * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
55 * through the pointer in hvReleaseData.
56 */
57struct naca_struct naca = {
58 .xItVpdAreas = &itVpdAreas,
59 .xRamDisk = 0,
60 .xRamDiskSize = 0,
61};
62
63struct ItLpRegSave {
64 u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003
65 u16 xSize; // Size of this class 004-005
66 u8 xInUse; // Area is live 006-007
67 u8 xRsvd1[9]; // Reserved 007-00F
68
69 u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
70 u32 xCTRL; // Control Register 170-173
71 u32 xDEC; // Decrementer 174-177
72 u32 xFPSCR; // FP Status and Control Reg 178-17B
73 u32 xPVR; // Processor Version Number 17C-17F
74
75 u64 xMMCR0; // Monitor Mode Control Reg 0 180-187
76 u32 xPMC1; // Perf Monitor Counter 1 188-18B
77 u32 xPMC2; // Perf Monitor Counter 2 18C-18F
78 u32 xPMC3; // Perf Monitor Counter 3 190-193
79 u32 xPMC4; // Perf Monitor Counter 4 194-197
80 u32 xPIR; // Processor ID Reg 198-19B
81
82 u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F
83 u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3
84 u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7
85 u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB
86 u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF
87 u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3
88 u32 xTSC; // Thread Switch Control 1B4-1B7
89 u32 xTST; // Thread Switch Timeout 1B8-1BB
90 u32 xRsvd; // Reserved 1BC-1BF
91
92 u64 xACCR; // Address Compare Control Reg 1C0-1C7
93 u64 xIMR; // Instruction Match Register 1C8-1CF
94 u64 xSDR1; // Storage Description Reg 1 1D0-1D7
95 u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF
96 u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7
97 u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF
98 u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7
99 u64 xTB; // Time Base Register 1F8-1FF
100
101 u64 xFPR[32]; // Floating Point Registers 200-2FF
102
103 u64 xMSR; // Machine State Register 300-307
104 u64 xNIA; // Next Instruction Address 308-30F
105
106 u64 xDABR; // Data Address Breakpoint Reg 310-317
107 u64 xIABR; // Inst Address Breakpoint Reg 318-31F
108
109 u64 xHID0; // HW Implementation Dependent0 320-327
110
111 u64 xHID4; // HW Implementation Dependent4 328-32F
112 u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
113 u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
114 u64 xSDAR; // Sample Data Address Register 340-347
115 u64 xSIAR; // Sample Inst Address Register 348-34F
116
117 u8 xRsvd3[176]; // Reserved 350-3FF
118};
119
120extern void system_reset_iSeries(void);
121extern void machine_check_iSeries(void);
122extern void data_access_iSeries(void);
123extern void instruction_access_iSeries(void);
124extern void hardware_interrupt_iSeries(void);
125extern void alignment_iSeries(void);
126extern void program_check_iSeries(void);
127extern void fp_unavailable_iSeries(void);
128extern void decrementer_iSeries(void);
129extern void trap_0a_iSeries(void);
130extern void trap_0b_iSeries(void);
131extern void system_call_iSeries(void);
132extern void single_step_iSeries(void);
133extern void trap_0e_iSeries(void);
134extern void performance_monitor_iSeries(void);
135extern void data_access_slb_iSeries(void);
136extern void instruction_access_slb_iSeries(void);
137
138struct ItLpNaca itLpNaca = {
139 .xDesc = 0xd397d581, /* "LpNa" ebcdic */
140 .xSize = 0x0400, /* size of ItLpNaca */
141 .xIntHdlrOffset = 0x0300, /* offset to int array */
142 .xMaxIntHdlrEntries = 19, /* # ents */
143 .xPrimaryLpIndex = 0, /* Part # of primary */
144 .xServiceLpIndex = 0, /* Part # of serv */
145 .xLpIndex = 0, /* Part # of me */
146 .xMaxLpQueues = 0, /* # of LP queues */
147 .xLpQueueOffset = 0x100, /* offset of start of LP queues */
148 .xPirEnvironMode = 0, /* Piranha stuff */
149 .xPirConsoleMode = 0,
150 .xPirDasdMode = 0,
151 .flags = 0,
152 .xSpVpdFormat = 0,
153 .xIntProcRatio = 0,
154 .xPlicVrmIndex = 0, /* VRM index of PLIC */
155 .xMinSupportedSlicVrmInd = 0, /* min supported SLIC */
156 .xMinCompatableSlicVrmInd = 0, /* min compat SLIC */
157 .xLoadAreaAddr = 0, /* 64-bit addr of load area */
158 .xLoadAreaChunks = 0, /* chunks for load area */
159 .xPaseSysCallCRMask = 0, /* PASE mask */
160 .xSlicSegmentTablePtr = 0, /* seg table */
161 .xOldLpQueue = { 0 }, /* Old LP Queue */
162 .xInterruptHdlr = {
163 (u64)system_reset_iSeries, /* 0x100 System Reset */
164 (u64)machine_check_iSeries, /* 0x200 Machine Check */
165 (u64)data_access_iSeries, /* 0x300 Data Access */
166 (u64)instruction_access_iSeries, /* 0x400 Instruction Access */
167 (u64)hardware_interrupt_iSeries, /* 0x500 External */
168 (u64)alignment_iSeries, /* 0x600 Alignment */
169 (u64)program_check_iSeries, /* 0x700 Program Check */
170 (u64)fp_unavailable_iSeries, /* 0x800 FP Unavailable */
171 (u64)decrementer_iSeries, /* 0x900 Decrementer */
172 (u64)trap_0a_iSeries, /* 0xa00 Trap 0A */
173 (u64)trap_0b_iSeries, /* 0xb00 Trap 0B */
174 (u64)system_call_iSeries, /* 0xc00 System Call */
175 (u64)single_step_iSeries, /* 0xd00 Single Step */
176 (u64)trap_0e_iSeries, /* 0xe00 Trap 0E */
177 (u64)performance_monitor_iSeries,/* 0xf00 Performance Monitor */
178 0, /* int 0x1000 */
179 0, /* int 0x1010 */
180 0, /* int 0x1020 CPU ctls */
181 (u64)hardware_interrupt_iSeries, /* SC Ret Hdlr */
182 (u64)data_access_slb_iSeries, /* 0x380 D-SLB */
183 (u64)instruction_access_slb_iSeries /* 0x480 I-SLB */
184 }
185};
186
187/* May be filled in by the hypervisor so cannot end up in the BSS */
188static struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data")));
189
190/* May be filled in by the hypervisor so cannot end up in the BSS */
191struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data")));
192
193#define maxPhysicalProcessors 32
194
195struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
196 {
197 .xInstCacheOperandSize = 32,
198 .xDataCacheOperandSize = 32,
199 .xProcFreq = 50000000,
200 .xTimeBaseFreq = 50000000,
201 .xPVR = 0x3600
202 }
203};
204
205/* Space for Main Store Vpd 27,200 bytes */
206/* May be filled in by the hypervisor so cannot end up in the BSS */
207u64 xMsVpd[3400] __attribute__((__section__(".data")));
208
209/* Space for Recovery Log Buffer */
210/* May be filled in by the hypervisor so cannot end up in the BSS */
211static u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data")));
212
213static const struct SpCommArea xSpCommArea = {
214 .xDesc = 0xE2D7C3C2,
215 .xFormat = 1,
216};
217
218static const struct ItLpRegSave iseries_reg_save[] = {
219 [0 ... (NR_CPUS-1)] = {
220 .xDesc = 0xd397d9e2, /* "LpRS" */
221 .xSize = sizeof(struct ItLpRegSave),
222 },
223};
224
225#define ALPACA_INIT(number) \
226{ \
227 .lppaca_ptr = &lppaca[number], \
228 .reg_save_ptr = &iseries_reg_save[number], \
229}
230
231const struct alpaca alpaca[] = {
232 ALPACA_INIT( 0),
233#if NR_CPUS > 1
234 ALPACA_INIT( 1), ALPACA_INIT( 2), ALPACA_INIT( 3),
235#if NR_CPUS > 4
236 ALPACA_INIT( 4), ALPACA_INIT( 5), ALPACA_INIT( 6), ALPACA_INIT( 7),
237#if NR_CPUS > 8
238 ALPACA_INIT( 8), ALPACA_INIT( 9), ALPACA_INIT(10), ALPACA_INIT(11),
239 ALPACA_INIT(12), ALPACA_INIT(13), ALPACA_INIT(14), ALPACA_INIT(15),
240 ALPACA_INIT(16), ALPACA_INIT(17), ALPACA_INIT(18), ALPACA_INIT(19),
241 ALPACA_INIT(20), ALPACA_INIT(21), ALPACA_INIT(22), ALPACA_INIT(23),
242 ALPACA_INIT(24), ALPACA_INIT(25), ALPACA_INIT(26), ALPACA_INIT(27),
243 ALPACA_INIT(28), ALPACA_INIT(29), ALPACA_INIT(30), ALPACA_INIT(31),
244#if NR_CPUS > 32
245 ALPACA_INIT(32), ALPACA_INIT(33), ALPACA_INIT(34), ALPACA_INIT(35),
246 ALPACA_INIT(36), ALPACA_INIT(37), ALPACA_INIT(38), ALPACA_INIT(39),
247 ALPACA_INIT(40), ALPACA_INIT(41), ALPACA_INIT(42), ALPACA_INIT(43),
248 ALPACA_INIT(44), ALPACA_INIT(45), ALPACA_INIT(46), ALPACA_INIT(47),
249 ALPACA_INIT(48), ALPACA_INIT(49), ALPACA_INIT(50), ALPACA_INIT(51),
250 ALPACA_INIT(52), ALPACA_INIT(53), ALPACA_INIT(54), ALPACA_INIT(55),
251 ALPACA_INIT(56), ALPACA_INIT(57), ALPACA_INIT(58), ALPACA_INIT(59),
252 ALPACA_INIT(60), ALPACA_INIT(61), ALPACA_INIT(62), ALPACA_INIT(63),
253#endif
254#endif
255#endif
256#endif
257};
258
259/* The LparMap data is now located at offset 0x6000 in head.S
260 * It was put there so that the HvReleaseData could address it
261 * with a 32-bit offset as required by the iSeries hypervisor
262 *
263 * The Naca has a pointer to the ItVpdAreas. The hypervisor finds
264 * the Naca via the HvReleaseData area. The HvReleaseData has the
265 * offset into the Naca of the pointer to the ItVpdAreas.
266 */
267const struct ItVpdAreas itVpdAreas = {
268 .xSlicDesc = 0xc9a3e5c1, /* "ItVA" */
269 .xSlicSize = sizeof(struct ItVpdAreas),
270 .xSlicVpdEntries = ItVpdMaxEntries, /* # VPD array entries */
271 .xSlicDmaEntries = ItDmaMaxEntries, /* # DMA array entries */
272 .xSlicMaxLogicalProcs = NR_CPUS * 2, /* Max logical procs */
273 .xSlicMaxPhysicalProcs = maxPhysicalProcessors, /* Max physical procs */
274 .xSlicDmaToksOffset = offsetof(struct ItVpdAreas, xPlicDmaToks),
275 .xSlicVpdAdrsOffset = offsetof(struct ItVpdAreas, xSlicVpdAdrs),
276 .xSlicDmaLensOffset = offsetof(struct ItVpdAreas, xPlicDmaLens),
277 .xSlicVpdLensOffset = offsetof(struct ItVpdAreas, xSlicVpdLens),
278 .xSlicMaxSlotLabels = 0, /* max slot labels */
279 .xSlicMaxLpQueues = 1, /* max LP queues */
280 .xPlicDmaLens = { 0 }, /* DMA lengths */
281 .xPlicDmaToks = { 0 }, /* DMA tokens */
282 .xSlicVpdLens = { /* VPD lengths */
283 0,0,0, /* 0 - 2 */
284 sizeof(xItExtVpdPanel), /* 3 Extended VPD */
285 sizeof(struct alpaca), /* 4 length of (fake) Paca */
286 0, /* 5 */
287 sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */
288 26992, /* 7 length of MS VPD */
289 0, /* 8 */
290 sizeof(struct ItLpNaca),/* 9 length of LP Naca */
291 0, /* 10 */
292 256, /* 11 length of Recovery Log Buf */
293 sizeof(struct SpCommArea), /* 12 length of SP Comm Area */
294 0,0,0, /* 13 - 15 */
295 sizeof(struct IoHriProcessorVpd),/* 16 length of Proc Vpd */
296 0,0,0,0,0,0, /* 17 - 22 */
297 sizeof(struct hvlpevent_queue), /* 23 length of Lp Queue */
298 0,0 /* 24 - 25 */
299 },
300 .xSlicVpdAdrs = { /* VPD addresses */
301 0,0,0, /* 0 - 2 */
302 &xItExtVpdPanel, /* 3 Extended VPD */
303 &alpaca[0], /* 4 first (fake) Paca */
304 0, /* 5 */
305 &xItIplParmsReal, /* 6 IPL parms */
306 &xMsVpd, /* 7 MS Vpd */
307 0, /* 8 */
308 &itLpNaca, /* 9 LpNaca */
309 0, /* 10 */
310 &xRecoveryLogBuffer, /* 11 Recovery Log Buffer */
311 &xSpCommArea, /* 12 SP Comm Area */
312 0,0,0, /* 13 - 15 */
313 &xIoHriProcessorVpd, /* 16 Proc Vpd */
314 0,0,0,0,0,0, /* 17 - 22 */
315 &hvlpevent_queue, /* 23 Lp Queue */
316 0,0
317 }
318};
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
deleted file mode 100644
index 202e22798d30..000000000000
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ /dev/null
@@ -1,341 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <linux/stddef.h>
11#include <linux/kernel.h>
12#include <linux/sched.h>
13#include <linux/bootmem.h>
14#include <linux/seq_file.h>
15#include <linux/proc_fs.h>
16#include <linux/export.h>
17
18#include <asm/system.h>
19#include <asm/paca.h>
20#include <asm/firmware.h>
21#include <asm/iseries/it_lp_queue.h>
22#include <asm/iseries/hv_lp_event.h>
23#include <asm/iseries/hv_call_event.h>
24#include "it_lp_naca.h"
25
26/*
27 * The LpQueue is used to pass event data from the hypervisor to
28 * the partition. This is where I/O interrupt events are communicated.
29 *
30 * It is written to by the hypervisor so cannot end up in the BSS.
31 */
32struct hvlpevent_queue hvlpevent_queue __attribute__((__section__(".data")));
33
34DEFINE_PER_CPU(unsigned long[HvLpEvent_Type_NumTypes], hvlpevent_counts);
35
36static char *event_types[HvLpEvent_Type_NumTypes] = {
37 "Hypervisor",
38 "Machine Facilities",
39 "Session Manager",
40 "SPD I/O",
41 "Virtual Bus",
42 "PCI I/O",
43 "RIO I/O",
44 "Virtual Lan",
45 "Virtual I/O"
46};
47
48/* Array of LpEvent handler functions */
49static LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
50static unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
51
52static struct HvLpEvent * get_next_hvlpevent(void)
53{
54 struct HvLpEvent * event;
55 event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
56
57 if (hvlpevent_is_valid(event)) {
58 /* rmb() needed only for weakly consistent machines (regatta) */
59 rmb();
60 /* Set pointer to next potential event */
61 hvlpevent_queue.hq_current_event += ((event->xSizeMinus1 +
62 IT_LP_EVENT_ALIGN) / IT_LP_EVENT_ALIGN) *
63 IT_LP_EVENT_ALIGN;
64
65 /* Wrap to beginning if no room at end */
66 if (hvlpevent_queue.hq_current_event >
67 hvlpevent_queue.hq_last_event) {
68 hvlpevent_queue.hq_current_event =
69 hvlpevent_queue.hq_event_stack;
70 }
71 } else {
72 event = NULL;
73 }
74
75 return event;
76}
77
78static unsigned long spread_lpevents = NR_CPUS;
79
80int hvlpevent_is_pending(void)
81{
82 struct HvLpEvent *next_event;
83
84 if (smp_processor_id() >= spread_lpevents)
85 return 0;
86
87 next_event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
88
89 return hvlpevent_is_valid(next_event) ||
90 hvlpevent_queue.hq_overflow_pending;
91}
92
93static void hvlpevent_clear_valid(struct HvLpEvent * event)
94{
95 /* Tell the Hypervisor that we're done with this event.
96 * Also clear bits within this event that might look like valid bits.
97 * ie. on 64-byte boundaries.
98 */
99 struct HvLpEvent *tmp;
100 unsigned extra = ((event->xSizeMinus1 + IT_LP_EVENT_ALIGN) /
101 IT_LP_EVENT_ALIGN) - 1;
102
103 switch (extra) {
104 case 3:
105 tmp = (struct HvLpEvent*)((char*)event + 3 * IT_LP_EVENT_ALIGN);
106 hvlpevent_invalidate(tmp);
107 case 2:
108 tmp = (struct HvLpEvent*)((char*)event + 2 * IT_LP_EVENT_ALIGN);
109 hvlpevent_invalidate(tmp);
110 case 1:
111 tmp = (struct HvLpEvent*)((char*)event + 1 * IT_LP_EVENT_ALIGN);
112 hvlpevent_invalidate(tmp);
113 }
114
115 mb();
116
117 hvlpevent_invalidate(event);
118}
119
120void process_hvlpevents(void)
121{
122 struct HvLpEvent * event;
123
124 restart:
125 /* If we have recursed, just return */
126 if (!spin_trylock(&hvlpevent_queue.hq_lock))
127 return;
128
129 for (;;) {
130 event = get_next_hvlpevent();
131 if (event) {
132 /* Call appropriate handler here, passing
133 * a pointer to the LpEvent. The handler
134 * must make a copy of the LpEvent if it
135 * needs it in a bottom half. (perhaps for
136 * an ACK)
137 *
138 * Handlers are responsible for ACK processing
139 *
140 * The Hypervisor guarantees that LpEvents will
141 * only be delivered with types that we have
142 * registered for, so no type check is necessary
143 * here!
144 */
145 if (event->xType < HvLpEvent_Type_NumTypes)
146 __get_cpu_var(hvlpevent_counts)[event->xType]++;
147 if (event->xType < HvLpEvent_Type_NumTypes &&
148 lpEventHandler[event->xType])
149 lpEventHandler[event->xType](event);
150 else {
151 u8 type = event->xType;
152
153 /*
154 * Don't printk in the spinlock as printk
155 * may require ack events form the HV to send
156 * any characters there.
157 */
158 hvlpevent_clear_valid(event);
159 spin_unlock(&hvlpevent_queue.hq_lock);
160 printk(KERN_INFO
161 "Unexpected Lp Event type=%d\n", type);
162 goto restart;
163 }
164
165 hvlpevent_clear_valid(event);
166 } else if (hvlpevent_queue.hq_overflow_pending)
167 /*
168 * No more valid events. If overflow events are
169 * pending process them
170 */
171 HvCallEvent_getOverflowLpEvents(hvlpevent_queue.hq_index);
172 else
173 break;
174 }
175
176 spin_unlock(&hvlpevent_queue.hq_lock);
177}
178
179static int set_spread_lpevents(char *str)
180{
181 unsigned long val = simple_strtoul(str, NULL, 0);
182
183 /*
184 * The parameter is the number of processors to share in processing
185 * lp events.
186 */
187 if (( val > 0) && (val <= NR_CPUS)) {
188 spread_lpevents = val;
189 printk("lpevent processing spread over %ld processors\n", val);
190 } else {
191 printk("invalid spread_lpevents %ld\n", val);
192 }
193
194 return 1;
195}
196__setup("spread_lpevents=", set_spread_lpevents);
197
198void __init setup_hvlpevent_queue(void)
199{
200 void *eventStack;
201
202 spin_lock_init(&hvlpevent_queue.hq_lock);
203
204 /* Allocate a page for the Event Stack. */
205 eventStack = alloc_bootmem_pages(IT_LP_EVENT_STACK_SIZE);
206 memset(eventStack, 0, IT_LP_EVENT_STACK_SIZE);
207
208 /* Invoke the hypervisor to initialize the event stack */
209 HvCallEvent_setLpEventStack(0, eventStack, IT_LP_EVENT_STACK_SIZE);
210
211 hvlpevent_queue.hq_event_stack = eventStack;
212 hvlpevent_queue.hq_current_event = eventStack;
213 hvlpevent_queue.hq_last_event = (char *)eventStack +
214 (IT_LP_EVENT_STACK_SIZE - IT_LP_EVENT_MAX_SIZE);
215 hvlpevent_queue.hq_index = 0;
216}
217
218/* Register a handler for an LpEvent type */
219int HvLpEvent_registerHandler(HvLpEvent_Type eventType, LpEventHandler handler)
220{
221 if (eventType < HvLpEvent_Type_NumTypes) {
222 lpEventHandler[eventType] = handler;
223 return 0;
224 }
225 return 1;
226}
227EXPORT_SYMBOL(HvLpEvent_registerHandler);
228
229int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType)
230{
231 might_sleep();
232
233 if (eventType < HvLpEvent_Type_NumTypes) {
234 if (!lpEventHandlerPaths[eventType]) {
235 lpEventHandler[eventType] = NULL;
236 /*
237 * We now sleep until all other CPUs have scheduled.
238 * This ensures that the deletion is seen by all
239 * other CPUs, and that the deleted handler isn't
240 * still running on another CPU when we return.
241 */
242 synchronize_sched();
243 return 0;
244 }
245 }
246 return 1;
247}
248EXPORT_SYMBOL(HvLpEvent_unregisterHandler);
249
250/*
251 * lpIndex is the partition index of the target partition.
252 * needed only for VirtualIo, VirtualLan and SessionMgr. Zero
253 * indicates to use our partition index - for the other types.
254 */
255int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex)
256{
257 if ((eventType < HvLpEvent_Type_NumTypes) &&
258 lpEventHandler[eventType]) {
259 if (lpIndex == 0)
260 lpIndex = itLpNaca.xLpIndex;
261 HvCallEvent_openLpEventPath(lpIndex, eventType);
262 ++lpEventHandlerPaths[eventType];
263 return 0;
264 }
265 return 1;
266}
267
268int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex)
269{
270 if ((eventType < HvLpEvent_Type_NumTypes) &&
271 lpEventHandler[eventType] &&
272 lpEventHandlerPaths[eventType]) {
273 if (lpIndex == 0)
274 lpIndex = itLpNaca.xLpIndex;
275 HvCallEvent_closeLpEventPath(lpIndex, eventType);
276 --lpEventHandlerPaths[eventType];
277 return 0;
278 }
279 return 1;
280}
281
282static int proc_lpevents_show(struct seq_file *m, void *v)
283{
284 int cpu, i;
285 unsigned long sum;
286 static unsigned long cpu_totals[NR_CPUS];
287
288 /* FIXME: do we care that there's no locking here? */
289 sum = 0;
290 for_each_online_cpu(cpu) {
291 cpu_totals[cpu] = 0;
292 for (i = 0; i < HvLpEvent_Type_NumTypes; i++) {
293 cpu_totals[cpu] += per_cpu(hvlpevent_counts, cpu)[i];
294 }
295 sum += cpu_totals[cpu];
296 }
297
298 seq_printf(m, "LpEventQueue 0\n");
299 seq_printf(m, " events processed:\t%lu\n", sum);
300
301 for (i = 0; i < HvLpEvent_Type_NumTypes; ++i) {
302 sum = 0;
303 for_each_online_cpu(cpu) {
304 sum += per_cpu(hvlpevent_counts, cpu)[i];
305 }
306
307 seq_printf(m, " %-20s %10lu\n", event_types[i], sum);
308 }
309
310 seq_printf(m, "\n events processed by processor:\n");
311
312 for_each_online_cpu(cpu) {
313 seq_printf(m, " CPU%02d %10lu\n", cpu, cpu_totals[cpu]);
314 }
315
316 return 0;
317}
318
319static int proc_lpevents_open(struct inode *inode, struct file *file)
320{
321 return single_open(file, proc_lpevents_show, NULL);
322}
323
324static const struct file_operations proc_lpevents_operations = {
325 .open = proc_lpevents_open,
326 .read = seq_read,
327 .llseek = seq_lseek,
328 .release = single_release,
329};
330
331static int __init proc_lpevents_init(void)
332{
333 if (!firmware_has_feature(FW_FEATURE_ISERIES))
334 return 0;
335
336 proc_create("iSeries/lpevents", S_IFREG|S_IRUGO, NULL,
337 &proc_lpevents_operations);
338 return 0;
339}
340__initcall(proc_lpevents_init);
341
diff --git a/arch/powerpc/platforms/iseries/main_store.h b/arch/powerpc/platforms/iseries/main_store.h
deleted file mode 100644
index 1a7a3f50e40b..000000000000
--- a/arch/powerpc/platforms/iseries/main_store.h
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#ifndef _ISERIES_MAIN_STORE_H
20#define _ISERIES_MAIN_STORE_H
21
22/* Main Store Vpd for Condor,iStar,sStar */
23struct IoHriMainStoreSegment4 {
24 u8 msArea0Exists:1;
25 u8 msArea1Exists:1;
26 u8 msArea2Exists:1;
27 u8 msArea3Exists:1;
28 u8 reserved1:4;
29 u8 reserved2;
30
31 u8 msArea0Functional:1;
32 u8 msArea1Functional:1;
33 u8 msArea2Functional:1;
34 u8 msArea3Functional:1;
35 u8 reserved3:4;
36 u8 reserved4;
37
38 u32 totalMainStore;
39
40 u64 msArea0Ptr;
41 u64 msArea1Ptr;
42 u64 msArea2Ptr;
43 u64 msArea3Ptr;
44
45 u32 cardProductionLevel;
46
47 u32 msAdrHole;
48
49 u8 msArea0HasRiserVpd:1;
50 u8 msArea1HasRiserVpd:1;
51 u8 msArea2HasRiserVpd:1;
52 u8 msArea3HasRiserVpd:1;
53 u8 reserved5:4;
54 u8 reserved6;
55 u16 reserved7;
56
57 u8 reserved8[28];
58
59 u64 nonInterleavedBlocksStartAdr;
60 u64 nonInterleavedBlocksEndAdr;
61};
62
63/* Main Store VPD for Power4 */
64struct __attribute((packed)) IoHriMainStoreChipInfo1 {
65 u32 chipMfgID;
66 char chipECLevel[4];
67};
68
69struct IoHriMainStoreVpdIdData {
70 char typeNumber[4];
71 char modelNumber[4];
72 char partNumber[12];
73 char serialNumber[12];
74};
75
76struct __attribute((packed)) IoHriMainStoreVpdFruData {
77 char fruLabel[8];
78 u8 numberOfSlots;
79 u8 pluggingType;
80 u16 slotMapIndex;
81};
82
83struct __attribute((packed)) IoHriMainStoreAdrRangeBlock {
84 void *blockStart;
85 void *blockEnd;
86 u32 blockProcChipId;
87};
88
89#define MaxAreaAdrRangeBlocks 4
90
91struct __attribute((packed)) IoHriMainStoreArea4 {
92 u32 msVpdFormat;
93 u8 containedVpdType;
94 u8 reserved1;
95 u16 reserved2;
96
97 u64 msExists;
98 u64 msFunctional;
99
100 u32 memorySize;
101 u32 procNodeId;
102
103 u32 numAdrRangeBlocks;
104 struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks];
105
106 struct IoHriMainStoreChipInfo1 chipInfo0;
107 struct IoHriMainStoreChipInfo1 chipInfo1;
108 struct IoHriMainStoreChipInfo1 chipInfo2;
109 struct IoHriMainStoreChipInfo1 chipInfo3;
110 struct IoHriMainStoreChipInfo1 chipInfo4;
111 struct IoHriMainStoreChipInfo1 chipInfo5;
112 struct IoHriMainStoreChipInfo1 chipInfo6;
113 struct IoHriMainStoreChipInfo1 chipInfo7;
114
115 void *msRamAreaArray;
116 u32 msRamAreaArrayNumEntries;
117 u32 msRamAreaArrayEntrySize;
118
119 u32 numaDimmExists;
120 u32 numaDimmFunctional;
121 void *numaDimmArray;
122 u32 numaDimmArrayNumEntries;
123 u32 numaDimmArrayEntrySize;
124
125 struct IoHriMainStoreVpdIdData idData;
126
127 u64 powerData;
128 u64 cardAssemblyPartNum;
129 u64 chipSerialNum;
130
131 u64 reserved3;
132 char reserved4[16];
133
134 struct IoHriMainStoreVpdFruData fruData;
135
136 u8 vpdPortNum;
137 u8 reserved5;
138 u8 frameId;
139 u8 rackUnit;
140 char asciiKeywordVpd[256];
141 u32 reserved6;
142};
143
144
145struct IoHriMainStoreSegment5 {
146 u16 reserved1;
147 u8 reserved2;
148 u8 msVpdFormat;
149
150 u32 totalMainStore;
151 u64 maxConfiguredMsAdr;
152
153 struct IoHriMainStoreArea4 *msAreaArray;
154 u32 msAreaArrayNumEntries;
155 u32 msAreaArrayEntrySize;
156
157 u32 msAreaExists;
158 u32 msAreaFunctional;
159
160 u64 reserved3;
161};
162
163extern u64 xMsVpd[];
164
165#endif /* _ISERIES_MAIN_STORE_H */
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
deleted file mode 100644
index 254c1fc3d8dd..000000000000
--- a/arch/powerpc/platforms/iseries/mf.c
+++ /dev/null
@@ -1,1275 +0,0 @@
1/*
2 * Copyright (C) 2001 Troy D. Armstrong IBM Corporation
3 * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
4 *
5 * This modules exists as an interface between a Linux secondary partition
6 * running on an iSeries and the primary partition's Virtual Service
7 * Processor (VSP) object. The VSP has final authority over powering on/off
8 * all partitions in the iSeries. It also provides miscellaneous low-level
9 * machine facility type operations.
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#include <linux/types.h>
28#include <linux/errno.h>
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <linux/completion.h>
32#include <linux/delay.h>
33#include <linux/export.h>
34#include <linux/proc_fs.h>
35#include <linux/dma-mapping.h>
36#include <linux/bcd.h>
37#include <linux/rtc.h>
38#include <linux/slab.h>
39
40#include <asm/time.h>
41#include <asm/uaccess.h>
42#include <asm/paca.h>
43#include <asm/abs_addr.h>
44#include <asm/firmware.h>
45#include <asm/iseries/mf.h>
46#include <asm/iseries/hv_lp_config.h>
47#include <asm/iseries/hv_lp_event.h>
48#include <asm/iseries/it_lp_queue.h>
49
50#include "setup.h"
51
52static int mf_initialized;
53
54/*
55 * This is the structure layout for the Machine Facilities LPAR event
56 * flows.
57 */
58struct vsp_cmd_data {
59 u64 token;
60 u16 cmd;
61 HvLpIndex lp_index;
62 u8 result_code;
63 u32 reserved;
64 union {
65 u64 state; /* GetStateOut */
66 u64 ipl_type; /* GetIplTypeOut, Function02SelectIplTypeIn */
67 u64 ipl_mode; /* GetIplModeOut, Function02SelectIplModeIn */
68 u64 page[4]; /* GetSrcHistoryIn */
69 u64 flag; /* GetAutoIplWhenPrimaryIplsOut,
70 SetAutoIplWhenPrimaryIplsIn,
71 WhiteButtonPowerOffIn,
72 Function08FastPowerOffIn,
73 IsSpcnRackPowerIncompleteOut */
74 struct {
75 u64 token;
76 u64 address_type;
77 u64 side;
78 u32 length;
79 u32 offset;
80 } kern; /* SetKernelImageIn, GetKernelImageIn,
81 SetKernelCmdLineIn, GetKernelCmdLineIn */
82 u32 length_out; /* GetKernelImageOut, GetKernelCmdLineOut */
83 u8 reserved[80];
84 } sub_data;
85};
86
87struct vsp_rsp_data {
88 struct completion com;
89 struct vsp_cmd_data *response;
90};
91
92struct alloc_data {
93 u16 size;
94 u16 type;
95 u32 count;
96 u16 reserved1;
97 u8 reserved2;
98 HvLpIndex target_lp;
99};
100
101struct ce_msg_data;
102
103typedef void (*ce_msg_comp_hdlr)(void *token, struct ce_msg_data *vsp_cmd_rsp);
104
105struct ce_msg_comp_data {
106 ce_msg_comp_hdlr handler;
107 void *token;
108};
109
110struct ce_msg_data {
111 u8 ce_msg[12];
112 char reserved[4];
113 struct ce_msg_comp_data *completion;
114};
115
116struct io_mf_lp_event {
117 struct HvLpEvent hp_lp_event;
118 u16 subtype_result_code;
119 u16 reserved1;
120 u32 reserved2;
121 union {
122 struct alloc_data alloc;
123 struct ce_msg_data ce_msg;
124 struct vsp_cmd_data vsp_cmd;
125 } data;
126};
127
128#define subtype_data(a, b, c, d) \
129 (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
130
131/*
132 * All outgoing event traffic is kept on a FIFO queue. The first
133 * pointer points to the one that is outstanding, and all new
134 * requests get stuck on the end. Also, we keep a certain number of
135 * preallocated pending events so that we can operate very early in
136 * the boot up sequence (before kmalloc is ready).
137 */
138struct pending_event {
139 struct pending_event *next;
140 struct io_mf_lp_event event;
141 MFCompleteHandler hdlr;
142 char dma_data[72];
143 unsigned dma_data_length;
144 unsigned remote_address;
145};
146static spinlock_t pending_event_spinlock;
147static struct pending_event *pending_event_head;
148static struct pending_event *pending_event_tail;
149static struct pending_event *pending_event_avail;
150#define PENDING_EVENT_PREALLOC_LEN 16
151static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN];
152
153/*
154 * Put a pending event onto the available queue, so it can get reused.
155 * Attention! You must have the pending_event_spinlock before calling!
156 */
157static void free_pending_event(struct pending_event *ev)
158{
159 if (ev != NULL) {
160 ev->next = pending_event_avail;
161 pending_event_avail = ev;
162 }
163}
164
165/*
166 * Enqueue the outbound event onto the stack. If the queue was
167 * empty to begin with, we must also issue it via the Hypervisor
168 * interface. There is a section of code below that will touch
169 * the first stack pointer without the protection of the pending_event_spinlock.
170 * This is OK, because we know that nobody else will be modifying
171 * the first pointer when we do this.
172 */
173static int signal_event(struct pending_event *ev)
174{
175 int rc = 0;
176 unsigned long flags;
177 int go = 1;
178 struct pending_event *ev1;
179 HvLpEvent_Rc hv_rc;
180
181 /* enqueue the event */
182 if (ev != NULL) {
183 ev->next = NULL;
184 spin_lock_irqsave(&pending_event_spinlock, flags);
185 if (pending_event_head == NULL)
186 pending_event_head = ev;
187 else {
188 go = 0;
189 pending_event_tail->next = ev;
190 }
191 pending_event_tail = ev;
192 spin_unlock_irqrestore(&pending_event_spinlock, flags);
193 }
194
195 /* send the event */
196 while (go) {
197 go = 0;
198
199 /* any DMA data to send beforehand? */
200 if (pending_event_head->dma_data_length > 0)
201 HvCallEvent_dmaToSp(pending_event_head->dma_data,
202 pending_event_head->remote_address,
203 pending_event_head->dma_data_length,
204 HvLpDma_Direction_LocalToRemote);
205
206 hv_rc = HvCallEvent_signalLpEvent(
207 &pending_event_head->event.hp_lp_event);
208 if (hv_rc != HvLpEvent_Rc_Good) {
209 printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() "
210 "failed with %d\n", (int)hv_rc);
211
212 spin_lock_irqsave(&pending_event_spinlock, flags);
213 ev1 = pending_event_head;
214 pending_event_head = pending_event_head->next;
215 if (pending_event_head != NULL)
216 go = 1;
217 spin_unlock_irqrestore(&pending_event_spinlock, flags);
218
219 if (ev1 == ev)
220 rc = -EIO;
221 else if (ev1->hdlr != NULL)
222 (*ev1->hdlr)((void *)ev1->event.hp_lp_event.xCorrelationToken, -EIO);
223
224 spin_lock_irqsave(&pending_event_spinlock, flags);
225 free_pending_event(ev1);
226 spin_unlock_irqrestore(&pending_event_spinlock, flags);
227 }
228 }
229
230 return rc;
231}
232
233/*
234 * Allocate a new pending_event structure, and initialize it.
235 */
236static struct pending_event *new_pending_event(void)
237{
238 struct pending_event *ev = NULL;
239 HvLpIndex primary_lp = HvLpConfig_getPrimaryLpIndex();
240 unsigned long flags;
241 struct HvLpEvent *hev;
242
243 spin_lock_irqsave(&pending_event_spinlock, flags);
244 if (pending_event_avail != NULL) {
245 ev = pending_event_avail;
246 pending_event_avail = pending_event_avail->next;
247 }
248 spin_unlock_irqrestore(&pending_event_spinlock, flags);
249 if (ev == NULL) {
250 ev = kmalloc(sizeof(struct pending_event), GFP_ATOMIC);
251 if (ev == NULL) {
252 printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n",
253 sizeof(struct pending_event));
254 return NULL;
255 }
256 }
257 memset(ev, 0, sizeof(struct pending_event));
258 hev = &ev->event.hp_lp_event;
259 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | HV_LP_EVENT_INT;
260 hev->xType = HvLpEvent_Type_MachineFac;
261 hev->xSourceLp = HvLpConfig_getLpIndex();
262 hev->xTargetLp = primary_lp;
263 hev->xSizeMinus1 = sizeof(ev->event) - 1;
264 hev->xRc = HvLpEvent_Rc_Good;
265 hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primary_lp,
266 HvLpEvent_Type_MachineFac);
267 hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primary_lp,
268 HvLpEvent_Type_MachineFac);
269
270 return ev;
271}
272
273static int __maybe_unused
274signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
275{
276 struct pending_event *ev = new_pending_event();
277 int rc;
278 struct vsp_rsp_data response;
279
280 if (ev == NULL)
281 return -ENOMEM;
282
283 init_completion(&response.com);
284 response.response = vsp_cmd;
285 ev->event.hp_lp_event.xSubtype = 6;
286 ev->event.hp_lp_event.x.xSubtypeData =
287 subtype_data('M', 'F', 'V', 'I');
288 ev->event.data.vsp_cmd.token = (u64)&response;
289 ev->event.data.vsp_cmd.cmd = vsp_cmd->cmd;
290 ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
291 ev->event.data.vsp_cmd.result_code = 0xFF;
292 ev->event.data.vsp_cmd.reserved = 0;
293 memcpy(&(ev->event.data.vsp_cmd.sub_data),
294 &(vsp_cmd->sub_data), sizeof(vsp_cmd->sub_data));
295 mb();
296
297 rc = signal_event(ev);
298 if (rc == 0)
299 wait_for_completion(&response.com);
300 return rc;
301}
302
303
304/*
305 * Send a 12-byte CE message to the primary partition VSP object
306 */
307static int signal_ce_msg(char *ce_msg, struct ce_msg_comp_data *completion)
308{
309 struct pending_event *ev = new_pending_event();
310
311 if (ev == NULL)
312 return -ENOMEM;
313
314 ev->event.hp_lp_event.xSubtype = 0;
315 ev->event.hp_lp_event.x.xSubtypeData =
316 subtype_data('M', 'F', 'C', 'E');
317 memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
318 ev->event.data.ce_msg.completion = completion;
319 return signal_event(ev);
320}
321
322/*
323 * Send a 12-byte CE message (with no data) to the primary partition VSP object
324 */
325static int signal_ce_msg_simple(u8 ce_op, struct ce_msg_comp_data *completion)
326{
327 u8 ce_msg[12];
328
329 memset(ce_msg, 0, sizeof(ce_msg));
330 ce_msg[3] = ce_op;
331 return signal_ce_msg(ce_msg, completion);
332}
333
334/*
335 * Send a 12-byte CE message and DMA data to the primary partition VSP object
336 */
337static int dma_and_signal_ce_msg(char *ce_msg,
338 struct ce_msg_comp_data *completion, void *dma_data,
339 unsigned dma_data_length, unsigned remote_address)
340{
341 struct pending_event *ev = new_pending_event();
342
343 if (ev == NULL)
344 return -ENOMEM;
345
346 ev->event.hp_lp_event.xSubtype = 0;
347 ev->event.hp_lp_event.x.xSubtypeData =
348 subtype_data('M', 'F', 'C', 'E');
349 memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
350 ev->event.data.ce_msg.completion = completion;
351 memcpy(ev->dma_data, dma_data, dma_data_length);
352 ev->dma_data_length = dma_data_length;
353 ev->remote_address = remote_address;
354 return signal_event(ev);
355}
356
357/*
358 * Initiate a nice (hopefully) shutdown of Linux. We simply are
359 * going to try and send the init process a SIGINT signal. If
360 * this fails (why?), we'll simply force it off in a not-so-nice
361 * manner.
362 */
363static int shutdown(void)
364{
365 int rc = kill_cad_pid(SIGINT, 1);
366
367 if (rc) {
368 printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
369 "hard shutdown commencing\n", rc);
370 mf_power_off();
371 } else
372 printk(KERN_INFO "mf.c: init has been successfully notified "
373 "to proceed with shutdown\n");
374 return rc;
375}
376
377/*
378 * The primary partition VSP object is sending us a new
379 * event flow. Handle it...
380 */
381static void handle_int(struct io_mf_lp_event *event)
382{
383 struct ce_msg_data *ce_msg_data;
384 struct ce_msg_data *pce_msg_data;
385 unsigned long flags;
386 struct pending_event *pev;
387
388 /* ack the interrupt */
389 event->hp_lp_event.xRc = HvLpEvent_Rc_Good;
390 HvCallEvent_ackLpEvent(&event->hp_lp_event);
391
392 /* process interrupt */
393 switch (event->hp_lp_event.xSubtype) {
394 case 0: /* CE message */
395 ce_msg_data = &event->data.ce_msg;
396 switch (ce_msg_data->ce_msg[3]) {
397 case 0x5B: /* power control notification */
398 if ((ce_msg_data->ce_msg[5] & 0x20) != 0) {
399 printk(KERN_INFO "mf.c: Commencing partition shutdown\n");
400 if (shutdown() == 0)
401 signal_ce_msg_simple(0xDB, NULL);
402 }
403 break;
404 case 0xC0: /* get time */
405 spin_lock_irqsave(&pending_event_spinlock, flags);
406 pev = pending_event_head;
407 if (pev != NULL)
408 pending_event_head = pending_event_head->next;
409 spin_unlock_irqrestore(&pending_event_spinlock, flags);
410 if (pev == NULL)
411 break;
412 pce_msg_data = &pev->event.data.ce_msg;
413 if (pce_msg_data->ce_msg[3] != 0x40)
414 break;
415 if (pce_msg_data->completion != NULL) {
416 ce_msg_comp_hdlr handler =
417 pce_msg_data->completion->handler;
418 void *token = pce_msg_data->completion->token;
419
420 if (handler != NULL)
421 (*handler)(token, ce_msg_data);
422 }
423 spin_lock_irqsave(&pending_event_spinlock, flags);
424 free_pending_event(pev);
425 spin_unlock_irqrestore(&pending_event_spinlock, flags);
426 /* send next waiting event */
427 if (pending_event_head != NULL)
428 signal_event(NULL);
429 break;
430 }
431 break;
432 case 1: /* IT sys shutdown */
433 printk(KERN_INFO "mf.c: Commencing system shutdown\n");
434 shutdown();
435 break;
436 }
437}
438
439/*
440 * The primary partition VSP object is acknowledging the receipt
441 * of a flow we sent to them. If there are other flows queued
442 * up, we must send another one now...
443 */
444static void handle_ack(struct io_mf_lp_event *event)
445{
446 unsigned long flags;
447 struct pending_event *two = NULL;
448 unsigned long free_it = 0;
449 struct ce_msg_data *ce_msg_data;
450 struct ce_msg_data *pce_msg_data;
451 struct vsp_rsp_data *rsp;
452
453 /* handle current event */
454 if (pending_event_head == NULL) {
455 printk(KERN_ERR "mf.c: stack empty for receiving ack\n");
456 return;
457 }
458
459 switch (event->hp_lp_event.xSubtype) {
460 case 0: /* CE msg */
461 ce_msg_data = &event->data.ce_msg;
462 if (ce_msg_data->ce_msg[3] != 0x40) {
463 free_it = 1;
464 break;
465 }
466 if (ce_msg_data->ce_msg[2] == 0)
467 break;
468 free_it = 1;
469 pce_msg_data = &pending_event_head->event.data.ce_msg;
470 if (pce_msg_data->completion != NULL) {
471 ce_msg_comp_hdlr handler =
472 pce_msg_data->completion->handler;
473 void *token = pce_msg_data->completion->token;
474
475 if (handler != NULL)
476 (*handler)(token, ce_msg_data);
477 }
478 break;
479 case 4: /* allocate */
480 case 5: /* deallocate */
481 if (pending_event_head->hdlr != NULL)
482 (*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count);
483 free_it = 1;
484 break;
485 case 6:
486 free_it = 1;
487 rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token;
488 if (rsp == NULL) {
489 printk(KERN_ERR "mf.c: no rsp\n");
490 break;
491 }
492 if (rsp->response != NULL)
493 memcpy(rsp->response, &event->data.vsp_cmd,
494 sizeof(event->data.vsp_cmd));
495 complete(&rsp->com);
496 break;
497 }
498
499 /* remove from queue */
500 spin_lock_irqsave(&pending_event_spinlock, flags);
501 if ((pending_event_head != NULL) && (free_it == 1)) {
502 struct pending_event *oldHead = pending_event_head;
503
504 pending_event_head = pending_event_head->next;
505 two = pending_event_head;
506 free_pending_event(oldHead);
507 }
508 spin_unlock_irqrestore(&pending_event_spinlock, flags);
509
510 /* send next waiting event */
511 if (two != NULL)
512 signal_event(NULL);
513}
514
515/*
516 * This is the generic event handler we are registering with
517 * the Hypervisor. Ensure the flows are for us, and then
518 * parse it enough to know if it is an interrupt or an
519 * acknowledge.
520 */
521static void hv_handler(struct HvLpEvent *event)
522{
523 if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
524 if (hvlpevent_is_ack(event))
525 handle_ack((struct io_mf_lp_event *)event);
526 else
527 handle_int((struct io_mf_lp_event *)event);
528 } else
529 printk(KERN_ERR "mf.c: alien event received\n");
530}
531
532/*
533 * Global kernel interface to allocate and seed events into the
534 * Hypervisor.
535 */
536void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
537 unsigned size, unsigned count, MFCompleteHandler hdlr,
538 void *user_token)
539{
540 struct pending_event *ev = new_pending_event();
541 int rc;
542
543 if (ev == NULL) {
544 rc = -ENOMEM;
545 } else {
546 ev->event.hp_lp_event.xSubtype = 4;
547 ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
548 ev->event.hp_lp_event.x.xSubtypeData =
549 subtype_data('M', 'F', 'M', 'A');
550 ev->event.data.alloc.target_lp = target_lp;
551 ev->event.data.alloc.type = type;
552 ev->event.data.alloc.size = size;
553 ev->event.data.alloc.count = count;
554 ev->hdlr = hdlr;
555 rc = signal_event(ev);
556 }
557 if ((rc != 0) && (hdlr != NULL))
558 (*hdlr)(user_token, rc);
559}
560EXPORT_SYMBOL(mf_allocate_lp_events);
561
562/*
563 * Global kernel interface to unseed and deallocate events already in
564 * Hypervisor.
565 */
566void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
567 unsigned count, MFCompleteHandler hdlr, void *user_token)
568{
569 struct pending_event *ev = new_pending_event();
570 int rc;
571
572 if (ev == NULL)
573 rc = -ENOMEM;
574 else {
575 ev->event.hp_lp_event.xSubtype = 5;
576 ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
577 ev->event.hp_lp_event.x.xSubtypeData =
578 subtype_data('M', 'F', 'M', 'D');
579 ev->event.data.alloc.target_lp = target_lp;
580 ev->event.data.alloc.type = type;
581 ev->event.data.alloc.count = count;
582 ev->hdlr = hdlr;
583 rc = signal_event(ev);
584 }
585 if ((rc != 0) && (hdlr != NULL))
586 (*hdlr)(user_token, rc);
587}
588EXPORT_SYMBOL(mf_deallocate_lp_events);
589
590/*
591 * Global kernel interface to tell the VSP object in the primary
592 * partition to power this partition off.
593 */
594void mf_power_off(void)
595{
596 printk(KERN_INFO "mf.c: Down it goes...\n");
597 signal_ce_msg_simple(0x4d, NULL);
598 for (;;)
599 ;
600}
601
602/*
603 * Global kernel interface to tell the VSP object in the primary
604 * partition to reboot this partition.
605 */
606void mf_reboot(char *cmd)
607{
608 printk(KERN_INFO "mf.c: Preparing to bounce...\n");
609 signal_ce_msg_simple(0x4e, NULL);
610 for (;;)
611 ;
612}
613
614/*
615 * Display a single word SRC onto the VSP control panel.
616 */
617void mf_display_src(u32 word)
618{
619 u8 ce[12];
620
621 memset(ce, 0, sizeof(ce));
622 ce[3] = 0x4a;
623 ce[7] = 0x01;
624 ce[8] = word >> 24;
625 ce[9] = word >> 16;
626 ce[10] = word >> 8;
627 ce[11] = word;
628 signal_ce_msg(ce, NULL);
629}
630
631/*
632 * Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
633 */
634static __init void mf_display_progress_src(u16 value)
635{
636 u8 ce[12];
637 u8 src[72];
638
639 memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12);
640 memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
641 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
642 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
643 "\x00\x00\x00\x00PROGxxxx ",
644 72);
645 src[6] = value >> 8;
646 src[7] = value & 255;
647 src[44] = "0123456789ABCDEF"[(value >> 12) & 15];
648 src[45] = "0123456789ABCDEF"[(value >> 8) & 15];
649 src[46] = "0123456789ABCDEF"[(value >> 4) & 15];
650 src[47] = "0123456789ABCDEF"[value & 15];
651 dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024);
652}
653
654/*
655 * Clear the VSP control panel. Used to "erase" an SRC that was
656 * previously displayed.
657 */
658static void mf_clear_src(void)
659{
660 signal_ce_msg_simple(0x4b, NULL);
661}
662
663void __init mf_display_progress(u16 value)
664{
665 if (!mf_initialized)
666 return;
667
668 if (0xFFFF == value)
669 mf_clear_src();
670 else
671 mf_display_progress_src(value);
672}
673
674/*
675 * Initialization code here.
676 */
677void __init mf_init(void)
678{
679 int i;
680
681 spin_lock_init(&pending_event_spinlock);
682
683 for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++)
684 free_pending_event(&pending_event_prealloc[i]);
685
686 HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
687
688 /* virtual continue ack */
689 signal_ce_msg_simple(0x57, NULL);
690
691 mf_initialized = 1;
692 mb();
693
694 printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
695 "initialized\n");
696}
697
698struct rtc_time_data {
699 struct completion com;
700 struct ce_msg_data ce_msg;
701 int rc;
702};
703
704static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
705{
706 struct rtc_time_data *rtc = token;
707
708 memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
709 rtc->rc = 0;
710 complete(&rtc->com);
711}
712
713static int mf_set_rtc(struct rtc_time *tm)
714{
715 char ce_time[12];
716 u8 day, mon, hour, min, sec, y1, y2;
717 unsigned year;
718
719 year = 1900 + tm->tm_year;
720 y1 = year / 100;
721 y2 = year % 100;
722
723 sec = tm->tm_sec;
724 min = tm->tm_min;
725 hour = tm->tm_hour;
726 day = tm->tm_mday;
727 mon = tm->tm_mon + 1;
728
729 sec = bin2bcd(sec);
730 min = bin2bcd(min);
731 hour = bin2bcd(hour);
732 mon = bin2bcd(mon);
733 day = bin2bcd(day);
734 y1 = bin2bcd(y1);
735 y2 = bin2bcd(y2);
736
737 memset(ce_time, 0, sizeof(ce_time));
738 ce_time[3] = 0x41;
739 ce_time[4] = y1;
740 ce_time[5] = y2;
741 ce_time[6] = sec;
742 ce_time[7] = min;
743 ce_time[8] = hour;
744 ce_time[10] = day;
745 ce_time[11] = mon;
746
747 return signal_ce_msg(ce_time, NULL);
748}
749
750static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
751{
752 tm->tm_wday = 0;
753 tm->tm_yday = 0;
754 tm->tm_isdst = 0;
755 if (rc) {
756 tm->tm_sec = 0;
757 tm->tm_min = 0;
758 tm->tm_hour = 0;
759 tm->tm_mday = 15;
760 tm->tm_mon = 5;
761 tm->tm_year = 52;
762 return rc;
763 }
764
765 if ((ce_msg[2] == 0xa9) ||
766 (ce_msg[2] == 0xaf)) {
767 /* TOD clock is not set */
768 tm->tm_sec = 1;
769 tm->tm_min = 1;
770 tm->tm_hour = 1;
771 tm->tm_mday = 10;
772 tm->tm_mon = 8;
773 tm->tm_year = 71;
774 mf_set_rtc(tm);
775 }
776 {
777 u8 year = ce_msg[5];
778 u8 sec = ce_msg[6];
779 u8 min = ce_msg[7];
780 u8 hour = ce_msg[8];
781 u8 day = ce_msg[10];
782 u8 mon = ce_msg[11];
783
784 sec = bcd2bin(sec);
785 min = bcd2bin(min);
786 hour = bcd2bin(hour);
787 day = bcd2bin(day);
788 mon = bcd2bin(mon);
789 year = bcd2bin(year);
790
791 if (year <= 69)
792 year += 100;
793
794 tm->tm_sec = sec;
795 tm->tm_min = min;
796 tm->tm_hour = hour;
797 tm->tm_mday = day;
798 tm->tm_mon = mon;
799 tm->tm_year = year;
800 }
801
802 return 0;
803}
804
805static int mf_get_rtc(struct rtc_time *tm)
806{
807 struct ce_msg_comp_data ce_complete;
808 struct rtc_time_data rtc_data;
809 int rc;
810
811 memset(&ce_complete, 0, sizeof(ce_complete));
812 memset(&rtc_data, 0, sizeof(rtc_data));
813 init_completion(&rtc_data.com);
814 ce_complete.handler = &get_rtc_time_complete;
815 ce_complete.token = &rtc_data;
816 rc = signal_ce_msg_simple(0x40, &ce_complete);
817 if (rc)
818 return rc;
819 wait_for_completion(&rtc_data.com);
820 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
821}
822
823struct boot_rtc_time_data {
824 int busy;
825 struct ce_msg_data ce_msg;
826 int rc;
827};
828
829static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
830{
831 struct boot_rtc_time_data *rtc = token;
832
833 memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
834 rtc->rc = 0;
835 rtc->busy = 0;
836}
837
838static int mf_get_boot_rtc(struct rtc_time *tm)
839{
840 struct ce_msg_comp_data ce_complete;
841 struct boot_rtc_time_data rtc_data;
842 int rc;
843
844 memset(&ce_complete, 0, sizeof(ce_complete));
845 memset(&rtc_data, 0, sizeof(rtc_data));
846 rtc_data.busy = 1;
847 ce_complete.handler = &get_boot_rtc_time_complete;
848 ce_complete.token = &rtc_data;
849 rc = signal_ce_msg_simple(0x40, &ce_complete);
850 if (rc)
851 return rc;
852 /* We need to poll here as we are not yet taking interrupts */
853 while (rtc_data.busy) {
854 if (hvlpevent_is_pending())
855 process_hvlpevents();
856 }
857 return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
858}
859
860#ifdef CONFIG_PROC_FS
861static int mf_cmdline_proc_show(struct seq_file *m, void *v)
862{
863 char *page, *p;
864 struct vsp_cmd_data vsp_cmd;
865 int rc;
866 dma_addr_t dma_addr;
867
868 /* The HV appears to return no more than 256 bytes of command line */
869 page = kmalloc(256, GFP_KERNEL);
870 if (!page)
871 return -ENOMEM;
872
873 dma_addr = iseries_hv_map(page, 256, DMA_FROM_DEVICE);
874 if (dma_addr == DMA_ERROR_CODE) {
875 kfree(page);
876 return -ENOMEM;
877 }
878 memset(page, 0, 256);
879 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
880 vsp_cmd.cmd = 33;
881 vsp_cmd.sub_data.kern.token = dma_addr;
882 vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
883 vsp_cmd.sub_data.kern.side = (u64)m->private;
884 vsp_cmd.sub_data.kern.length = 256;
885 mb();
886 rc = signal_vsp_instruction(&vsp_cmd);
887 iseries_hv_unmap(dma_addr, 256, DMA_FROM_DEVICE);
888 if (rc) {
889 kfree(page);
890 return rc;
891 }
892 if (vsp_cmd.result_code != 0) {
893 kfree(page);
894 return -ENOMEM;
895 }
896 p = page;
897 while (p - page < 256) {
898 if (*p == '\0' || *p == '\n') {
899 *p = '\n';
900 break;
901 }
902 p++;
903
904 }
905 seq_write(m, page, p - page);
906 kfree(page);
907 return 0;
908}
909
910static int mf_cmdline_proc_open(struct inode *inode, struct file *file)
911{
912 return single_open(file, mf_cmdline_proc_show, PDE(inode)->data);
913}
914
915#if 0
916static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
917{
918 struct vsp_cmd_data vsp_cmd;
919 int rc;
920 int len = *size;
921 dma_addr_t dma_addr;
922
923 dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE);
924 memset(buffer, 0, len);
925 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
926 vsp_cmd.cmd = 32;
927 vsp_cmd.sub_data.kern.token = dma_addr;
928 vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
929 vsp_cmd.sub_data.kern.side = side;
930 vsp_cmd.sub_data.kern.offset = offset;
931 vsp_cmd.sub_data.kern.length = len;
932 mb();
933 rc = signal_vsp_instruction(&vsp_cmd);
934 if (rc == 0) {
935 if (vsp_cmd.result_code == 0)
936 *size = vsp_cmd.sub_data.length_out;
937 else
938 rc = -ENOMEM;
939 }
940
941 iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE);
942
943 return rc;
944}
945
946static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,
947 int count, int *eof, void *data)
948{
949 int sizeToGet = count;
950
951 if (!capable(CAP_SYS_ADMIN))
952 return -EACCES;
953
954 if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) {
955 if (sizeToGet != 0) {
956 *start = page + off;
957 return sizeToGet;
958 }
959 *eof = 1;
960 return 0;
961 }
962 *eof = 1;
963 return 0;
964}
965#endif
966
967static int mf_side_proc_show(struct seq_file *m, void *v)
968{
969 char mf_current_side = ' ';
970 struct vsp_cmd_data vsp_cmd;
971
972 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
973 vsp_cmd.cmd = 2;
974 vsp_cmd.sub_data.ipl_type = 0;
975 mb();
976
977 if (signal_vsp_instruction(&vsp_cmd) == 0) {
978 if (vsp_cmd.result_code == 0) {
979 switch (vsp_cmd.sub_data.ipl_type) {
980 case 0: mf_current_side = 'A';
981 break;
982 case 1: mf_current_side = 'B';
983 break;
984 case 2: mf_current_side = 'C';
985 break;
986 default: mf_current_side = 'D';
987 break;
988 }
989 }
990 }
991
992 seq_printf(m, "%c\n", mf_current_side);
993 return 0;
994}
995
996static int mf_side_proc_open(struct inode *inode, struct file *file)
997{
998 return single_open(file, mf_side_proc_show, NULL);
999}
1000
1001static ssize_t mf_side_proc_write(struct file *file, const char __user *buffer,
1002 size_t count, loff_t *pos)
1003{
1004 char side;
1005 u64 newSide;
1006 struct vsp_cmd_data vsp_cmd;
1007
1008 if (!capable(CAP_SYS_ADMIN))
1009 return -EACCES;
1010
1011 if (count == 0)
1012 return 0;
1013
1014 if (get_user(side, buffer))
1015 return -EFAULT;
1016
1017 switch (side) {
1018 case 'A': newSide = 0;
1019 break;
1020 case 'B': newSide = 1;
1021 break;
1022 case 'C': newSide = 2;
1023 break;
1024 case 'D': newSide = 3;
1025 break;
1026 default:
1027 printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
1028 return -EINVAL;
1029 }
1030
1031 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1032 vsp_cmd.sub_data.ipl_type = newSide;
1033 vsp_cmd.cmd = 10;
1034
1035 (void)signal_vsp_instruction(&vsp_cmd);
1036
1037 return count;
1038}
1039
1040static const struct file_operations mf_side_proc_fops = {
1041 .owner = THIS_MODULE,
1042 .open = mf_side_proc_open,
1043 .read = seq_read,
1044 .llseek = seq_lseek,
1045 .release = single_release,
1046 .write = mf_side_proc_write,
1047};
1048
1049static int mf_src_proc_show(struct seq_file *m, void *v)
1050{
1051 return 0;
1052}
1053
1054static int mf_src_proc_open(struct inode *inode, struct file *file)
1055{
1056 return single_open(file, mf_src_proc_show, NULL);
1057}
1058
1059static ssize_t mf_src_proc_write(struct file *file, const char __user *buffer,
1060 size_t count, loff_t *pos)
1061{
1062 char stkbuf[10];
1063
1064 if (!capable(CAP_SYS_ADMIN))
1065 return -EACCES;
1066
1067 if ((count < 4) && (count != 1)) {
1068 printk(KERN_ERR "mf_proc: invalid src\n");
1069 return -EINVAL;
1070 }
1071
1072 if (count > (sizeof(stkbuf) - 1))
1073 count = sizeof(stkbuf) - 1;
1074 if (copy_from_user(stkbuf, buffer, count))
1075 return -EFAULT;
1076
1077 if ((count == 1) && (*stkbuf == '\0'))
1078 mf_clear_src();
1079 else
1080 mf_display_src(*(u32 *)stkbuf);
1081
1082 return count;
1083}
1084
1085static const struct file_operations mf_src_proc_fops = {
1086 .owner = THIS_MODULE,
1087 .open = mf_src_proc_open,
1088 .read = seq_read,
1089 .llseek = seq_lseek,
1090 .release = single_release,
1091 .write = mf_src_proc_write,
1092};
1093
1094static ssize_t mf_cmdline_proc_write(struct file *file, const char __user *buffer,
1095 size_t count, loff_t *pos)
1096{
1097 void *data = PDE(file->f_path.dentry->d_inode)->data;
1098 struct vsp_cmd_data vsp_cmd;
1099 dma_addr_t dma_addr;
1100 char *page;
1101 int ret = -EACCES;
1102
1103 if (!capable(CAP_SYS_ADMIN))
1104 goto out;
1105
1106 dma_addr = 0;
1107 page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
1108 ret = -ENOMEM;
1109 if (page == NULL)
1110 goto out;
1111
1112 ret = -EFAULT;
1113 if (copy_from_user(page, buffer, count))
1114 goto out_free;
1115
1116 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1117 vsp_cmd.cmd = 31;
1118 vsp_cmd.sub_data.kern.token = dma_addr;
1119 vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
1120 vsp_cmd.sub_data.kern.side = (u64)data;
1121 vsp_cmd.sub_data.kern.length = count;
1122 mb();
1123 (void)signal_vsp_instruction(&vsp_cmd);
1124 ret = count;
1125
1126out_free:
1127 iseries_hv_free(count, page, dma_addr);
1128out:
1129 return ret;
1130}
1131
1132static const struct file_operations mf_cmdline_proc_fops = {
1133 .owner = THIS_MODULE,
1134 .open = mf_cmdline_proc_open,
1135 .read = seq_read,
1136 .llseek = seq_lseek,
1137 .release = single_release,
1138 .write = mf_cmdline_proc_write,
1139};
1140
1141static ssize_t proc_mf_change_vmlinux(struct file *file,
1142 const char __user *buf,
1143 size_t count, loff_t *ppos)
1144{
1145 struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);
1146 ssize_t rc;
1147 dma_addr_t dma_addr;
1148 char *page;
1149 struct vsp_cmd_data vsp_cmd;
1150
1151 rc = -EACCES;
1152 if (!capable(CAP_SYS_ADMIN))
1153 goto out;
1154
1155 dma_addr = 0;
1156 page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
1157 rc = -ENOMEM;
1158 if (page == NULL) {
1159 printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
1160 goto out;
1161 }
1162 rc = -EFAULT;
1163 if (copy_from_user(page, buf, count))
1164 goto out_free;
1165
1166 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1167 vsp_cmd.cmd = 30;
1168 vsp_cmd.sub_data.kern.token = dma_addr;
1169 vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
1170 vsp_cmd.sub_data.kern.side = (u64)dp->data;
1171 vsp_cmd.sub_data.kern.offset = *ppos;
1172 vsp_cmd.sub_data.kern.length = count;
1173 mb();
1174 rc = signal_vsp_instruction(&vsp_cmd);
1175 if (rc)
1176 goto out_free;
1177 rc = -ENOMEM;
1178 if (vsp_cmd.result_code != 0)
1179 goto out_free;
1180
1181 *ppos += count;
1182 rc = count;
1183out_free:
1184 iseries_hv_free(count, page, dma_addr);
1185out:
1186 return rc;
1187}
1188
1189static const struct file_operations proc_vmlinux_operations = {
1190 .write = proc_mf_change_vmlinux,
1191 .llseek = default_llseek,
1192};
1193
1194static int __init mf_proc_init(void)
1195{
1196 struct proc_dir_entry *mf_proc_root;
1197 struct proc_dir_entry *ent;
1198 struct proc_dir_entry *mf;
1199 char name[2];
1200 int i;
1201
1202 if (!firmware_has_feature(FW_FEATURE_ISERIES))
1203 return 0;
1204
1205 mf_proc_root = proc_mkdir("iSeries/mf", NULL);
1206 if (!mf_proc_root)
1207 return 1;
1208
1209 name[1] = '\0';
1210 for (i = 0; i < 4; i++) {
1211 name[0] = 'A' + i;
1212 mf = proc_mkdir(name, mf_proc_root);
1213 if (!mf)
1214 return 1;
1215
1216 ent = proc_create_data("cmdline", S_IRUSR|S_IWUSR, mf,
1217 &mf_cmdline_proc_fops, (void *)(long)i);
1218 if (!ent)
1219 return 1;
1220
1221 if (i == 3) /* no vmlinux entry for 'D' */
1222 continue;
1223
1224 ent = proc_create_data("vmlinux", S_IFREG|S_IWUSR, mf,
1225 &proc_vmlinux_operations,
1226 (void *)(long)i);
1227 if (!ent)
1228 return 1;
1229 }
1230
1231 ent = proc_create("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root,
1232 &mf_side_proc_fops);
1233 if (!ent)
1234 return 1;
1235
1236 ent = proc_create("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root,
1237 &mf_src_proc_fops);
1238 if (!ent)
1239 return 1;
1240
1241 return 0;
1242}
1243
1244__initcall(mf_proc_init);
1245
1246#endif /* CONFIG_PROC_FS */
1247
1248/*
1249 * Get the RTC from the virtual service processor
1250 * This requires flowing LpEvents to the primary partition
1251 */
1252void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
1253{
1254 mf_get_rtc(rtc_tm);
1255 rtc_tm->tm_mon--;
1256}
1257
1258/*
1259 * Set the RTC in the virtual service processor
1260 * This requires flowing LpEvents to the primary partition
1261 */
1262int iSeries_set_rtc_time(struct rtc_time *tm)
1263{
1264 mf_set_rtc(tm);
1265 return 0;
1266}
1267
1268unsigned long iSeries_get_boot_time(void)
1269{
1270 struct rtc_time tm;
1271
1272 mf_get_boot_rtc(&tm);
1273 return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday,
1274 tm.tm_hour, tm.tm_min, tm.tm_sec);
1275}
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
deleted file mode 100644
index 2c6ff0fdac98..000000000000
--- a/arch/powerpc/platforms/iseries/misc.S
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * This file contains miscellaneous low-level functions.
3 * Copyright (C) 1995-2005 IBM Corp
4 *
5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras.
7 * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
8 * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <asm/processor.h>
17#include <asm/asm-offsets.h>
18#include <asm/ppc_asm.h>
19
20 .text
21
22/* Handle pending interrupts in interrupt context */
23_GLOBAL(iseries_handle_interrupts)
24 li r0,0x5555
25 sc
26 blr
diff --git a/arch/powerpc/platforms/iseries/naca.h b/arch/powerpc/platforms/iseries/naca.h
deleted file mode 100644
index f01708e12862..000000000000
--- a/arch/powerpc/platforms/iseries/naca.h
+++ /dev/null
@@ -1,24 +0,0 @@
1#ifndef _PLATFORMS_ISERIES_NACA_H
2#define _PLATFORMS_ISERIES_NACA_H
3
4/*
5 * c 2001 PPC 64 Team, IBM Corp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <asm/types.h>
14
15struct naca_struct {
16 /* Kernel only data - undefined for user space */
17 const void *xItVpdAreas; /* VPD Data 0x00 */
18 void *xRamDisk; /* iSeries ramdisk 0x08 */
19 u64 xRamDiskSize; /* In pages 0x10 */
20};
21
22extern struct naca_struct naca;
23
24#endif /* _PLATFORMS_ISERIES_NACA_H */
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
deleted file mode 100644
index c75412884625..000000000000
--- a/arch/powerpc/platforms/iseries/pci.c
+++ /dev/null
@@ -1,919 +0,0 @@
1/*
2 * Copyright (C) 2001 Allan Trautman, IBM Corporation
3 * Copyright (C) 2005,2007 Stephen Rothwell, IBM Corp
4 *
5 * iSeries specific routines for PCI.
6 *
7 * Based on code from pci.c and iSeries_pci.c 32bit
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#undef DEBUG
25
26#include <linux/jiffies.h>
27#include <linux/kernel.h>
28#include <linux/list.h>
29#include <linux/string.h>
30#include <linux/slab.h>
31#include <linux/init.h>
32#include <linux/pci.h>
33#include <linux/of.h>
34#include <linux/ratelimit.h>
35
36#include <asm/types.h>
37#include <asm/io.h>
38#include <asm/irq.h>
39#include <asm/prom.h>
40#include <asm/machdep.h>
41#include <asm/pci-bridge.h>
42#include <asm/iommu.h>
43#include <asm/abs_addr.h>
44#include <asm/firmware.h>
45
46#include <asm/iseries/hv_types.h>
47#include <asm/iseries/hv_call_xm.h>
48#include <asm/iseries/mf.h>
49#include <asm/iseries/iommu.h>
50
51#include <asm/ppc-pci.h>
52
53#include "irq.h"
54#include "pci.h"
55#include "call_pci.h"
56
57#define PCI_RETRY_MAX 3
58static int limit_pci_retries = 1; /* Set Retry Error on. */
59
60/*
61 * Table defines
62 * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
63 */
64#define IOMM_TABLE_MAX_ENTRIES 1024
65#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
66#define BASE_IO_MEMORY 0xE000000000000000UL
67#define END_IO_MEMORY 0xEFFFFFFFFFFFFFFFUL
68
69static unsigned long max_io_memory = BASE_IO_MEMORY;
70static long current_iomm_table_entry;
71
72/*
73 * Lookup Tables.
74 */
75static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
76static u64 ds_addr_table[IOMM_TABLE_MAX_ENTRIES];
77
78static DEFINE_SPINLOCK(iomm_table_lock);
79
80/*
81 * Generate a Direct Select Address for the Hypervisor
82 */
83static inline u64 iseries_ds_addr(struct device_node *node)
84{
85 struct pci_dn *pdn = PCI_DN(node);
86 const u32 *sbp = of_get_property(node, "linux,subbus", NULL);
87
88 return ((u64)pdn->busno << 48) + ((u64)(sbp ? *sbp : 0) << 40)
89 + ((u64)0x10 << 32);
90}
91
92/*
93 * Size of Bus VPD data
94 */
95#define BUS_VPDSIZE 1024
96
97/*
98 * Bus Vpd Tags
99 */
100#define VPD_END_OF_AREA 0x79
101#define VPD_ID_STRING 0x82
102#define VPD_VENDOR_AREA 0x84
103
104/*
105 * Mfg Area Tags
106 */
107#define VPD_FRU_FRAME_ID 0x4649 /* "FI" */
108#define VPD_SLOT_MAP_FORMAT 0x4D46 /* "MF" */
109#define VPD_SLOT_MAP 0x534D /* "SM" */
110
111/*
112 * Structures of the areas
113 */
114struct mfg_vpd_area {
115 u16 tag;
116 u8 length;
117 u8 data1;
118 u8 data2;
119};
120#define MFG_ENTRY_SIZE 3
121
122struct slot_map {
123 u8 agent;
124 u8 secondary_agent;
125 u8 phb;
126 char card_location[3];
127 char parms[8];
128 char reserved[2];
129};
130#define SLOT_ENTRY_SIZE 16
131
132/*
133 * Parse the Slot Area
134 */
135static void __init iseries_parse_slot_area(struct slot_map *map, int len,
136 HvAgentId agent, u8 *phb, char card[4])
137{
138 /*
139 * Parse Slot label until we find the one requested
140 */
141 while (len > 0) {
142 if (map->agent == agent) {
143 /*
144 * If Phb wasn't found, grab the entry first one found.
145 */
146 if (*phb == 0xff)
147 *phb = map->phb;
148 /* Found it, extract the data. */
149 if (map->phb == *phb) {
150 memcpy(card, &map->card_location, 3);
151 card[3] = 0;
152 break;
153 }
154 }
155 /* Point to the next Slot */
156 map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
157 len -= SLOT_ENTRY_SIZE;
158 }
159}
160
161/*
162 * Parse the Mfg Area
163 */
164static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
165 HvAgentId agent, u8 *phb, u8 *frame, char card[4])
166{
167 u16 slot_map_fmt = 0;
168
169 /* Parse Mfg Data */
170 while (len > 0) {
171 int mfg_tag_len = area->length;
172 /* Frame ID (FI 4649020310 ) */
173 if (area->tag == VPD_FRU_FRAME_ID)
174 *frame = area->data1;
175 /* Slot Map Format (MF 4D46020004 ) */
176 else if (area->tag == VPD_SLOT_MAP_FORMAT)
177 slot_map_fmt = (area->data1 * 256)
178 + area->data2;
179 /* Slot Map (SM 534D90 */
180 else if (area->tag == VPD_SLOT_MAP) {
181 struct slot_map *slot_map;
182
183 if (slot_map_fmt == 0x1004)
184 slot_map = (struct slot_map *)((char *)area
185 + MFG_ENTRY_SIZE + 1);
186 else
187 slot_map = (struct slot_map *)((char *)area
188 + MFG_ENTRY_SIZE);
189 iseries_parse_slot_area(slot_map, mfg_tag_len,
190 agent, phb, card);
191 }
192 /*
193 * Point to the next Mfg Area
194 * Use defined size, sizeof give wrong answer
195 */
196 area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
197 + MFG_ENTRY_SIZE);
198 len -= (mfg_tag_len + MFG_ENTRY_SIZE);
199 }
200}
201
202/*
203 * Look for "BUS".. Data is not Null terminated.
204 * PHBID of 0xFF indicates PHB was not found in VPD Data.
205 */
206static u8 __init iseries_parse_phbid(u8 *area, int len)
207{
208 while (len > 0) {
209 if ((*area == 'B') && (*(area + 1) == 'U')
210 && (*(area + 2) == 'S')) {
211 area += 3;
212 while (*area == ' ')
213 area++;
214 return *area & 0x0F;
215 }
216 area++;
217 len--;
218 }
219 return 0xff;
220}
221
222/*
223 * Parse out the VPD Areas
224 */
225static void __init iseries_parse_vpd(u8 *data, int data_len,
226 HvAgentId agent, u8 *frame, char card[4])
227{
228 u8 phb = 0xff;
229
230 while (data_len > 0) {
231 int len;
232 u8 tag = *data;
233
234 if (tag == VPD_END_OF_AREA)
235 break;
236 len = *(data + 1) + (*(data + 2) * 256);
237 data += 3;
238 data_len -= 3;
239 if (tag == VPD_ID_STRING)
240 phb = iseries_parse_phbid(data, len);
241 else if (tag == VPD_VENDOR_AREA)
242 iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
243 agent, &phb, frame, card);
244 /* Point to next Area. */
245 data += len;
246 data_len -= len;
247 }
248}
249
250static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
251 u8 *frame, char card[4])
252{
253 int status = 0;
254 int bus_vpd_len = 0;
255 u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
256
257 if (bus_vpd == NULL) {
258 printk("PCI: Bus VPD Buffer allocation failure.\n");
259 return 0;
260 }
261 bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
262 BUS_VPDSIZE);
263 if (bus_vpd_len == 0) {
264 printk("PCI: Bus VPD Buffer zero length.\n");
265 goto out_free;
266 }
267 /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
268 /* Make sure this is what I think it is */
269 if (*bus_vpd != VPD_ID_STRING) {
270 printk("PCI: Bus VPD Buffer missing starting tag.\n");
271 goto out_free;
272 }
273 iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
274 status = 1;
275out_free:
276 kfree(bus_vpd);
277 return status;
278}
279
280/*
281 * Prints the device information.
282 * - Pass in pci_dev* pointer to the device.
283 * - Pass in the device count
284 *
285 * Format:
286 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
287 * controller
288 */
289static void __init iseries_device_information(struct pci_dev *pdev,
290 u16 bus, HvSubBusNumber subbus)
291{
292 u8 frame = 0;
293 char card[4];
294 HvAgentId agent;
295
296 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
297 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
298
299 if (iseries_get_location_code(bus, agent, &frame, card)) {
300 printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
301 "Card %4s 0x%04X\n", pci_name(pdev), pdev->vendor,
302 frame, card, (int)(pdev->class >> 8));
303 }
304}
305
306/*
307 * iomm_table_allocate_entry
308 *
309 * Adds pci_dev entry in address translation table
310 *
311 * - Allocates the number of entries required in table base on BAR
312 * size.
313 * - Allocates starting at BASE_IO_MEMORY and increases.
314 * - The size is round up to be a multiple of entry size.
315 * - CurrentIndex is incremented to keep track of the last entry.
316 * - Builds the resource entry for allocated BARs.
317 */
318static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
319{
320 struct resource *bar_res = &dev->resource[bar_num];
321 long bar_size = pci_resource_len(dev, bar_num);
322 struct device_node *dn = pci_device_to_OF_node(dev);
323
324 /*
325 * No space to allocate, quick exit, skip Allocation.
326 */
327 if (bar_size == 0)
328 return;
329 /*
330 * Set Resource values.
331 */
332 spin_lock(&iomm_table_lock);
333 bar_res->start = BASE_IO_MEMORY +
334 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
335 bar_res->end = bar_res->start + bar_size - 1;
336 /*
337 * Allocate the number of table entries needed for BAR.
338 */
339 while (bar_size > 0 ) {
340 iomm_table[current_iomm_table_entry] = dn;
341 ds_addr_table[current_iomm_table_entry] =
342 iseries_ds_addr(dn) | (bar_num << 24);
343 bar_size -= IOMM_TABLE_ENTRY_SIZE;
344 ++current_iomm_table_entry;
345 }
346 max_io_memory = BASE_IO_MEMORY +
347 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
348 spin_unlock(&iomm_table_lock);
349}
350
351/*
352 * allocate_device_bars
353 *
354 * - Allocates ALL pci_dev BAR's and updates the resources with the
355 * BAR value. BARS with zero length will have the resources
356 * The HvCallPci_getBarParms is used to get the size of the BAR
357 * space. It calls iomm_table_allocate_entry to allocate
358 * each entry.
359 * - Loops through The Bar resources(0 - 5) including the ROM
360 * is resource(6).
361 */
362static void __init allocate_device_bars(struct pci_dev *dev)
363{
364 int bar_num;
365
366 for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
367 iomm_table_allocate_entry(dev, bar_num);
368}
369
370/*
371 * Log error information to system console.
372 * Filter out the device not there errors.
373 * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
374 * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
375 * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
376 */
377static void pci_log_error(char *error, int bus, int subbus,
378 int agent, int hv_res)
379{
380 if (hv_res == 0x0302)
381 return;
382 printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
383 error, bus, subbus, agent, hv_res);
384}
385
386/*
387 * Look down the chain to find the matching Device Device
388 */
389static struct device_node *find_device_node(int bus, int devfn)
390{
391 struct device_node *node;
392
393 for (node = NULL; (node = of_find_all_nodes(node)); ) {
394 struct pci_dn *pdn = PCI_DN(node);
395
396 if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
397 return node;
398 }
399 return NULL;
400}
401
402/*
403 * iSeries_pcibios_fixup_resources
404 *
405 * Fixes up all resources for devices
406 */
407void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
408{
409 const u32 *agent;
410 const u32 *sub_bus;
411 unsigned char bus = pdev->bus->number;
412 struct device_node *node;
413 int i;
414
415 node = pci_device_to_OF_node(pdev);
416 pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
417 pci_name(pdev), pdev, node);
418 if (!node) {
419 printk("PCI: %s disabled, device tree entry not found !\n",
420 pci_name(pdev));
421 for (i = 0; i <= PCI_ROM_RESOURCE; i++)
422 pdev->resource[i].flags = 0;
423 return;
424 }
425 sub_bus = of_get_property(node, "linux,subbus", NULL);
426 agent = of_get_property(node, "linux,agent-id", NULL);
427 if (agent && sub_bus) {
428 u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
429 int err;
430
431 err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
432 if (err)
433 pci_log_error("Connect Bus Unit",
434 bus, *sub_bus, *agent, err);
435 else {
436 err = HvCallPci_configStore8(bus, *sub_bus,
437 *agent, PCI_INTERRUPT_LINE, irq);
438 if (err)
439 pci_log_error("PciCfgStore Irq Failed!",
440 bus, *sub_bus, *agent, err);
441 else
442 pdev->irq = irq;
443 }
444 }
445
446 allocate_device_bars(pdev);
447 if (likely(sub_bus))
448 iseries_device_information(pdev, bus, *sub_bus);
449 else
450 printk(KERN_ERR "PCI: Device node %s has missing or invalid "
451 "linux,subbus property\n", node->full_name);
452}
453
454/*
455 * iSeries_pci_final_fixup(void)
456 */
457void __init iSeries_pci_final_fixup(void)
458{
459 /* Fix up at the device node and pci_dev relationship */
460 mf_display_src(0xC9000100);
461 iSeries_activate_IRQs();
462 mf_display_src(0xC9000200);
463}
464
465/*
466 * Config space read and write functions.
467 * For now at least, we look for the device node for the bus and devfn
468 * that we are asked to access. It may be possible to translate the devfn
469 * to a subbus and deviceid more directly.
470 */
471static u64 hv_cfg_read_func[4] = {
472 HvCallPciConfigLoad8, HvCallPciConfigLoad16,
473 HvCallPciConfigLoad32, HvCallPciConfigLoad32
474};
475
476static u64 hv_cfg_write_func[4] = {
477 HvCallPciConfigStore8, HvCallPciConfigStore16,
478 HvCallPciConfigStore32, HvCallPciConfigStore32
479};
480
481/*
482 * Read PCI config space
483 */
484static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
485 int offset, int size, u32 *val)
486{
487 struct device_node *node = find_device_node(bus->number, devfn);
488 u64 fn;
489 struct HvCallPci_LoadReturn ret;
490
491 if (node == NULL)
492 return PCIBIOS_DEVICE_NOT_FOUND;
493 if (offset > 255) {
494 *val = ~0;
495 return PCIBIOS_BAD_REGISTER_NUMBER;
496 }
497
498 fn = hv_cfg_read_func[(size - 1) & 3];
499 HvCall3Ret16(fn, &ret, iseries_ds_addr(node), offset, 0);
500
501 if (ret.rc != 0) {
502 *val = ~0;
503 return PCIBIOS_DEVICE_NOT_FOUND; /* or something */
504 }
505
506 *val = ret.value;
507 return 0;
508}
509
510/*
511 * Write PCI config space
512 */
513
514static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
515 int offset, int size, u32 val)
516{
517 struct device_node *node = find_device_node(bus->number, devfn);
518 u64 fn;
519 u64 ret;
520
521 if (node == NULL)
522 return PCIBIOS_DEVICE_NOT_FOUND;
523 if (offset > 255)
524 return PCIBIOS_BAD_REGISTER_NUMBER;
525
526 fn = hv_cfg_write_func[(size - 1) & 3];
527 ret = HvCall4(fn, iseries_ds_addr(node), offset, val, 0);
528
529 if (ret != 0)
530 return PCIBIOS_DEVICE_NOT_FOUND;
531
532 return 0;
533}
534
535static struct pci_ops iSeries_pci_ops = {
536 .read = iSeries_pci_read_config,
537 .write = iSeries_pci_write_config
538};
539
540/*
541 * Check Return Code
542 * -> On Failure, print and log information.
543 * Increment Retry Count, if exceeds max, panic partition.
544 *
545 * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
546 * PCI: Device 23.90 ReadL Retry( 1)
547 * PCI: Device 23.90 ReadL Retry Successful(1)
548 */
549static int check_return_code(char *type, struct device_node *dn,
550 int *retry, u64 ret)
551{
552 if (ret != 0) {
553 struct pci_dn *pdn = PCI_DN(dn);
554
555 (*retry)++;
556 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
557 type, pdn->busno, pdn->devfn,
558 *retry, (int)ret);
559 /*
560 * Bump the retry and check for retry count exceeded.
561 * If, Exceeded, panic the system.
562 */
563 if (((*retry) > PCI_RETRY_MAX) &&
564 (limit_pci_retries > 0)) {
565 mf_display_src(0xB6000103);
566 panic_timeout = 0;
567 panic("PCI: Hardware I/O Error, SRC B6000103, "
568 "Automatic Reboot Disabled.\n");
569 }
570 return -1; /* Retry Try */
571 }
572 return 0;
573}
574
575/*
576 * Translate the I/O Address into a device node, bar, and bar offset.
577 * Note: Make sure the passed variable end up on the stack to avoid
578 * the exposure of being device global.
579 */
580static inline struct device_node *xlate_iomm_address(
581 const volatile void __iomem *addr,
582 u64 *dsaptr, u64 *bar_offset, const char *func)
583{
584 unsigned long orig_addr;
585 unsigned long base_addr;
586 unsigned long ind;
587 struct device_node *dn;
588
589 orig_addr = (unsigned long __force)addr;
590 if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
591 static DEFINE_RATELIMIT_STATE(ratelimit, 60 * HZ, 10);
592
593 if (__ratelimit(&ratelimit))
594 printk(KERN_ERR
595 "iSeries_%s: invalid access at IO address %p\n",
596 func, addr);
597 return NULL;
598 }
599 base_addr = orig_addr - BASE_IO_MEMORY;
600 ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
601 dn = iomm_table[ind];
602
603 if (dn != NULL) {
604 *dsaptr = ds_addr_table[ind];
605 *bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE;
606 } else
607 panic("PCI: Invalid PCI IO address detected!\n");
608 return dn;
609}
610
611/*
612 * Read MM I/O Instructions for the iSeries
613 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
614 * else, data is returned in Big Endian format.
615 */
616static u8 iseries_readb(const volatile void __iomem *addr)
617{
618 u64 bar_offset;
619 u64 dsa;
620 int retry = 0;
621 struct HvCallPci_LoadReturn ret;
622 struct device_node *dn =
623 xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
624
625 if (dn == NULL)
626 return 0xff;
627 do {
628 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
629 } while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
630
631 return ret.value;
632}
633
634static u16 iseries_readw_be(const volatile void __iomem *addr)
635{
636 u64 bar_offset;
637 u64 dsa;
638 int retry = 0;
639 struct HvCallPci_LoadReturn ret;
640 struct device_node *dn =
641 xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
642
643 if (dn == NULL)
644 return 0xffff;
645 do {
646 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
647 bar_offset, 0);
648 } while (check_return_code("RDW", dn, &retry, ret.rc) != 0);
649
650 return ret.value;
651}
652
653static u32 iseries_readl_be(const volatile void __iomem *addr)
654{
655 u64 bar_offset;
656 u64 dsa;
657 int retry = 0;
658 struct HvCallPci_LoadReturn ret;
659 struct device_node *dn =
660 xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
661
662 if (dn == NULL)
663 return 0xffffffff;
664 do {
665 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
666 bar_offset, 0);
667 } while (check_return_code("RDL", dn, &retry, ret.rc) != 0);
668
669 return ret.value;
670}
671
672/*
673 * Write MM I/O Instructions for the iSeries
674 *
675 */
676static void iseries_writeb(u8 data, volatile void __iomem *addr)
677{
678 u64 bar_offset;
679 u64 dsa;
680 int retry = 0;
681 u64 rc;
682 struct device_node *dn =
683 xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
684
685 if (dn == NULL)
686 return;
687 do {
688 rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
689 } while (check_return_code("WWB", dn, &retry, rc) != 0);
690}
691
692static void iseries_writew_be(u16 data, volatile void __iomem *addr)
693{
694 u64 bar_offset;
695 u64 dsa;
696 int retry = 0;
697 u64 rc;
698 struct device_node *dn =
699 xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
700
701 if (dn == NULL)
702 return;
703 do {
704 rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
705 } while (check_return_code("WWW", dn, &retry, rc) != 0);
706}
707
708static void iseries_writel_be(u32 data, volatile void __iomem *addr)
709{
710 u64 bar_offset;
711 u64 dsa;
712 int retry = 0;
713 u64 rc;
714 struct device_node *dn =
715 xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
716
717 if (dn == NULL)
718 return;
719 do {
720 rc = HvCall4(HvCallPciBarStore32, dsa, bar_offset, data, 0);
721 } while (check_return_code("WWL", dn, &retry, rc) != 0);
722}
723
724static u16 iseries_readw(const volatile void __iomem *addr)
725{
726 return le16_to_cpu(iseries_readw_be(addr));
727}
728
729static u32 iseries_readl(const volatile void __iomem *addr)
730{
731 return le32_to_cpu(iseries_readl_be(addr));
732}
733
734static void iseries_writew(u16 data, volatile void __iomem *addr)
735{
736 iseries_writew_be(cpu_to_le16(data), addr);
737}
738
739static void iseries_writel(u32 data, volatile void __iomem *addr)
740{
741 iseries_writel(cpu_to_le32(data), addr);
742}
743
744static void iseries_readsb(const volatile void __iomem *addr, void *buf,
745 unsigned long count)
746{
747 u8 *dst = buf;
748 while(count-- > 0)
749 *(dst++) = iseries_readb(addr);
750}
751
752static void iseries_readsw(const volatile void __iomem *addr, void *buf,
753 unsigned long count)
754{
755 u16 *dst = buf;
756 while(count-- > 0)
757 *(dst++) = iseries_readw_be(addr);
758}
759
760static void iseries_readsl(const volatile void __iomem *addr, void *buf,
761 unsigned long count)
762{
763 u32 *dst = buf;
764 while(count-- > 0)
765 *(dst++) = iseries_readl_be(addr);
766}
767
768static void iseries_writesb(volatile void __iomem *addr, const void *buf,
769 unsigned long count)
770{
771 const u8 *src = buf;
772 while(count-- > 0)
773 iseries_writeb(*(src++), addr);
774}
775
776static void iseries_writesw(volatile void __iomem *addr, const void *buf,
777 unsigned long count)
778{
779 const u16 *src = buf;
780 while(count-- > 0)
781 iseries_writew_be(*(src++), addr);
782}
783
784static void iseries_writesl(volatile void __iomem *addr, const void *buf,
785 unsigned long count)
786{
787 const u32 *src = buf;
788 while(count-- > 0)
789 iseries_writel_be(*(src++), addr);
790}
791
792static void iseries_memset_io(volatile void __iomem *addr, int c,
793 unsigned long n)
794{
795 volatile char __iomem *d = addr;
796
797 while (n-- > 0)
798 iseries_writeb(c, d++);
799}
800
801static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
802 unsigned long n)
803{
804 char *d = dest;
805 const volatile char __iomem *s = src;
806
807 while (n-- > 0)
808 *d++ = iseries_readb(s++);
809}
810
811static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
812 unsigned long n)
813{
814 const char *s = src;
815 volatile char __iomem *d = dest;
816
817 while (n-- > 0)
818 iseries_writeb(*s++, d++);
819}
820
821/* We only set MMIO ops. The default PIO ops will be default
822 * to the MMIO ops + pci_io_base which is 0 on iSeries as
823 * expected so both should work.
824 *
825 * Note that we don't implement the readq/writeq versions as
826 * I don't know of an HV call for doing so. Thus, the default
827 * operation will be used instead, which will fault a the value
828 * return by iSeries for MMIO addresses always hits a non mapped
829 * area. This is as good as the BUG() we used to have there.
830 */
831static struct ppc_pci_io __initdata iseries_pci_io = {
832 .readb = iseries_readb,
833 .readw = iseries_readw,
834 .readl = iseries_readl,
835 .readw_be = iseries_readw_be,
836 .readl_be = iseries_readl_be,
837 .writeb = iseries_writeb,
838 .writew = iseries_writew,
839 .writel = iseries_writel,
840 .writew_be = iseries_writew_be,
841 .writel_be = iseries_writel_be,
842 .readsb = iseries_readsb,
843 .readsw = iseries_readsw,
844 .readsl = iseries_readsl,
845 .writesb = iseries_writesb,
846 .writesw = iseries_writesw,
847 .writesl = iseries_writesl,
848 .memset_io = iseries_memset_io,
849 .memcpy_fromio = iseries_memcpy_fromio,
850 .memcpy_toio = iseries_memcpy_toio,
851};
852
853/*
854 * iSeries_pcibios_init
855 *
856 * Description:
857 * This function checks for all possible system PCI host bridges that connect
858 * PCI buses. The system hypervisor is queried as to the guest partition
859 * ownership status. A pci_controller is built for any bus which is partially
860 * owned or fully owned by this guest partition.
861 */
862void __init iSeries_pcibios_init(void)
863{
864 struct pci_controller *phb;
865 struct device_node *root = of_find_node_by_path("/");
866 struct device_node *node = NULL;
867
868 /* Install IO hooks */
869 ppc_pci_io = iseries_pci_io;
870
871 pci_probe_only = 1;
872
873 /* iSeries has no IO space in the common sense, it needs to set
874 * the IO base to 0
875 */
876 pci_io_base = 0;
877
878 if (root == NULL) {
879 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
880 "of device tree\n");
881 return;
882 }
883 while ((node = of_get_next_child(root, node)) != NULL) {
884 HvBusNumber bus;
885 const u32 *busp;
886
887 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
888 continue;
889
890 busp = of_get_property(node, "bus-range", NULL);
891 if (busp == NULL)
892 continue;
893 bus = *busp;
894 printk("bus %d appears to exist\n", bus);
895 phb = pcibios_alloc_controller(node);
896 if (phb == NULL)
897 continue;
898 /* All legacy iSeries PHBs are in domain zero */
899 phb->global_number = 0;
900
901 phb->first_busno = bus;
902 phb->last_busno = bus;
903 phb->ops = &iSeries_pci_ops;
904 phb->io_base_virt = (void __iomem *)_IO_BASE;
905 phb->io_resource.flags = IORESOURCE_IO;
906 phb->io_resource.start = BASE_IO_MEMORY;
907 phb->io_resource.end = END_IO_MEMORY;
908 phb->io_resource.name = "iSeries PCI IO";
909 phb->mem_resources[0].flags = IORESOURCE_MEM;
910 phb->mem_resources[0].start = BASE_IO_MEMORY;
911 phb->mem_resources[0].end = END_IO_MEMORY;
912 phb->mem_resources[0].name = "Series PCI MEM";
913 }
914
915 of_node_put(root);
916
917 pci_devs_phb_init();
918}
919
diff --git a/arch/powerpc/platforms/iseries/pci.h b/arch/powerpc/platforms/iseries/pci.h
deleted file mode 100644
index d9cf974c2718..000000000000
--- a/arch/powerpc/platforms/iseries/pci.h
+++ /dev/null
@@ -1,58 +0,0 @@
1#ifndef _PLATFORMS_ISERIES_PCI_H
2#define _PLATFORMS_ISERIES_PCI_H
3
4/*
5 * Created by Allan Trautman on Tue Feb 20, 2001.
6 *
7 * Define some useful macros for the iSeries pci routines.
8 * Copyright (C) 2001 Allan H Trautman, IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the:
22 * Free Software Foundation, Inc.,
23 * 59 Temple Place, Suite 330,
24 * Boston, MA 02111-1307 USA
25 *
26 * Change Activity:
27 * Created Feb 20, 2001
28 * Added device reset, March 22, 2001
29 * Ported to ppc64, May 25, 2001
30 * End Change Activity
31 */
32
33/*
34 * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
35 * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
36 */
37
38#define ISERIES_PCI_AGENTID(idsel, func) \
39 (((idsel & 0x0F) << 4) | (func & 0x07))
40#define ISERIES_ENCODE_DEVICE(agentid) \
41 ((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
42
43#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
44#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
45
46struct pci_dev;
47
48#ifdef CONFIG_PCI
49extern void iSeries_pcibios_init(void);
50extern void iSeries_pci_final_fixup(void);
51extern void iSeries_pcibios_fixup_resources(struct pci_dev *dev);
52#else
53static inline void iSeries_pcibios_init(void) { }
54static inline void iSeries_pci_final_fixup(void) { }
55static inline void iSeries_pcibios_fixup_resources(struct pci_dev *dev) {}
56#endif
57
58#endif /* _PLATFORMS_ISERIES_PCI_H */
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
deleted file mode 100644
index 06763682db47..000000000000
--- a/arch/powerpc/platforms/iseries/proc.c
+++ /dev/null
@@ -1,120 +0,0 @@
1/*
2 * Copyright (C) 2001 Kyle A. Lucke IBM Corporation
3 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/init.h>
20#include <linux/proc_fs.h>
21#include <linux/seq_file.h>
22#include <linux/param.h> /* for HZ */
23#include <asm/paca.h>
24#include <asm/processor.h>
25#include <asm/time.h>
26#include <asm/lppaca.h>
27#include <asm/firmware.h>
28#include <asm/iseries/hv_call_xm.h>
29
30#include "processor_vpd.h"
31#include "main_store.h"
32
33static int __init iseries_proc_create(void)
34{
35 struct proc_dir_entry *e;
36
37 if (!firmware_has_feature(FW_FEATURE_ISERIES))
38 return 0;
39
40 e = proc_mkdir("iSeries", 0);
41 if (!e)
42 return 1;
43
44 return 0;
45}
46core_initcall(iseries_proc_create);
47
48static unsigned long startTitan = 0;
49static unsigned long startTb = 0;
50
51static int proc_titantod_show(struct seq_file *m, void *v)
52{
53 unsigned long tb0, titan_tod;
54
55 tb0 = get_tb();
56 titan_tod = HvCallXm_loadTod();
57
58 seq_printf(m, "Titan\n" );
59 seq_printf(m, " time base = %016lx\n", tb0);
60 seq_printf(m, " titan tod = %016lx\n", titan_tod);
61 seq_printf(m, " xProcFreq = %016x\n",
62 xIoHriProcessorVpd[0].xProcFreq);
63 seq_printf(m, " xTimeBaseFreq = %016x\n",
64 xIoHriProcessorVpd[0].xTimeBaseFreq);
65 seq_printf(m, " tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy);
66 seq_printf(m, " tb_ticks_per_usec = %lu\n", tb_ticks_per_usec);
67
68 if (!startTitan) {
69 startTitan = titan_tod;
70 startTb = tb0;
71 } else {
72 unsigned long titan_usec = (titan_tod - startTitan) >> 12;
73 unsigned long tb_ticks = (tb0 - startTb);
74 unsigned long titan_jiffies = titan_usec / (1000000/HZ);
75 unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
76 unsigned long titan_jiff_rem_usec =
77 titan_usec - titan_jiff_usec;
78 unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
79 unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
80 unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
81 unsigned long tb_jiff_rem_usec =
82 tb_jiff_rem_ticks / tb_ticks_per_usec;
83 unsigned long new_tb_ticks_per_jiffy =
84 (tb_ticks * (1000000/HZ))/titan_usec;
85
86 seq_printf(m, " titan elapsed = %lu uSec\n", titan_usec);
87 seq_printf(m, " tb elapsed = %lu ticks\n", tb_ticks);
88 seq_printf(m, " titan jiffies = %lu.%04lu\n", titan_jiffies,
89 titan_jiff_rem_usec);
90 seq_printf(m, " tb jiffies = %lu.%04lu\n", tb_jiffies,
91 tb_jiff_rem_usec);
92 seq_printf(m, " new tb_ticks_per_jiffy = %lu\n",
93 new_tb_ticks_per_jiffy);
94 }
95
96 return 0;
97}
98
99static int proc_titantod_open(struct inode *inode, struct file *file)
100{
101 return single_open(file, proc_titantod_show, NULL);
102}
103
104static const struct file_operations proc_titantod_operations = {
105 .open = proc_titantod_open,
106 .read = seq_read,
107 .llseek = seq_lseek,
108 .release = single_release,
109};
110
111static int __init iseries_proc_init(void)
112{
113 if (!firmware_has_feature(FW_FEATURE_ISERIES))
114 return 0;
115
116 proc_create("iSeries/titanTod", S_IFREG|S_IRUGO, NULL,
117 &proc_titantod_operations);
118 return 0;
119}
120__initcall(iseries_proc_init);
diff --git a/arch/powerpc/platforms/iseries/processor_vpd.h b/arch/powerpc/platforms/iseries/processor_vpd.h
deleted file mode 100644
index 7ac5d0d0dbfa..000000000000
--- a/arch/powerpc/platforms/iseries/processor_vpd.h
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISERIES_PROCESSOR_VPD_H
19#define _ISERIES_PROCESSOR_VPD_H
20
21#include <asm/types.h>
22
23/*
24 * This struct maps Processor Vpd that is DMAd to SLIC by CSP
25 */
26struct IoHriProcessorVpd {
27 u8 xFormat; // VPD format indicator x00-x00
28 u8 xProcStatus:8; // Processor State x01-x01
29 u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02
30 u8 xSrcType:1; // Src Type x03-x03
31 u8 xSrcSoft:1; // Src stay soft ...
32 u8 xSrcParable:1; // Src parable ...
33 u8 xRsvd1:5; // Reserved ...
34 u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05
35 u16 xRsvd2; // Reserved x06-x07
36 u32 xHwNodeId; // Hardware node id x08-x0B
37 u32 xHwProcId; // Hardware processor id x0C-x0F
38
39 u32 xTypeNum; // Card Type/CCIN number x10-x13
40 u32 xModelNum; // Model/Feature number x14-x17
41 u64 xSerialNum; // Serial number x18-x1F
42 char xPartNum[12]; // Book Part or FPU number x20-x2B
43 char xMfgID[4]; // Manufacturing ID x2C-x2F
44
45 u32 xProcFreq; // Processor Frequency x30-x33
46 u32 xTimeBaseFreq; // Time Base Frequency x34-x37
47
48 u32 xChipEcLevel; // Chip EC Levels x38-x3B
49 u32 xProcIdReg; // PIR SPR value x3C-x3F
50 u32 xPVR; // PVR value x40-x43
51 u8 xRsvd3[12]; // Reserved x44-x4F
52
53 u32 xInstCacheSize; // Instruction cache size in KB x50-x53
54 u32 xInstBlockSize; // Instruction cache block size x54-x57
55 u32 xDataCacheOperandSize; // Data cache operand size x58-x5B
56 u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F
57
58 u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63
59 u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67
60 u64 xRsvd4; // Reserved x68-x6F
61
62 u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73
63 u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77
64 u64 xRsvd5; // Reserved x78-x7F
65
66 u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83
67 u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87
68 u64 xRsvd6; // Reserved x88-x8F
69
70 u64 xFruLabel; // Card Location Label x90-x97
71 u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98
72 u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99
73 u16 xSlotMapIndex; // Index in slot map table x9A-x9B
74 u8 xSmartCardPortNo; // Smart card port number x9C-x9C
75 u8 xRsvd7; // Reserved x9D-x9D
76 u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F
77
78 u8 xRsvd8[24]; // Reserved xA0-xB7
79
80 char xProcSrc[72]; // CSP format SRC xB8-xFF
81};
82
83extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
84
85#endif /* _ISERIES_PROCESSOR_VPD_H */
diff --git a/arch/powerpc/platforms/iseries/release_data.h b/arch/powerpc/platforms/iseries/release_data.h
deleted file mode 100644
index 6ad7d843e8fc..000000000000
--- a/arch/powerpc/platforms/iseries/release_data.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISERIES_RELEASE_DATA_H
19#define _ISERIES_RELEASE_DATA_H
20
21/*
22 * This control block contains the critical information about the
23 * release so that it can be changed in the future (ie, the virtual
24 * address of the OS's NACA).
25 */
26#include <asm/types.h>
27#include "naca.h"
28
29/*
30 * When we IPL a secondary partition, we will check if if the
31 * secondary xMinPlicVrmIndex > the primary xVrmIndex.
32 * If it is then this tells PLIC that this secondary is not
33 * supported running on this "old" of a level of PLIC.
34 *
35 * Likewise, we will compare the primary xMinSlicVrmIndex to
36 * the secondary xVrmIndex.
37 * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
38 * know that this PLIC does not support running an OS "that old".
39 */
40
41#define HVREL_TAGSINACTIVE 0x8000
42#define HVREL_32BIT 0x4000
43#define HVREL_NOSHAREDPROCS 0x2000
44#define HVREL_NOHMT 0x1000
45
46struct HvReleaseData {
47 u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */
48 u16 xSize; /* Size of this control block x04-x05 */
49 u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
50 struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
51 u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
52 u32 xRsvd1; /* Reserved x14-x17 */
53 u16 xFlags;
54 u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */
55 u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */
56 u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
57 char xVrmName[12]; /* Displayable name x20-x2B */
58 char xRsvd3[20]; /* Reserved x2C-x3F */
59};
60
61extern const struct HvReleaseData hvReleaseData;
62
63#endif /* _ISERIES_RELEASE_DATA_H */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
deleted file mode 100644
index a5fbf4cb6329..000000000000
--- a/arch/powerpc/platforms/iseries/setup.c
+++ /dev/null
@@ -1,718 +0,0 @@
1/*
2 * Copyright (c) 2000 Mike Corrigan <mikejc@us.ibm.com>
3 * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
4 *
5 * Description:
6 * Architecture- / platform-specific boot-time initialization code for
7 * the IBM iSeries LPAR. Adapted from original code by Grant Erickson and
8 * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
9 * <dan@net4x.com>.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#undef DEBUG
18
19#include <linux/init.h>
20#include <linux/threads.h>
21#include <linux/smp.h>
22#include <linux/param.h>
23#include <linux/string.h>
24#include <linux/export.h>
25#include <linux/seq_file.h>
26#include <linux/kdev_t.h>
27#include <linux/kexec.h>
28#include <linux/major.h>
29#include <linux/root_dev.h>
30#include <linux/kernel.h>
31#include <linux/hrtimer.h>
32#include <linux/tick.h>
33
34#include <asm/processor.h>
35#include <asm/machdep.h>
36#include <asm/page.h>
37#include <asm/mmu.h>
38#include <asm/pgtable.h>
39#include <asm/mmu_context.h>
40#include <asm/cputable.h>
41#include <asm/sections.h>
42#include <asm/iommu.h>
43#include <asm/firmware.h>
44#include <asm/system.h>
45#include <asm/time.h>
46#include <asm/paca.h>
47#include <asm/cache.h>
48#include <asm/abs_addr.h>
49#include <asm/iseries/hv_lp_config.h>
50#include <asm/iseries/hv_call_event.h>
51#include <asm/iseries/hv_call_xm.h>
52#include <asm/iseries/it_lp_queue.h>
53#include <asm/iseries/mf.h>
54#include <asm/iseries/hv_lp_event.h>
55#include <asm/iseries/lpar_map.h>
56#include <asm/udbg.h>
57#include <asm/irq.h>
58
59#include "naca.h"
60#include "setup.h"
61#include "irq.h"
62#include "vpd_areas.h"
63#include "processor_vpd.h"
64#include "it_lp_naca.h"
65#include "main_store.h"
66#include "call_sm.h"
67#include "call_hpt.h"
68#include "pci.h"
69
70#ifdef DEBUG
71#define DBG(fmt...) udbg_printf(fmt)
72#else
73#define DBG(fmt...)
74#endif
75
76/* Function Prototypes */
77static unsigned long build_iSeries_Memory_Map(void);
78static void iseries_shared_idle(void);
79static void iseries_dedicated_idle(void);
80
81
82struct MemoryBlock {
83 unsigned long absStart;
84 unsigned long absEnd;
85 unsigned long logicalStart;
86 unsigned long logicalEnd;
87};
88
89/*
90 * Process the main store vpd to determine where the holes in memory are
91 * and return the number of physical blocks and fill in the array of
92 * block data.
93 */
94static unsigned long iSeries_process_Condor_mainstore_vpd(
95 struct MemoryBlock *mb_array, unsigned long max_entries)
96{
97 unsigned long holeFirstChunk, holeSizeChunks;
98 unsigned long numMemoryBlocks = 1;
99 struct IoHriMainStoreSegment4 *msVpd =
100 (struct IoHriMainStoreSegment4 *)xMsVpd;
101 unsigned long holeStart = msVpd->nonInterleavedBlocksStartAdr;
102 unsigned long holeEnd = msVpd->nonInterleavedBlocksEndAdr;
103 unsigned long holeSize = holeEnd - holeStart;
104
105 printk("Mainstore_VPD: Condor\n");
106 /*
107 * Determine if absolute memory has any
108 * holes so that we can interpret the
109 * access map we get back from the hypervisor
110 * correctly.
111 */
112 mb_array[0].logicalStart = 0;
113 mb_array[0].logicalEnd = 0x100000000UL;
114 mb_array[0].absStart = 0;
115 mb_array[0].absEnd = 0x100000000UL;
116
117 if (holeSize) {
118 numMemoryBlocks = 2;
119 holeStart = holeStart & 0x000fffffffffffffUL;
120 holeStart = addr_to_chunk(holeStart);
121 holeFirstChunk = holeStart;
122 holeSize = addr_to_chunk(holeSize);
123 holeSizeChunks = holeSize;
124 printk( "Main store hole: start chunk = %0lx, size = %0lx chunks\n",
125 holeFirstChunk, holeSizeChunks );
126 mb_array[0].logicalEnd = holeFirstChunk;
127 mb_array[0].absEnd = holeFirstChunk;
128 mb_array[1].logicalStart = holeFirstChunk;
129 mb_array[1].logicalEnd = 0x100000000UL - holeSizeChunks;
130 mb_array[1].absStart = holeFirstChunk + holeSizeChunks;
131 mb_array[1].absEnd = 0x100000000UL;
132 }
133 return numMemoryBlocks;
134}
135
136#define MaxSegmentAreas 32
137#define MaxSegmentAdrRangeBlocks 128
138#define MaxAreaRangeBlocks 4
139
140static unsigned long iSeries_process_Regatta_mainstore_vpd(
141 struct MemoryBlock *mb_array, unsigned long max_entries)
142{
143 struct IoHriMainStoreSegment5 *msVpdP =
144 (struct IoHriMainStoreSegment5 *)xMsVpd;
145 unsigned long numSegmentBlocks = 0;
146 u32 existsBits = msVpdP->msAreaExists;
147 unsigned long area_num;
148
149 printk("Mainstore_VPD: Regatta\n");
150
151 for (area_num = 0; area_num < MaxSegmentAreas; ++area_num ) {
152 unsigned long numAreaBlocks;
153 struct IoHriMainStoreArea4 *currentArea;
154
155 if (existsBits & 0x80000000) {
156 unsigned long block_num;
157
158 currentArea = &msVpdP->msAreaArray[area_num];
159 numAreaBlocks = currentArea->numAdrRangeBlocks;
160 printk("ms_vpd: processing area %2ld blocks=%ld",
161 area_num, numAreaBlocks);
162 for (block_num = 0; block_num < numAreaBlocks;
163 ++block_num ) {
164 /* Process an address range block */
165 struct MemoryBlock tempBlock;
166 unsigned long i;
167
168 tempBlock.absStart =
169 (unsigned long)currentArea->xAdrRangeBlock[block_num].blockStart;
170 tempBlock.absEnd =
171 (unsigned long)currentArea->xAdrRangeBlock[block_num].blockEnd;
172 tempBlock.logicalStart = 0;
173 tempBlock.logicalEnd = 0;
174 printk("\n block %ld absStart=%016lx absEnd=%016lx",
175 block_num, tempBlock.absStart,
176 tempBlock.absEnd);
177
178 for (i = 0; i < numSegmentBlocks; ++i) {
179 if (mb_array[i].absStart ==
180 tempBlock.absStart)
181 break;
182 }
183 if (i == numSegmentBlocks) {
184 if (numSegmentBlocks == max_entries)
185 panic("iSeries_process_mainstore_vpd: too many memory blocks");
186 mb_array[numSegmentBlocks] = tempBlock;
187 ++numSegmentBlocks;
188 } else
189 printk(" (duplicate)");
190 }
191 printk("\n");
192 }
193 existsBits <<= 1;
194 }
195 /* Now sort the blocks found into ascending sequence */
196 if (numSegmentBlocks > 1) {
197 unsigned long m, n;
198
199 for (m = 0; m < numSegmentBlocks - 1; ++m) {
200 for (n = numSegmentBlocks - 1; m < n; --n) {
201 if (mb_array[n].absStart <
202 mb_array[n-1].absStart) {
203 struct MemoryBlock tempBlock;
204
205 tempBlock = mb_array[n];
206 mb_array[n] = mb_array[n-1];
207 mb_array[n-1] = tempBlock;
208 }
209 }
210 }
211 }
212 /*
213 * Assign "logical" addresses to each block. These
214 * addresses correspond to the hypervisor "bitmap" space.
215 * Convert all addresses into units of 256K chunks.
216 */
217 {
218 unsigned long i, nextBitmapAddress;
219
220 printk("ms_vpd: %ld sorted memory blocks\n", numSegmentBlocks);
221 nextBitmapAddress = 0;
222 for (i = 0; i < numSegmentBlocks; ++i) {
223 unsigned long length = mb_array[i].absEnd -
224 mb_array[i].absStart;
225
226 mb_array[i].logicalStart = nextBitmapAddress;
227 mb_array[i].logicalEnd = nextBitmapAddress + length;
228 nextBitmapAddress += length;
229 printk(" Bitmap range: %016lx - %016lx\n"
230 " Absolute range: %016lx - %016lx\n",
231 mb_array[i].logicalStart,
232 mb_array[i].logicalEnd,
233 mb_array[i].absStart, mb_array[i].absEnd);
234 mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
235 0x000fffffffffffffUL);
236 mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd &
237 0x000fffffffffffffUL);
238 mb_array[i].logicalStart =
239 addr_to_chunk(mb_array[i].logicalStart);
240 mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd);
241 }
242 }
243
244 return numSegmentBlocks;
245}
246
247static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
248 unsigned long max_entries)
249{
250 unsigned long i;
251 unsigned long mem_blocks = 0;
252
253 if (mmu_has_feature(MMU_FTR_SLB))
254 mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array,
255 max_entries);
256 else
257 mem_blocks = iSeries_process_Condor_mainstore_vpd(mb_array,
258 max_entries);
259
260 printk("Mainstore_VPD: numMemoryBlocks = %ld\n", mem_blocks);
261 for (i = 0; i < mem_blocks; ++i) {
262 printk("Mainstore_VPD: block %3ld logical chunks %016lx - %016lx\n"
263 " abs chunks %016lx - %016lx\n",
264 i, mb_array[i].logicalStart, mb_array[i].logicalEnd,
265 mb_array[i].absStart, mb_array[i].absEnd);
266 }
267 return mem_blocks;
268}
269
270static void __init iSeries_get_cmdline(void)
271{
272 char *p, *q;
273
274 /* copy the command line parameter from the primary VSP */
275 HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
276 HvLpDma_Direction_RemoteToLocal);
277
278 p = cmd_line;
279 q = cmd_line + 255;
280 while(p < q) {
281 if (!*p || *p == '\n')
282 break;
283 ++p;
284 }
285 *p = 0;
286}
287
288static void __init iSeries_init_early(void)
289{
290 DBG(" -> iSeries_init_early()\n");
291
292 /* Snapshot the timebase, for use in later recalibration */
293 iSeries_time_init_early();
294
295 /*
296 * Initialize the DMA/TCE management
297 */
298 iommu_init_early_iSeries();
299
300 /* Initialize machine-dependency vectors */
301#ifdef CONFIG_SMP
302 smp_init_iSeries();
303#endif
304
305 /* Associate Lp Event Queue 0 with processor 0 */
306 HvCallEvent_setLpEventQueueInterruptProc(0, 0);
307
308 mf_init();
309
310 DBG(" <- iSeries_init_early()\n");
311}
312
313struct mschunks_map mschunks_map = {
314 /* XXX We don't use these, but Piranha might need them. */
315 .chunk_size = MSCHUNKS_CHUNK_SIZE,
316 .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
317 .chunk_mask = MSCHUNKS_OFFSET_MASK,
318};
319EXPORT_SYMBOL(mschunks_map);
320
321static void mschunks_alloc(unsigned long num_chunks)
322{
323 klimit = _ALIGN(klimit, sizeof(u32));
324 mschunks_map.mapping = (u32 *)klimit;
325 klimit += num_chunks * sizeof(u32);
326 mschunks_map.num_chunks = num_chunks;
327}
328
329/*
330 * The iSeries may have very large memories ( > 128 GB ) and a partition
331 * may get memory in "chunks" that may be anywhere in the 2**52 real
332 * address space. The chunks are 256K in size. To map this to the
333 * memory model Linux expects, the AS/400 specific code builds a
334 * translation table to translate what Linux thinks are "physical"
335 * addresses to the actual real addresses. This allows us to make
336 * it appear to Linux that we have contiguous memory starting at
337 * physical address zero while in fact this could be far from the truth.
338 * To avoid confusion, I'll let the words physical and/or real address
339 * apply to the Linux addresses while I'll use "absolute address" to
340 * refer to the actual hardware real address.
341 *
342 * build_iSeries_Memory_Map gets information from the Hypervisor and
343 * looks at the Main Store VPD to determine the absolute addresses
344 * of the memory that has been assigned to our partition and builds
345 * a table used to translate Linux's physical addresses to these
346 * absolute addresses. Absolute addresses are needed when
347 * communicating with the hypervisor (e.g. to build HPT entries)
348 *
349 * Returns the physical memory size
350 */
351
352static unsigned long __init build_iSeries_Memory_Map(void)
353{
354 u32 loadAreaFirstChunk, loadAreaLastChunk, loadAreaSize;
355 u32 nextPhysChunk;
356 u32 hptFirstChunk, hptLastChunk, hptSizeChunks, hptSizePages;
357 u32 totalChunks,moreChunks;
358 u32 currChunk, thisChunk, absChunk;
359 u32 currDword;
360 u32 chunkBit;
361 u64 map;
362 struct MemoryBlock mb[32];
363 unsigned long numMemoryBlocks, curBlock;
364
365 /* Chunk size on iSeries is 256K bytes */
366 totalChunks = (u32)HvLpConfig_getMsChunks();
367 mschunks_alloc(totalChunks);
368
369 /*
370 * Get absolute address of our load area
371 * and map it to physical address 0
372 * This guarantees that the loadarea ends up at physical 0
373 * otherwise, it might not be returned by PLIC as the first
374 * chunks
375 */
376
377 loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr);
378 loadAreaSize = itLpNaca.xLoadAreaChunks;
379
380 /*
381 * Only add the pages already mapped here.
382 * Otherwise we might add the hpt pages
383 * The rest of the pages of the load area
384 * aren't in the HPT yet and can still
385 * be assigned an arbitrary physical address
386 */
387 if ((loadAreaSize * 64) > HvPagesToMap)
388 loadAreaSize = HvPagesToMap / 64;
389
390 loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1;
391
392 /*
393 * TODO Do we need to do something if the HPT is in the 64MB load area?
394 * This would be required if the itLpNaca.xLoadAreaChunks includes
395 * the HPT size
396 */
397
398 printk("Mapping load area - physical addr = 0000000000000000\n"
399 " absolute addr = %016lx\n",
400 chunk_to_addr(loadAreaFirstChunk));
401 printk("Load area size %dK\n", loadAreaSize * 256);
402
403 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
404 mschunks_map.mapping[nextPhysChunk] =
405 loadAreaFirstChunk + nextPhysChunk;
406
407 /*
408 * Get absolute address of our HPT and remember it so
409 * we won't map it to any physical address
410 */
411 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
412 hptSizePages = (u32)HvCallHpt_getHptPages();
413 hptSizeChunks = hptSizePages >>
414 (MSCHUNKS_CHUNK_SHIFT - HW_PAGE_SHIFT);
415 hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
416
417 printk("HPT absolute addr = %016lx, size = %dK\n",
418 chunk_to_addr(hptFirstChunk), hptSizeChunks * 256);
419
420 /*
421 * Determine if absolute memory has any
422 * holes so that we can interpret the
423 * access map we get back from the hypervisor
424 * correctly.
425 */
426 numMemoryBlocks = iSeries_process_mainstore_vpd(mb, 32);
427
428 /*
429 * Process the main store access map from the hypervisor
430 * to build up our physical -> absolute translation table
431 */
432 curBlock = 0;
433 currChunk = 0;
434 currDword = 0;
435 moreChunks = totalChunks;
436
437 while (moreChunks) {
438 map = HvCallSm_get64BitsOfAccessMap(itLpNaca.xLpIndex,
439 currDword);
440 thisChunk = currChunk;
441 while (map) {
442 chunkBit = map >> 63;
443 map <<= 1;
444 if (chunkBit) {
445 --moreChunks;
446 while (thisChunk >= mb[curBlock].logicalEnd) {
447 ++curBlock;
448 if (curBlock >= numMemoryBlocks)
449 panic("out of memory blocks");
450 }
451 if (thisChunk < mb[curBlock].logicalStart)
452 panic("memory block error");
453
454 absChunk = mb[curBlock].absStart +
455 (thisChunk - mb[curBlock].logicalStart);
456 if (((absChunk < hptFirstChunk) ||
457 (absChunk > hptLastChunk)) &&
458 ((absChunk < loadAreaFirstChunk) ||
459 (absChunk > loadAreaLastChunk))) {
460 mschunks_map.mapping[nextPhysChunk] =
461 absChunk;
462 ++nextPhysChunk;
463 }
464 }
465 ++thisChunk;
466 }
467 ++currDword;
468 currChunk += 64;
469 }
470
471 /*
472 * main store size (in chunks) is
473 * totalChunks - hptSizeChunks
474 * which should be equal to
475 * nextPhysChunk
476 */
477 return chunk_to_addr(nextPhysChunk);
478}
479
480/*
481 * Document me.
482 */
483static void __init iSeries_setup_arch(void)
484{
485 if (get_lppaca()->shared_proc) {
486 ppc_md.idle_loop = iseries_shared_idle;
487 printk(KERN_DEBUG "Using shared processor idle loop\n");
488 } else {
489 ppc_md.idle_loop = iseries_dedicated_idle;
490 printk(KERN_DEBUG "Using dedicated idle loop\n");
491 }
492
493 /* Setup the Lp Event Queue */
494 setup_hvlpevent_queue();
495
496 printk("Max logical processors = %d\n",
497 itVpdAreas.xSlicMaxLogicalProcs);
498 printk("Max physical processors = %d\n",
499 itVpdAreas.xSlicMaxPhysicalProcs);
500
501 iSeries_pcibios_init();
502}
503
504static void iSeries_show_cpuinfo(struct seq_file *m)
505{
506 seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
507}
508
509static void __init iSeries_progress(char * st, unsigned short code)
510{
511 printk("Progress: [%04x] - %s\n", (unsigned)code, st);
512 mf_display_progress(code);
513}
514
515static void __init iSeries_fixup_klimit(void)
516{
517 /*
518 * Change klimit to take into account any ram disk
519 * that may be included
520 */
521 if (naca.xRamDisk)
522 klimit = KERNELBASE + (u64)naca.xRamDisk +
523 (naca.xRamDiskSize * HW_PAGE_SIZE);
524}
525
526static int __init iSeries_src_init(void)
527{
528 /* clear the progress line */
529 if (firmware_has_feature(FW_FEATURE_ISERIES))
530 ppc_md.progress(" ", 0xffff);
531 return 0;
532}
533
534late_initcall(iSeries_src_init);
535
536static inline void process_iSeries_events(void)
537{
538 asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
539}
540
541static void yield_shared_processor(void)
542{
543 unsigned long tb;
544
545 HvCall_setEnabledInterrupts(HvCall_MaskIPI |
546 HvCall_MaskLpEvent |
547 HvCall_MaskLpProd |
548 HvCall_MaskTimeout);
549
550 tb = get_tb();
551 /* Compute future tb value when yield should expire */
552 HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
553
554 /*
555 * The decrementer stops during the yield. Force a fake decrementer
556 * here and let the timer_interrupt code sort out the actual time.
557 */
558 get_lppaca()->int_dword.fields.decr_int = 1;
559 ppc64_runlatch_on();
560 process_iSeries_events();
561}
562
563static void iseries_shared_idle(void)
564{
565 while (1) {
566 tick_nohz_idle_enter();
567 rcu_idle_enter();
568 while (!need_resched() && !hvlpevent_is_pending()) {
569 local_irq_disable();
570 ppc64_runlatch_off();
571
572 /* Recheck with irqs off */
573 if (!need_resched() && !hvlpevent_is_pending())
574 yield_shared_processor();
575
576 HMT_medium();
577 local_irq_enable();
578 }
579
580 ppc64_runlatch_on();
581 rcu_idle_exit();
582 tick_nohz_idle_exit();
583
584 if (hvlpevent_is_pending())
585 process_iSeries_events();
586
587 schedule_preempt_disabled();
588 }
589}
590
591static void iseries_dedicated_idle(void)
592{
593 set_thread_flag(TIF_POLLING_NRFLAG);
594
595 while (1) {
596 tick_nohz_idle_enter();
597 rcu_idle_enter();
598 if (!need_resched()) {
599 while (!need_resched()) {
600 ppc64_runlatch_off();
601 HMT_low();
602
603 if (hvlpevent_is_pending()) {
604 HMT_medium();
605 ppc64_runlatch_on();
606 process_iSeries_events();
607 }
608 }
609
610 HMT_medium();
611 }
612
613 ppc64_runlatch_on();
614 rcu_idle_exit();
615 tick_nohz_idle_exit();
616 schedule_preempt_disabled();
617 }
618}
619
620static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size,
621 unsigned long flags, void *caller)
622{
623 return (void __iomem *)address;
624}
625
626static void iseries_iounmap(volatile void __iomem *token)
627{
628}
629
630static int __init iseries_probe(void)
631{
632 unsigned long root = of_get_flat_dt_root();
633 if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
634 return 0;
635
636 hpte_init_iSeries();
637 /* iSeries does not support 16M pages */
638 cur_cpu_spec->mmu_features &= ~MMU_FTR_16M_PAGE;
639
640 return 1;
641}
642
643#ifdef CONFIG_KEXEC
644static int iseries_kexec_prepare(struct kimage *image)
645{
646 return -ENOSYS;
647}
648#endif
649
650define_machine(iseries) {
651 .name = "iSeries",
652 .setup_arch = iSeries_setup_arch,
653 .show_cpuinfo = iSeries_show_cpuinfo,
654 .init_IRQ = iSeries_init_IRQ,
655 .get_irq = iSeries_get_irq,
656 .init_early = iSeries_init_early,
657 .pcibios_fixup = iSeries_pci_final_fixup,
658 .pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
659 .restart = mf_reboot,
660 .power_off = mf_power_off,
661 .halt = mf_power_off,
662 .get_boot_time = iSeries_get_boot_time,
663 .set_rtc_time = iSeries_set_rtc_time,
664 .get_rtc_time = iSeries_get_rtc_time,
665 .calibrate_decr = generic_calibrate_decr,
666 .progress = iSeries_progress,
667 .probe = iseries_probe,
668 .ioremap = iseries_ioremap,
669 .iounmap = iseries_iounmap,
670#ifdef CONFIG_KEXEC
671 .machine_kexec_prepare = iseries_kexec_prepare,
672#endif
673 /* XXX Implement enable_pmcs for iSeries */
674};
675
676void * __init iSeries_early_setup(void)
677{
678 unsigned long phys_mem_size;
679
680 /* Identify CPU type. This is done again by the common code later
681 * on but calling this function multiple times is fine.
682 */
683 identify_cpu(0, mfspr(SPRN_PVR));
684 initialise_paca(&boot_paca, 0);
685
686 powerpc_firmware_features |= FW_FEATURE_ISERIES;
687 powerpc_firmware_features |= FW_FEATURE_LPAR;
688
689#ifdef CONFIG_SMP
690 /* On iSeries we know we can never have more than 64 cpus */
691 nr_cpu_ids = max(nr_cpu_ids, 64);
692#endif
693
694 iSeries_fixup_klimit();
695
696 /*
697 * Initialize the table which translate Linux physical addresses to
698 * AS/400 absolute addresses
699 */
700 phys_mem_size = build_iSeries_Memory_Map();
701
702 iSeries_get_cmdline();
703
704 return (void *) __pa(build_flat_dt(phys_mem_size));
705}
706
707static void hvputc(char c)
708{
709 if (c == '\n')
710 hvputc('\r');
711
712 HvCall_writeLogBuffer(&c, 1);
713}
714
715void __init udbg_init_iseries(void)
716{
717 udbg_putc = hvputc;
718}
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
deleted file mode 100644
index 729754bbb018..000000000000
--- a/arch/powerpc/platforms/iseries/setup.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/*
2 * Copyright (c) 2000 Mike Corrigan <mikejc@us.ibm.com>
3 * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
4 *
5 * Description:
6 * Architecture- / platform-specific boot-time initialization code for
7 * the IBM AS/400 LPAR. Adapted from original code by Grant Erickson and
8 * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
9 * <dan@netx4.com>.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
17#ifndef __ISERIES_SETUP_H__
18#define __ISERIES_SETUP_H__
19
20extern void *iSeries_early_setup(void);
21extern unsigned long iSeries_get_boot_time(void);
22extern int iSeries_set_rtc_time(struct rtc_time *tm);
23extern void iSeries_get_rtc_time(struct rtc_time *tm);
24
25extern void *build_flat_dt(unsigned long phys_mem_size);
26
27#endif /* __ISERIES_SETUP_H__ */
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
deleted file mode 100644
index 02df49fb59f0..000000000000
--- a/arch/powerpc/platforms/iseries/smp.c
+++ /dev/null
@@ -1,88 +0,0 @@
1/*
2 * SMP support for iSeries machines.
3 *
4 * Dave Engebretsen, Peter Bergner, and
5 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
6 *
7 * Plus various changes from other IBM teams...
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#undef DEBUG
16
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/smp.h>
20#include <linux/interrupt.h>
21#include <linux/kernel_stat.h>
22#include <linux/delay.h>
23#include <linux/init.h>
24#include <linux/spinlock.h>
25#include <linux/cache.h>
26#include <linux/err.h>
27#include <linux/device.h>
28#include <linux/cpu.h>
29
30#include <asm/ptrace.h>
31#include <linux/atomic.h>
32#include <asm/irq.h>
33#include <asm/page.h>
34#include <asm/pgtable.h>
35#include <asm/io.h>
36#include <asm/smp.h>
37#include <asm/paca.h>
38#include <asm/iseries/hv_call.h>
39#include <asm/time.h>
40#include <asm/machdep.h>
41#include <asm/cputable.h>
42#include <asm/system.h>
43
44static void smp_iSeries_cause_ipi(int cpu, unsigned long data)
45{
46 HvCall_sendIPI(&(paca[cpu]));
47}
48
49static int smp_iSeries_probe(void)
50{
51 return cpumask_weight(cpu_possible_mask);
52}
53
54static int smp_iSeries_kick_cpu(int nr)
55{
56 BUG_ON((nr < 0) || (nr >= NR_CPUS));
57
58 /* Verify that our partition has a processor nr */
59 if (lppaca_of(nr).dyn_proc_status >= 2)
60 return -ENOENT;
61
62 /* The processor is currently spinning, waiting
63 * for the cpu_start field to become non-zero
64 * After we set cpu_start, the processor will
65 * continue on to secondary_start in iSeries_head.S
66 */
67 paca[nr].cpu_start = 1;
68
69 return 0;
70}
71
72static void __devinit smp_iSeries_setup_cpu(int nr)
73{
74}
75
76static struct smp_ops_t iSeries_smp_ops = {
77 .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
78 .cause_ipi = smp_iSeries_cause_ipi,
79 .probe = smp_iSeries_probe,
80 .kick_cpu = smp_iSeries_kick_cpu,
81 .setup_cpu = smp_iSeries_setup_cpu,
82};
83
84/* This is called very early. */
85void __init smp_init_iSeries(void)
86{
87 smp_ops = &iSeries_smp_ops;
88}
diff --git a/arch/powerpc/platforms/iseries/spcomm_area.h b/arch/powerpc/platforms/iseries/spcomm_area.h
deleted file mode 100644
index 598b7c14573a..000000000000
--- a/arch/powerpc/platforms/iseries/spcomm_area.h
+++ /dev/null
@@ -1,34 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#ifndef _ISERIES_SPCOMM_AREA_H
20#define _ISERIES_SPCOMM_AREA_H
21
22
23struct SpCommArea {
24 u32 xDesc; // Descriptor (only in new formats) 000-003
25 u8 xFormat; // Format (only in new formats) 004-004
26 u8 xRsvd1[11]; // Reserved 005-00F
27 u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017
28 u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F
29 u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027
30 u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F
31 u8 xRsvd2[80]; // Reserved 030-07F
32};
33
34#endif /* _ISERIES_SPCOMM_AREA_H */
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
deleted file mode 100644
index 04be62d368a6..000000000000
--- a/arch/powerpc/platforms/iseries/vio.c
+++ /dev/null
@@ -1,556 +0,0 @@
1/*
2 * Legacy iSeries specific vio initialisation
3 * that needs to be built in (not a module).
4 *
5 * © Copyright 2007 IBM Corporation
6 * Author: Stephen Rothwell
7 * Some parts collected from various other files
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/of.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/completion.h>
27#include <linux/proc_fs.h>
28#include <linux/export.h>
29
30#include <asm/firmware.h>
31#include <asm/vio.h>
32#include <asm/iseries/vio.h>
33#include <asm/iseries/iommu.h>
34#include <asm/iseries/hv_types.h>
35#include <asm/iseries/hv_lp_event.h>
36
37#define FIRST_VTY 0
38#define NUM_VTYS 1
39#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
40#define NUM_VSCSIS 1
41#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
42#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
43#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
44#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
45#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
46#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
47#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
48#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
49
50struct vio_waitevent {
51 struct completion com;
52 int rc;
53 u16 sub_result;
54};
55
56struct vio_resource {
57 char rsrcname[10];
58 char type[4];
59 char model[3];
60};
61
62static struct property *new_property(const char *name, int length,
63 const void *value)
64{
65 struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
66 GFP_KERNEL);
67
68 if (!np)
69 return NULL;
70 np->name = (char *)(np + 1);
71 np->value = np->name + strlen(name) + 1;
72 strcpy(np->name, name);
73 memcpy(np->value, value, length);
74 np->length = length;
75 return np;
76}
77
78static void free_property(struct property *np)
79{
80 kfree(np);
81}
82
83static struct device_node *new_node(const char *path,
84 struct device_node *parent)
85{
86 struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
87
88 if (!np)
89 return NULL;
90 np->full_name = kstrdup(path, GFP_KERNEL);
91 if (!np->full_name) {
92 kfree(np);
93 return NULL;
94 }
95 of_node_set_flag(np, OF_DYNAMIC);
96 kref_init(&np->kref);
97 np->parent = of_node_get(parent);
98 return np;
99}
100
101static void free_node(struct device_node *np)
102{
103 struct property *next;
104 struct property *prop;
105
106 next = np->properties;
107 while (next) {
108 prop = next;
109 next = prop->next;
110 free_property(prop);
111 }
112 of_node_put(np->parent);
113 kfree(np->full_name);
114 kfree(np);
115}
116
117static int add_string_property(struct device_node *np, const char *name,
118 const char *value)
119{
120 struct property *nprop = new_property(name, strlen(value) + 1, value);
121
122 if (!nprop)
123 return 0;
124 prom_add_property(np, nprop);
125 return 1;
126}
127
128static int add_raw_property(struct device_node *np, const char *name,
129 int length, const void *value)
130{
131 struct property *nprop = new_property(name, length, value);
132
133 if (!nprop)
134 return 0;
135 prom_add_property(np, nprop);
136 return 1;
137}
138
139static struct device_node *do_device_node(struct device_node *parent,
140 const char *name, u32 reg, u32 unit, const char *type,
141 const char *compat, struct vio_resource *res)
142{
143 struct device_node *np;
144 char path[32];
145
146 snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
147 np = new_node(path, parent);
148 if (!np)
149 return NULL;
150 if (!add_string_property(np, "name", name) ||
151 !add_string_property(np, "device_type", type) ||
152 !add_string_property(np, "compatible", compat) ||
153 !add_raw_property(np, "reg", sizeof(reg), &reg) ||
154 !add_raw_property(np, "linux,unit_address",
155 sizeof(unit), &unit)) {
156 goto node_free;
157 }
158 if (res) {
159 if (!add_raw_property(np, "linux,vio_rsrcname",
160 sizeof(res->rsrcname), res->rsrcname) ||
161 !add_raw_property(np, "linux,vio_type",
162 sizeof(res->type), res->type) ||
163 !add_raw_property(np, "linux,vio_model",
164 sizeof(res->model), res->model))
165 goto node_free;
166 }
167 np->name = of_get_property(np, "name", NULL);
168 np->type = of_get_property(np, "device_type", NULL);
169 of_attach_node(np);
170#ifdef CONFIG_PROC_DEVICETREE
171 if (parent->pde) {
172 struct proc_dir_entry *ent;
173
174 ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
175 if (ent)
176 proc_device_tree_add_node(np, ent);
177 }
178#endif
179 return np;
180
181 node_free:
182 free_node(np);
183 return NULL;
184}
185
186/*
187 * This is here so that we can dynamically add viodasd
188 * devices without exposing all the above infrastructure.
189 */
190struct vio_dev *vio_create_viodasd(u32 unit)
191{
192 struct device_node *vio_root;
193 struct device_node *np;
194 struct vio_dev *vdev = NULL;
195
196 vio_root = of_find_node_by_path("/vdevice");
197 if (!vio_root)
198 return NULL;
199 np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
200 "block", "IBM,iSeries-viodasd", NULL);
201 of_node_put(vio_root);
202 if (np) {
203 vdev = vio_register_device_node(np);
204 if (!vdev)
205 free_node(np);
206 }
207 return vdev;
208}
209EXPORT_SYMBOL_GPL(vio_create_viodasd);
210
211static void __init handle_block_event(struct HvLpEvent *event)
212{
213 struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
214 struct vio_waitevent *pwe;
215
216 if (event == NULL)
217 /* Notification that a partition went away! */
218 return;
219 /* First, we should NEVER get an int here...only acks */
220 if (hvlpevent_is_int(event)) {
221 printk(KERN_WARNING "handle_viod_request: "
222 "Yikes! got an int in viodasd event handler!\n");
223 if (hvlpevent_need_ack(event)) {
224 event->xRc = HvLpEvent_Rc_InvalidSubtype;
225 HvCallEvent_ackLpEvent(event);
226 }
227 return;
228 }
229
230 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
231 case vioblockopen:
232 /*
233 * Handle a response to an open request. We get all the
234 * disk information in the response, so update it. The
235 * correlation token contains a pointer to a waitevent
236 * structure that has a completion in it. update the
237 * return code in the waitevent structure and post the
238 * completion to wake up the guy who sent the request
239 */
240 pwe = (struct vio_waitevent *)event->xCorrelationToken;
241 pwe->rc = event->xRc;
242 pwe->sub_result = bevent->sub_result;
243 complete(&pwe->com);
244 break;
245 case vioblockclose:
246 break;
247 default:
248 printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
249 if (hvlpevent_need_ack(event)) {
250 event->xRc = HvLpEvent_Rc_InvalidSubtype;
251 HvCallEvent_ackLpEvent(event);
252 }
253 }
254}
255
256static void __init probe_disk(struct device_node *vio_root, u32 unit)
257{
258 HvLpEvent_Rc hvrc;
259 struct vio_waitevent we;
260 u16 flags = 0;
261
262retry:
263 init_completion(&we.com);
264
265 /* Send the open event to OS/400 */
266 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
267 HvLpEvent_Type_VirtualIo,
268 viomajorsubtype_blockio | vioblockopen,
269 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
270 viopath_sourceinst(viopath_hostLp),
271 viopath_targetinst(viopath_hostLp),
272 (u64)(unsigned long)&we, VIOVERSION << 16,
273 ((u64)unit << 48) | ((u64)flags<< 32),
274 0, 0, 0);
275 if (hvrc != 0) {
276 printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
277 (int)hvrc);
278 return;
279 }
280
281 wait_for_completion(&we.com);
282
283 if (we.rc != 0) {
284 if (flags != 0)
285 return;
286 /* try again with read only flag set */
287 flags = vioblockflags_ro;
288 goto retry;
289 }
290
291 /* Send the close event to OS/400. We DON'T expect a response */
292 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
293 HvLpEvent_Type_VirtualIo,
294 viomajorsubtype_blockio | vioblockclose,
295 HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
296 viopath_sourceinst(viopath_hostLp),
297 viopath_targetinst(viopath_hostLp),
298 0, VIOVERSION << 16,
299 ((u64)unit << 48) | ((u64)flags << 32),
300 0, 0, 0);
301 if (hvrc != 0) {
302 printk(KERN_WARNING "probe_disk: "
303 "bad rc sending event to OS/400 %d\n", (int)hvrc);
304 return;
305 }
306
307 do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
308 "block", "IBM,iSeries-viodasd", NULL);
309}
310
311static void __init get_viodasd_info(struct device_node *vio_root)
312{
313 int rc;
314 u32 unit;
315
316 rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
317 if (rc) {
318 printk(KERN_WARNING "get_viodasd_info: "
319 "error opening path to host partition %d\n",
320 viopath_hostLp);
321 return;
322 }
323
324 /* Initialize our request handler */
325 vio_setHandler(viomajorsubtype_blockio, handle_block_event);
326
327 for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
328 probe_disk(vio_root, unit);
329
330 vio_clearHandler(viomajorsubtype_blockio);
331 viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
332}
333
334static void __init handle_cd_event(struct HvLpEvent *event)
335{
336 struct viocdlpevent *bevent;
337 struct vio_waitevent *pwe;
338
339 if (!event)
340 /* Notification that a partition went away! */
341 return;
342
343 /* First, we should NEVER get an int here...only acks */
344 if (hvlpevent_is_int(event)) {
345 printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
346 if (hvlpevent_need_ack(event)) {
347 event->xRc = HvLpEvent_Rc_InvalidSubtype;
348 HvCallEvent_ackLpEvent(event);
349 }
350 return;
351 }
352
353 bevent = (struct viocdlpevent *)event;
354
355 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
356 case viocdgetinfo:
357 pwe = (struct vio_waitevent *)event->xCorrelationToken;
358 pwe->rc = event->xRc;
359 pwe->sub_result = bevent->sub_result;
360 complete(&pwe->com);
361 break;
362
363 default:
364 printk(KERN_WARNING "handle_cd_event: "
365 "message with unexpected subtype %0x04X!\n",
366 event->xSubtype & VIOMINOR_SUBTYPE_MASK);
367 if (hvlpevent_need_ack(event)) {
368 event->xRc = HvLpEvent_Rc_InvalidSubtype;
369 HvCallEvent_ackLpEvent(event);
370 }
371 }
372}
373
374static void __init get_viocd_info(struct device_node *vio_root)
375{
376 HvLpEvent_Rc hvrc;
377 u32 unit;
378 struct vio_waitevent we;
379 struct vio_resource *unitinfo;
380 dma_addr_t unitinfo_dmaaddr;
381 int ret;
382
383 ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
384 if (ret) {
385 printk(KERN_WARNING
386 "get_viocd_info: error opening path to host partition %d\n",
387 viopath_hostLp);
388 return;
389 }
390
391 /* Initialize our request handler */
392 vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
393
394 unitinfo = iseries_hv_alloc(
395 sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
396 &unitinfo_dmaaddr, GFP_ATOMIC);
397 if (!unitinfo) {
398 printk(KERN_WARNING
399 "get_viocd_info: error allocating unitinfo\n");
400 goto clear_handler;
401 }
402
403 memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
404
405 init_completion(&we.com);
406
407 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
408 HvLpEvent_Type_VirtualIo,
409 viomajorsubtype_cdio | viocdgetinfo,
410 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
411 viopath_sourceinst(viopath_hostLp),
412 viopath_targetinst(viopath_hostLp),
413 (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
414 sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
415 if (hvrc != HvLpEvent_Rc_Good) {
416 printk(KERN_WARNING
417 "get_viocd_info: cdrom error sending event. rc %d\n",
418 (int)hvrc);
419 goto hv_free;
420 }
421
422 wait_for_completion(&we.com);
423
424 if (we.rc) {
425 printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
426 we.rc, we.sub_result);
427 goto hv_free;
428 }
429
430 for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
431 unitinfo[unit].rsrcname[0]; unit++) {
432 if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
433 "block", "IBM,iSeries-viocd", &unitinfo[unit]))
434 break;
435 }
436
437 hv_free:
438 iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
439 unitinfo, unitinfo_dmaaddr);
440 clear_handler:
441 vio_clearHandler(viomajorsubtype_cdio);
442 viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
443}
444
445/* Handle interrupt events for tape */
446static void __init handle_tape_event(struct HvLpEvent *event)
447{
448 struct vio_waitevent *we;
449 struct viotapelpevent *tevent = (struct viotapelpevent *)event;
450
451 if (event == NULL)
452 /* Notification that a partition went away! */
453 return;
454
455 we = (struct vio_waitevent *)event->xCorrelationToken;
456 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
457 case viotapegetinfo:
458 we->rc = tevent->sub_type_result;
459 complete(&we->com);
460 break;
461 default:
462 printk(KERN_WARNING "handle_tape_event: weird ack\n");
463 }
464}
465
466static void __init get_viotape_info(struct device_node *vio_root)
467{
468 HvLpEvent_Rc hvrc;
469 u32 unit;
470 struct vio_resource *unitinfo;
471 dma_addr_t unitinfo_dmaaddr;
472 size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
473 struct vio_waitevent we;
474 int ret;
475
476 init_completion(&we.com);
477
478 ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
479 if (ret) {
480 printk(KERN_WARNING "get_viotape_info: "
481 "error on viopath_open to hostlp %d\n", ret);
482 return;
483 }
484
485 vio_setHandler(viomajorsubtype_tape, handle_tape_event);
486
487 unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
488 if (!unitinfo)
489 goto clear_handler;
490
491 memset(unitinfo, 0, len);
492
493 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
494 HvLpEvent_Type_VirtualIo,
495 viomajorsubtype_tape | viotapegetinfo,
496 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
497 viopath_sourceinst(viopath_hostLp),
498 viopath_targetinst(viopath_hostLp),
499 (u64)(unsigned long)&we, VIOVERSION << 16,
500 unitinfo_dmaaddr, len, 0, 0);
501 if (hvrc != HvLpEvent_Rc_Good) {
502 printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
503 (int)hvrc);
504 goto hv_free;
505 }
506
507 wait_for_completion(&we.com);
508
509 for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
510 unitinfo[unit].rsrcname[0]; unit++) {
511 if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
512 unit, "byte", "IBM,iSeries-viotape",
513 &unitinfo[unit]))
514 break;
515 }
516
517 hv_free:
518 iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
519 clear_handler:
520 vio_clearHandler(viomajorsubtype_tape);
521 viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
522}
523
524static int __init iseries_vio_init(void)
525{
526 struct device_node *vio_root;
527 int ret = -ENODEV;
528
529 if (!firmware_has_feature(FW_FEATURE_ISERIES))
530 goto out;
531
532 iommu_vio_init();
533
534 vio_root = of_find_node_by_path("/vdevice");
535 if (!vio_root)
536 goto out;
537
538 if (viopath_hostLp == HvLpIndexInvalid) {
539 vio_set_hostlp();
540 /* If we don't have a host, bail out */
541 if (viopath_hostLp == HvLpIndexInvalid)
542 goto put_node;
543 }
544
545 get_viodasd_info(vio_root);
546 get_viocd_info(vio_root);
547 get_viotape_info(vio_root);
548
549 ret = 0;
550
551 put_node:
552 of_node_put(vio_root);
553 out:
554 return ret;
555}
556arch_initcall(iseries_vio_init);
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
deleted file mode 100644
index 40dad0840eb3..000000000000
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ /dev/null
@@ -1,677 +0,0 @@
1/* -*- linux-c -*-
2 *
3 * iSeries Virtual I/O Message Path code
4 *
5 * Authors: Dave Boutcher <boutcher@us.ibm.com>
6 * Ryan Arnold <ryanarn@us.ibm.com>
7 * Colin Devilbiss <devilbis@us.ibm.com>
8 *
9 * (C) Copyright 2000-2005 IBM Corporation
10 *
11 * This code is used by the iSeries virtual disk, cd,
12 * tape, and console to communicate with OS/400 in another
13 * partition.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of the
18 * License, or (at your option) anyu later version.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software Foundation,
27 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30#include <linux/export.h>
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/errno.h>
34#include <linux/vmalloc.h>
35#include <linux/string.h>
36#include <linux/proc_fs.h>
37#include <linux/dma-mapping.h>
38#include <linux/wait.h>
39#include <linux/seq_file.h>
40#include <linux/interrupt.h>
41#include <linux/completion.h>
42
43#include <asm/system.h>
44#include <asm/uaccess.h>
45#include <asm/prom.h>
46#include <asm/firmware.h>
47#include <asm/iseries/hv_types.h>
48#include <asm/iseries/hv_lp_event.h>
49#include <asm/iseries/hv_lp_config.h>
50#include <asm/iseries/mf.h>
51#include <asm/iseries/vio.h>
52
53/* Status of the path to each other partition in the system.
54 * This is overkill, since we will only ever establish connections
55 * to our hosting partition and the primary partition on the system.
56 * But this allows for other support in the future.
57 */
58static struct viopathStatus {
59 int isOpen; /* Did we open the path? */
60 int isActive; /* Do we have a mon msg outstanding */
61 int users[VIO_MAX_SUBTYPES];
62 HvLpInstanceId mSourceInst;
63 HvLpInstanceId mTargetInst;
64 int numberAllocated;
65} viopathStatus[HVMAXARCHITECTEDLPS];
66
67static DEFINE_SPINLOCK(statuslock);
68
69/*
70 * For each kind of event we allocate a buffer that is
71 * guaranteed not to cross a page boundary
72 */
73static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256]
74 __attribute__((__aligned__(4096)));
75static atomic_t event_buffer_available[VIO_MAX_SUBTYPES];
76static int event_buffer_initialised;
77
78static void handleMonitorEvent(struct HvLpEvent *event);
79
80/*
81 * We use this structure to handle asynchronous responses. The caller
82 * blocks on the semaphore and the handler posts the semaphore. However,
83 * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ...
84 */
85struct alloc_parms {
86 struct completion done;
87 int number;
88 atomic_t wait_atomic;
89 int used_wait_atomic;
90};
91
92/* Put a sequence number in each mon msg. The value is not
93 * important. Start at something other than 0 just for
94 * readability. wrapping this is ok.
95 */
96static u8 viomonseq = 22;
97
98/* Our hosting logical partition. We get this at startup
99 * time, and different modules access this variable directly.
100 */
101HvLpIndex viopath_hostLp = HvLpIndexInvalid;
102EXPORT_SYMBOL(viopath_hostLp);
103HvLpIndex viopath_ourLp = HvLpIndexInvalid;
104EXPORT_SYMBOL(viopath_ourLp);
105
106/* For each kind of incoming event we set a pointer to a
107 * routine to call.
108 */
109static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES];
110
111#define VIOPATH_KERN_WARN KERN_WARNING "viopath: "
112#define VIOPATH_KERN_INFO KERN_INFO "viopath: "
113
114static int proc_viopath_show(struct seq_file *m, void *v)
115{
116 char *buf;
117 u16 vlanMap;
118 dma_addr_t handle;
119 HvLpEvent_Rc hvrc;
120 DECLARE_COMPLETION_ONSTACK(done);
121 struct device_node *node;
122 const char *sysid;
123
124 buf = kzalloc(HW_PAGE_SIZE, GFP_KERNEL);
125 if (!buf)
126 return 0;
127
128 handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE);
129
130 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
131 HvLpEvent_Type_VirtualIo,
132 viomajorsubtype_config | vioconfigget,
133 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
134 viopath_sourceinst(viopath_hostLp),
135 viopath_targetinst(viopath_hostLp),
136 (u64)(unsigned long)&done, VIOVERSION << 16,
137 ((u64)handle) << 32, HW_PAGE_SIZE, 0, 0);
138
139 if (hvrc != HvLpEvent_Rc_Good)
140 printk(VIOPATH_KERN_WARN "hv error on op %d\n", (int)hvrc);
141
142 wait_for_completion(&done);
143
144 vlanMap = HvLpConfig_getVirtualLanIndexMap();
145
146 buf[HW_PAGE_SIZE-1] = '\0';
147 seq_printf(m, "%s", buf);
148
149 iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE);
150 kfree(buf);
151
152 seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
153
154 node = of_find_node_by_path("/");
155 sysid = NULL;
156 if (node != NULL)
157 sysid = of_get_property(node, "system-id", NULL);
158
159 if (sysid == NULL)
160 seq_printf(m, "SRLNBR=<UNKNOWN>\n");
161 else
162 /* Skip "IBM," on front of serial number, see dt.c */
163 seq_printf(m, "SRLNBR=%s\n", sysid + 4);
164
165 of_node_put(node);
166
167 return 0;
168}
169
170static int proc_viopath_open(struct inode *inode, struct file *file)
171{
172 return single_open(file, proc_viopath_show, NULL);
173}
174
175static const struct file_operations proc_viopath_operations = {
176 .open = proc_viopath_open,
177 .read = seq_read,
178 .llseek = seq_lseek,
179 .release = single_release,
180};
181
182static int __init vio_proc_init(void)
183{
184 if (!firmware_has_feature(FW_FEATURE_ISERIES))
185 return 0;
186
187 proc_create("iSeries/config", 0, NULL, &proc_viopath_operations);
188 return 0;
189}
190__initcall(vio_proc_init);
191
192/* See if a given LP is active. Allow for invalid lps to be passed in
193 * and just return invalid
194 */
195int viopath_isactive(HvLpIndex lp)
196{
197 if (lp == HvLpIndexInvalid)
198 return 0;
199 if (lp < HVMAXARCHITECTEDLPS)
200 return viopathStatus[lp].isActive;
201 else
202 return 0;
203}
204EXPORT_SYMBOL(viopath_isactive);
205
206/*
207 * We cache the source and target instance ids for each
208 * partition.
209 */
210HvLpInstanceId viopath_sourceinst(HvLpIndex lp)
211{
212 return viopathStatus[lp].mSourceInst;
213}
214EXPORT_SYMBOL(viopath_sourceinst);
215
216HvLpInstanceId viopath_targetinst(HvLpIndex lp)
217{
218 return viopathStatus[lp].mTargetInst;
219}
220EXPORT_SYMBOL(viopath_targetinst);
221
222/*
223 * Send a monitor message. This is a message with the acknowledge
224 * bit on that the other side will NOT explicitly acknowledge. When
225 * the other side goes down, the hypervisor will acknowledge any
226 * outstanding messages....so we will know when the other side dies.
227 */
228static void sendMonMsg(HvLpIndex remoteLp)
229{
230 HvLpEvent_Rc hvrc;
231
232 viopathStatus[remoteLp].mSourceInst =
233 HvCallEvent_getSourceLpInstanceId(remoteLp,
234 HvLpEvent_Type_VirtualIo);
235 viopathStatus[remoteLp].mTargetInst =
236 HvCallEvent_getTargetLpInstanceId(remoteLp,
237 HvLpEvent_Type_VirtualIo);
238
239 /*
240 * Deliberately ignore the return code here. if we call this
241 * more than once, we don't care.
242 */
243 vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent);
244
245 hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo,
246 viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck,
247 HvLpEvent_AckType_DeferredAck,
248 viopathStatus[remoteLp].mSourceInst,
249 viopathStatus[remoteLp].mTargetInst,
250 viomonseq++, 0, 0, 0, 0, 0);
251
252 if (hvrc == HvLpEvent_Rc_Good)
253 viopathStatus[remoteLp].isActive = 1;
254 else {
255 printk(VIOPATH_KERN_WARN "could not connect to partition %d\n",
256 remoteLp);
257 viopathStatus[remoteLp].isActive = 0;
258 }
259}
260
261static void handleMonitorEvent(struct HvLpEvent *event)
262{
263 HvLpIndex remoteLp;
264 int i;
265
266 /*
267 * This handler is _also_ called as part of the loop
268 * at the end of this routine, so it must be able to
269 * ignore NULL events...
270 */
271 if (!event)
272 return;
273
274 /*
275 * First see if this is just a normal monitor message from the
276 * other partition
277 */
278 if (hvlpevent_is_int(event)) {
279 remoteLp = event->xSourceLp;
280 if (!viopathStatus[remoteLp].isActive)
281 sendMonMsg(remoteLp);
282 return;
283 }
284
285 /*
286 * This path is for an acknowledgement; the other partition
287 * died
288 */
289 remoteLp = event->xTargetLp;
290 if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) ||
291 (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) {
292 printk(VIOPATH_KERN_WARN "ignoring ack....mismatched instances\n");
293 return;
294 }
295
296 printk(VIOPATH_KERN_WARN "partition %d ended\n", remoteLp);
297
298 viopathStatus[remoteLp].isActive = 0;
299
300 /*
301 * For each active handler, pass them a NULL
302 * message to indicate that the other partition
303 * died
304 */
305 for (i = 0; i < VIO_MAX_SUBTYPES; i++) {
306 if (vio_handler[i] != NULL)
307 (*vio_handler[i])(NULL);
308 }
309}
310
311int vio_setHandler(int subtype, vio_event_handler_t *beh)
312{
313 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
314 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
315 return -EINVAL;
316 if (vio_handler[subtype] != NULL)
317 return -EBUSY;
318 vio_handler[subtype] = beh;
319 return 0;
320}
321EXPORT_SYMBOL(vio_setHandler);
322
323int vio_clearHandler(int subtype)
324{
325 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
326 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
327 return -EINVAL;
328 if (vio_handler[subtype] == NULL)
329 return -EAGAIN;
330 vio_handler[subtype] = NULL;
331 return 0;
332}
333EXPORT_SYMBOL(vio_clearHandler);
334
335static void handleConfig(struct HvLpEvent *event)
336{
337 if (!event)
338 return;
339 if (hvlpevent_is_int(event)) {
340 printk(VIOPATH_KERN_WARN
341 "unexpected config request from partition %d",
342 event->xSourceLp);
343
344 if (hvlpevent_need_ack(event)) {
345 event->xRc = HvLpEvent_Rc_InvalidSubtype;
346 HvCallEvent_ackLpEvent(event);
347 }
348 return;
349 }
350
351 complete((struct completion *)event->xCorrelationToken);
352}
353
354/*
355 * Initialization of the hosting partition
356 */
357void vio_set_hostlp(void)
358{
359 /*
360 * If this has already been set then we DON'T want to either change
361 * it or re-register the proc file system
362 */
363 if (viopath_hostLp != HvLpIndexInvalid)
364 return;
365
366 /*
367 * Figure out our hosting partition. This isn't allowed to change
368 * while we're active
369 */
370 viopath_ourLp = HvLpConfig_getLpIndex();
371 viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
372
373 if (viopath_hostLp != HvLpIndexInvalid)
374 vio_setHandler(viomajorsubtype_config, handleConfig);
375}
376EXPORT_SYMBOL(vio_set_hostlp);
377
378static void vio_handleEvent(struct HvLpEvent *event)
379{
380 HvLpIndex remoteLp;
381 int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
382 >> VIOMAJOR_SUBTYPE_SHIFT;
383
384 if (hvlpevent_is_int(event)) {
385 remoteLp = event->xSourceLp;
386 /*
387 * The isActive is checked because if the hosting partition
388 * went down and came back up it would not be active but it
389 * would have different source and target instances, in which
390 * case we'd want to reset them. This case really protects
391 * against an unauthorized active partition sending interrupts
392 * or acks to this linux partition.
393 */
394 if (viopathStatus[remoteLp].isActive
395 && (event->xSourceInstanceId !=
396 viopathStatus[remoteLp].mTargetInst)) {
397 printk(VIOPATH_KERN_WARN
398 "message from invalid partition. "
399 "int msg rcvd, source inst (%d) doesn't match (%d)\n",
400 viopathStatus[remoteLp].mTargetInst,
401 event->xSourceInstanceId);
402 return;
403 }
404
405 if (viopathStatus[remoteLp].isActive
406 && (event->xTargetInstanceId !=
407 viopathStatus[remoteLp].mSourceInst)) {
408 printk(VIOPATH_KERN_WARN
409 "message from invalid partition. "
410 "int msg rcvd, target inst (%d) doesn't match (%d)\n",
411 viopathStatus[remoteLp].mSourceInst,
412 event->xTargetInstanceId);
413 return;
414 }
415 } else {
416 remoteLp = event->xTargetLp;
417 if (event->xSourceInstanceId !=
418 viopathStatus[remoteLp].mSourceInst) {
419 printk(VIOPATH_KERN_WARN
420 "message from invalid partition. "
421 "ack msg rcvd, source inst (%d) doesn't match (%d)\n",
422 viopathStatus[remoteLp].mSourceInst,
423 event->xSourceInstanceId);
424 return;
425 }
426
427 if (event->xTargetInstanceId !=
428 viopathStatus[remoteLp].mTargetInst) {
429 printk(VIOPATH_KERN_WARN
430 "message from invalid partition. "
431 "viopath: ack msg rcvd, target inst (%d) doesn't match (%d)\n",
432 viopathStatus[remoteLp].mTargetInst,
433 event->xTargetInstanceId);
434 return;
435 }
436 }
437
438 if (vio_handler[subtype] == NULL) {
439 printk(VIOPATH_KERN_WARN
440 "unexpected virtual io event subtype %d from partition %d\n",
441 event->xSubtype, remoteLp);
442 /* No handler. Ack if necessary */
443 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
444 event->xRc = HvLpEvent_Rc_InvalidSubtype;
445 HvCallEvent_ackLpEvent(event);
446 }
447 return;
448 }
449
450 /* This innocuous little line is where all the real work happens */
451 (*vio_handler[subtype])(event);
452}
453
454static void viopath_donealloc(void *parm, int number)
455{
456 struct alloc_parms *parmsp = parm;
457
458 parmsp->number = number;
459 if (parmsp->used_wait_atomic)
460 atomic_set(&parmsp->wait_atomic, 0);
461 else
462 complete(&parmsp->done);
463}
464
465static int allocateEvents(HvLpIndex remoteLp, int numEvents)
466{
467 struct alloc_parms parms;
468
469 if (system_state != SYSTEM_RUNNING) {
470 parms.used_wait_atomic = 1;
471 atomic_set(&parms.wait_atomic, 1);
472 } else {
473 parms.used_wait_atomic = 0;
474 init_completion(&parms.done);
475 }
476 mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */
477 numEvents, &viopath_donealloc, &parms);
478 if (system_state != SYSTEM_RUNNING) {
479 while (atomic_read(&parms.wait_atomic))
480 mb();
481 } else
482 wait_for_completion(&parms.done);
483 return parms.number;
484}
485
486int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
487{
488 int i;
489 unsigned long flags;
490 int tempNumAllocated;
491
492 if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
493 return -EINVAL;
494
495 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
496 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
497 return -EINVAL;
498
499 spin_lock_irqsave(&statuslock, flags);
500
501 if (!event_buffer_initialised) {
502 for (i = 0; i < VIO_MAX_SUBTYPES; i++)
503 atomic_set(&event_buffer_available[i], 1);
504 event_buffer_initialised = 1;
505 }
506
507 viopathStatus[remoteLp].users[subtype]++;
508
509 if (!viopathStatus[remoteLp].isOpen) {
510 viopathStatus[remoteLp].isOpen = 1;
511 HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo);
512
513 /*
514 * Don't hold the spinlock during an operation that
515 * can sleep.
516 */
517 spin_unlock_irqrestore(&statuslock, flags);
518 tempNumAllocated = allocateEvents(remoteLp, 1);
519 spin_lock_irqsave(&statuslock, flags);
520
521 viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
522
523 if (viopathStatus[remoteLp].numberAllocated == 0) {
524 HvCallEvent_closeLpEventPath(remoteLp,
525 HvLpEvent_Type_VirtualIo);
526
527 spin_unlock_irqrestore(&statuslock, flags);
528 return -ENOMEM;
529 }
530
531 viopathStatus[remoteLp].mSourceInst =
532 HvCallEvent_getSourceLpInstanceId(remoteLp,
533 HvLpEvent_Type_VirtualIo);
534 viopathStatus[remoteLp].mTargetInst =
535 HvCallEvent_getTargetLpInstanceId(remoteLp,
536 HvLpEvent_Type_VirtualIo);
537 HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo,
538 &vio_handleEvent);
539 sendMonMsg(remoteLp);
540 printk(VIOPATH_KERN_INFO "opening connection to partition %d, "
541 "setting sinst %d, tinst %d\n",
542 remoteLp, viopathStatus[remoteLp].mSourceInst,
543 viopathStatus[remoteLp].mTargetInst);
544 }
545
546 spin_unlock_irqrestore(&statuslock, flags);
547 tempNumAllocated = allocateEvents(remoteLp, numReq);
548 spin_lock_irqsave(&statuslock, flags);
549 viopathStatus[remoteLp].numberAllocated += tempNumAllocated;
550 spin_unlock_irqrestore(&statuslock, flags);
551
552 return 0;
553}
554EXPORT_SYMBOL(viopath_open);
555
556int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
557{
558 unsigned long flags;
559 int i;
560 int numOpen;
561 struct alloc_parms parms;
562
563 if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
564 return -EINVAL;
565
566 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
567 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
568 return -EINVAL;
569
570 spin_lock_irqsave(&statuslock, flags);
571 /*
572 * If the viopath_close somehow gets called before a
573 * viopath_open it could decrement to -1 which is a non
574 * recoverable state so we'll prevent this from
575 * happening.
576 */
577 if (viopathStatus[remoteLp].users[subtype] > 0)
578 viopathStatus[remoteLp].users[subtype]--;
579
580 spin_unlock_irqrestore(&statuslock, flags);
581
582 parms.used_wait_atomic = 0;
583 init_completion(&parms.done);
584 mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo,
585 numReq, &viopath_donealloc, &parms);
586 wait_for_completion(&parms.done);
587
588 spin_lock_irqsave(&statuslock, flags);
589 for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++)
590 numOpen += viopathStatus[remoteLp].users[i];
591
592 if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
593 printk(VIOPATH_KERN_INFO "closing connection to partition %d\n",
594 remoteLp);
595
596 HvCallEvent_closeLpEventPath(remoteLp,
597 HvLpEvent_Type_VirtualIo);
598 viopathStatus[remoteLp].isOpen = 0;
599 viopathStatus[remoteLp].isActive = 0;
600
601 for (i = 0; i < VIO_MAX_SUBTYPES; i++)
602 atomic_set(&event_buffer_available[i], 0);
603 event_buffer_initialised = 0;
604 }
605 spin_unlock_irqrestore(&statuslock, flags);
606 return 0;
607}
608EXPORT_SYMBOL(viopath_close);
609
610void *vio_get_event_buffer(int subtype)
611{
612 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
613 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES))
614 return NULL;
615
616 if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0)
617 return &event_buffer[subtype * 256];
618 else
619 return NULL;
620}
621EXPORT_SYMBOL(vio_get_event_buffer);
622
623void vio_free_event_buffer(int subtype, void *buffer)
624{
625 subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
626 if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) {
627 printk(VIOPATH_KERN_WARN
628 "unexpected subtype %d freeing event buffer\n", subtype);
629 return;
630 }
631
632 if (atomic_read(&event_buffer_available[subtype]) != 0) {
633 printk(VIOPATH_KERN_WARN
634 "freeing unallocated event buffer, subtype %d\n",
635 subtype);
636 return;
637 }
638
639 if (buffer != &event_buffer[subtype * 256]) {
640 printk(VIOPATH_KERN_WARN
641 "freeing invalid event buffer, subtype %d\n", subtype);
642 }
643
644 atomic_set(&event_buffer_available[subtype], 1);
645}
646EXPORT_SYMBOL(vio_free_event_buffer);
647
648static const struct vio_error_entry vio_no_error =
649 { 0, 0, "Non-VIO Error" };
650static const struct vio_error_entry vio_unknown_error =
651 { 0, EIO, "Unknown Error" };
652
653static const struct vio_error_entry vio_default_errors[] = {
654 {0x0001, EIO, "No Connection"},
655 {0x0002, EIO, "No Receiver"},
656 {0x0003, EIO, "No Buffer Available"},
657 {0x0004, EBADRQC, "Invalid Message Type"},
658 {0x0000, 0, NULL},
659};
660
661const struct vio_error_entry *vio_lookup_rc(
662 const struct vio_error_entry *local_table, u16 rc)
663{
664 const struct vio_error_entry *cur;
665
666 if (!rc)
667 return &vio_no_error;
668 if (local_table)
669 for (cur = local_table; cur->rc; ++cur)
670 if (cur->rc == rc)
671 return cur;
672 for (cur = vio_default_errors; cur->rc; ++cur)
673 if (cur->rc == rc)
674 return cur;
675 return &vio_unknown_error;
676}
677EXPORT_SYMBOL(vio_lookup_rc);
diff --git a/arch/powerpc/platforms/iseries/vpd_areas.h b/arch/powerpc/platforms/iseries/vpd_areas.h
deleted file mode 100644
index feb001f3a5fe..000000000000
--- a/arch/powerpc/platforms/iseries/vpd_areas.h
+++ /dev/null
@@ -1,88 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISERIES_VPD_AREAS_H
19#define _ISERIES_VPD_AREAS_H
20
21/*
22 * This file defines the address and length of all of the VPD area passed to
23 * the OS from PLIC (most of which start from the SP).
24 */
25
26#include <asm/types.h>
27
28/* VPD Entry index is carved in stone - cannot be changed (easily). */
29#define ItVpdCecVpd 0
30#define ItVpdDynamicSpace 1
31#define ItVpdExtVpd 2
32#define ItVpdExtVpdOnPanel 3
33#define ItVpdFirstPaca 4
34#define ItVpdIoVpd 5
35#define ItVpdIplParms 6
36#define ItVpdMsVpd 7
37#define ItVpdPanelVpd 8
38#define ItVpdLpNaca 9
39#define ItVpdBackplaneAndMaybeClockCardVpd 10
40#define ItVpdRecoveryLogBuffer 11
41#define ItVpdSpCommArea 12
42#define ItVpdSpLogBuffer 13
43#define ItVpdSpLogBufferSave 14
44#define ItVpdSpCardVpd 15
45#define ItVpdFirstProcVpd 16
46#define ItVpdApModelVpd 17
47#define ItVpdClockCardVpd 18
48#define ItVpdBusExtCardVpd 19
49#define ItVpdProcCapacityVpd 20
50#define ItVpdInteractiveCapacityVpd 21
51#define ItVpdFirstSlotLabel 22
52#define ItVpdFirstLpQueue 23
53#define ItVpdFirstL3CacheVpd 24
54#define ItVpdFirstProcFruVpd 25
55
56#define ItVpdMaxEntries 26
57
58#define ItDmaMaxEntries 10
59
60#define ItVpdAreasMaxSlotLabels 192
61
62
63struct ItVpdAreas {
64 u32 xSlicDesc; // Descriptor 000-003
65 u16 xSlicSize; // Size of this control block 004-005
66 u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007
67 u16 xRsvd1:15; // Reserved bits ...
68 u16 xSlicVpdEntries; // Number of VPD entries 008-009
69 u16 xSlicDmaEntries; // Number of DMA entries 00A-00B
70 u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D
71 u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F
72 u16 xSlicDmaToksOffset; // Offset into this of array 010-011
73 u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013
74 u16 xSlicDmaLensOffset; // Offset into this of array 014-015
75 u16 xSlicVpdLensOffset; // Offset into this of array 016-017
76 u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019
77 u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B
78 u8 xRsvd2[4]; // Reserved 01C-01F
79 u64 xRsvd3[12]; // Reserved 020-07F
80 u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
81 u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
82 u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
83 const void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
84};
85
86extern const struct ItVpdAreas itVpdAreas;
87
88#endif /* _ISERIES_VPD_AREAS_H */
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 0bcbfe7b2c55..3b7545a51aa9 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -262,7 +262,7 @@ static void __init maple_init_IRQ(void)
262 flags |= MPIC_BIG_ENDIAN; 262 flags |= MPIC_BIG_ENDIAN;
263 263
264 /* XXX Maple specific bits */ 264 /* XXX Maple specific bits */
265 flags |= MPIC_U3_HT_IRQS | MPIC_WANTS_RESET; 265 flags |= MPIC_U3_HT_IRQS;
266 /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */ 266 /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
267 flags |= MPIC_BIG_ENDIAN; 267 flags |= MPIC_BIG_ENDIAN;
268 268
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 98b7a7c13176..e777ad471a48 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -224,7 +224,7 @@ static __init void pas_init_IRQ(void)
224 openpic_addr = of_read_number(opprop, naddr); 224 openpic_addr = of_read_number(opprop, naddr);
225 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); 225 printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
226 226
227 mpic_flags = MPIC_LARGE_VECTORS | MPIC_NO_BIAS; 227 mpic_flags = MPIC_LARGE_VECTORS | MPIC_NO_BIAS | MPIC_NO_RESET;
228 228
229 nmiprop = of_get_property(mpic_node, "nmi-source", NULL); 229 nmiprop = of_get_property(mpic_node, "nmi-source", NULL);
230 if (nmiprop) 230 if (nmiprop)
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 54d227127c9f..da18b26dcc6f 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -279,7 +279,7 @@ static u32 core99_check(u8* datas)
279 279
280static int sm_erase_bank(int bank) 280static int sm_erase_bank(int bank)
281{ 281{
282 int stat, i; 282 int stat;
283 unsigned long timeout; 283 unsigned long timeout;
284 284
285 u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 285 u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
@@ -301,11 +301,10 @@ static int sm_erase_bank(int bank)
301 out_8(base, SM_FLASH_CMD_CLEAR_STATUS); 301 out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
302 out_8(base, SM_FLASH_CMD_RESET); 302 out_8(base, SM_FLASH_CMD_RESET);
303 303
304 for (i=0; i<NVRAM_SIZE; i++) 304 if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
305 if (base[i] != 0xff) { 305 printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
306 printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n"); 306 return -ENXIO;
307 return -ENXIO; 307 }
308 }
309 return 0; 308 return 0;
310} 309}
311 310
@@ -336,17 +335,16 @@ static int sm_write_bank(int bank, u8* datas)
336 } 335 }
337 out_8(base, SM_FLASH_CMD_CLEAR_STATUS); 336 out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
338 out_8(base, SM_FLASH_CMD_RESET); 337 out_8(base, SM_FLASH_CMD_RESET);
339 for (i=0; i<NVRAM_SIZE; i++) 338 if (memcmp(base, datas, NVRAM_SIZE)) {
340 if (base[i] != datas[i]) { 339 printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
341 printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n"); 340 return -ENXIO;
342 return -ENXIO; 341 }
343 }
344 return 0; 342 return 0;
345} 343}
346 344
347static int amd_erase_bank(int bank) 345static int amd_erase_bank(int bank)
348{ 346{
349 int i, stat = 0; 347 int stat = 0;
350 unsigned long timeout; 348 unsigned long timeout;
351 349
352 u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 350 u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
@@ -382,12 +380,11 @@ static int amd_erase_bank(int bank)
382 /* Reset */ 380 /* Reset */
383 out_8(base, 0xf0); 381 out_8(base, 0xf0);
384 udelay(1); 382 udelay(1);
385 383
386 for (i=0; i<NVRAM_SIZE; i++) 384 if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
387 if (base[i] != 0xff) { 385 printk(KERN_ERR "nvram: AMD flash erase failed !\n");
388 printk(KERN_ERR "nvram: AMD flash erase failed !\n"); 386 return -ENXIO;
389 return -ENXIO; 387 }
390 }
391 return 0; 388 return 0;
392} 389}
393 390
@@ -429,11 +426,10 @@ static int amd_write_bank(int bank, u8* datas)
429 out_8(base, 0xf0); 426 out_8(base, 0xf0);
430 udelay(1); 427 udelay(1);
431 428
432 for (i=0; i<NVRAM_SIZE; i++) 429 if (memcmp(base, datas, NVRAM_SIZE)) {
433 if (base[i] != datas[i]) { 430 printk(KERN_ERR "nvram: AMD flash write failed !\n");
434 printk(KERN_ERR "nvram: AMD flash write failed !\n"); 431 return -ENXIO;
435 return -ENXIO; 432 }
436 }
437 return 0; 433 return 0;
438} 434}
439 435
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 92afc382a49e..66ad93de1d55 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -457,7 +457,6 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
457 457
458 pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); 458 pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
459 459
460 flags |= MPIC_WANTS_RESET;
461 if (of_get_property(np, "big-endian", NULL)) 460 if (of_get_property(np, "big-endian", NULL))
462 flags |= MPIC_BIG_ENDIAN; 461 flags |= MPIC_BIG_ENDIAN;
463 462
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index f92b9ef7340e..214478d781ae 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -31,6 +31,7 @@
31#include <asm/iommu.h> 31#include <asm/iommu.h>
32#include <asm/tce.h> 32#include <asm/tce.h>
33#include <asm/abs_addr.h> 33#include <asm/abs_addr.h>
34#include <asm/firmware.h>
34 35
35#include "powernv.h" 36#include "powernv.h"
36#include "pci.h" 37#include "pci.h"
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 467bd4ac6824..db1ad1c8f68f 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -31,7 +31,6 @@
31#include <asm/xics.h> 31#include <asm/xics.h>
32#include <asm/rtas.h> 32#include <asm/rtas.h>
33#include <asm/opal.h> 33#include <asm/opal.h>
34#include <asm/xics.h>
35 34
36#include "powernv.h" 35#include "powernv.h"
37 36
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index f2556257bbdc..aadbe4f6d537 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -73,7 +73,7 @@ config IO_EVENT_IRQ
73 73
74config LPARCFG 74config LPARCFG
75 bool "LPAR Configuration Data" 75 bool "LPAR Configuration Data"
76 depends on PPC_PSERIES || PPC_ISERIES 76 depends on PPC_PSERIES
77 help 77 help
78 Provide system capacity information via human readable 78 Provide system capacity information via human readable
79 <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. 79 <key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 236db46b4078..c222189f5bb2 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -6,7 +6,8 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
6 firmware.o power.o dlpar.o mobility.o 6 firmware.o power.o dlpar.o mobility.o
7obj-$(CONFIG_SMP) += smp.o 7obj-$(CONFIG_SMP) += smp.o
8obj-$(CONFIG_SCANLOG) += scanlog.o 8obj-$(CONFIG_SCANLOG) += scanlog.o
9obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o 9obj-$(CONFIG_EEH) += eeh.o eeh_dev.o eeh_cache.o eeh_driver.o \
10 eeh_event.o eeh_sysfs.o eeh_pseries.o
10obj-$(CONFIG_KEXEC) += kexec.o 11obj-$(CONFIG_KEXEC) += kexec.o
11obj-$(CONFIG_PCI) += pci.o pci_dlpar.o 12obj-$(CONFIG_PCI) += pci.o pci_dlpar.o
12obj-$(CONFIG_PSERIES_MSI) += msi.o 13obj-$(CONFIG_PSERIES_MSI) += msi.o
@@ -18,7 +19,6 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o
18obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o 19obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
19obj-$(CONFIG_HVCS) += hvcserver.o 20obj-$(CONFIG_HVCS) += hvcserver.o
20obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o 21obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
21obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
22obj-$(CONFIG_CMM) += cmm.o 22obj-$(CONFIG_CMM) += cmm.o
23obj-$(CONFIG_DTL) += dtl.o 23obj-$(CONFIG_DTL) += dtl.o
24obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o 24obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index c0b40af4ce4f..8011088392d3 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * eeh.c
3 * Copyright IBM Corporation 2001, 2005, 2006 2 * Copyright IBM Corporation 2001, 2005, 2006
4 * Copyright Dave Engebretsen & Todd Inglett 2001 3 * Copyright Dave Engebretsen & Todd Inglett 2001
5 * Copyright Linas Vepstas 2005, 2006 4 * Copyright Linas Vepstas 2005, 2006
5 * Copyright 2001-2012 IBM Corporation.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
22 */ 22 */
23 23
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/sched.h> /* for init_mm */ 25#include <linux/sched.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/list.h> 27#include <linux/list.h>
28#include <linux/pci.h> 28#include <linux/pci.h>
@@ -86,16 +86,8 @@
86/* Time to wait for a PCI slot to report status, in milliseconds */ 86/* Time to wait for a PCI slot to report status, in milliseconds */
87#define PCI_BUS_RESET_WAIT_MSEC (60*1000) 87#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
88 88
89/* RTAS tokens */ 89/* Platform dependent EEH operations */
90static int ibm_set_eeh_option; 90struct eeh_ops *eeh_ops = NULL;
91static int ibm_set_slot_reset;
92static int ibm_read_slot_reset_state;
93static int ibm_read_slot_reset_state2;
94static int ibm_slot_error_detail;
95static int ibm_get_config_addr_info;
96static int ibm_get_config_addr_info2;
97static int ibm_configure_bridge;
98static int ibm_configure_pe;
99 91
100int eeh_subsystem_enabled; 92int eeh_subsystem_enabled;
101EXPORT_SYMBOL(eeh_subsystem_enabled); 93EXPORT_SYMBOL(eeh_subsystem_enabled);
@@ -103,14 +95,6 @@ EXPORT_SYMBOL(eeh_subsystem_enabled);
103/* Lock to avoid races due to multiple reports of an error */ 95/* Lock to avoid races due to multiple reports of an error */
104static DEFINE_RAW_SPINLOCK(confirm_error_lock); 96static DEFINE_RAW_SPINLOCK(confirm_error_lock);
105 97
106/* Buffer for reporting slot-error-detail rtas calls. Its here
107 * in BSS, and not dynamically alloced, so that it ends up in
108 * RMO where RTAS can access it.
109 */
110static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
111static DEFINE_SPINLOCK(slot_errbuf_lock);
112static int eeh_error_buf_size;
113
114/* Buffer for reporting pci register dumps. Its here in BSS, and 98/* Buffer for reporting pci register dumps. Its here in BSS, and
115 * not dynamically alloced, so that it ends up in RMO where RTAS 99 * not dynamically alloced, so that it ends up in RMO where RTAS
116 * can access it. 100 * can access it.
@@ -118,74 +102,50 @@ static int eeh_error_buf_size;
118#define EEH_PCI_REGS_LOG_LEN 4096 102#define EEH_PCI_REGS_LOG_LEN 4096
119static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN]; 103static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
120 104
121/* System monitoring statistics */ 105/*
122static unsigned long no_device; 106 * The struct is used to maintain the EEH global statistic
123static unsigned long no_dn; 107 * information. Besides, the EEH global statistics will be
124static unsigned long no_cfg_addr; 108 * exported to user space through procfs
125static unsigned long ignored_check; 109 */
126static unsigned long total_mmio_ffs; 110struct eeh_stats {
127static unsigned long false_positives; 111 u64 no_device; /* PCI device not found */
128static unsigned long slot_resets; 112 u64 no_dn; /* OF node not found */
129 113 u64 no_cfg_addr; /* Config address not found */
130#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) 114 u64 ignored_check; /* EEH check skipped */
131 115 u64 total_mmio_ffs; /* Total EEH checks */
132/* --------------------------------------------------------------- */ 116 u64 false_positives; /* Unnecessary EEH checks */
133/* Below lies the EEH event infrastructure */ 117 u64 slot_resets; /* PE reset */
118};
134 119
135static void rtas_slot_error_detail(struct pci_dn *pdn, int severity, 120static struct eeh_stats eeh_stats;
136 char *driver_log, size_t loglen)
137{
138 int config_addr;
139 unsigned long flags;
140 int rc;
141 121
142 /* Log the error with the rtas logger */ 122#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
143 spin_lock_irqsave(&slot_errbuf_lock, flags);
144 memset(slot_errbuf, 0, eeh_error_buf_size);
145
146 /* Use PE configuration address, if present */
147 config_addr = pdn->eeh_config_addr;
148 if (pdn->eeh_pe_config_addr)
149 config_addr = pdn->eeh_pe_config_addr;
150
151 rc = rtas_call(ibm_slot_error_detail,
152 8, 1, NULL, config_addr,
153 BUID_HI(pdn->phb->buid),
154 BUID_LO(pdn->phb->buid),
155 virt_to_phys(driver_log), loglen,
156 virt_to_phys(slot_errbuf),
157 eeh_error_buf_size,
158 severity);
159
160 if (rc == 0)
161 log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
162 spin_unlock_irqrestore(&slot_errbuf_lock, flags);
163}
164 123
165/** 124/**
166 * gather_pci_data - copy assorted PCI config space registers to buff 125 * eeh_gather_pci_data - Copy assorted PCI config space registers to buff
167 * @pdn: device to report data for 126 * @edev: device to report data for
168 * @buf: point to buffer in which to log 127 * @buf: point to buffer in which to log
169 * @len: amount of room in buffer 128 * @len: amount of room in buffer
170 * 129 *
171 * This routine captures assorted PCI configuration space data, 130 * This routine captures assorted PCI configuration space data,
172 * and puts them into a buffer for RTAS error logging. 131 * and puts them into a buffer for RTAS error logging.
173 */ 132 */
174static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) 133static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
175{ 134{
176 struct pci_dev *dev = pdn->pcidev; 135 struct device_node *dn = eeh_dev_to_of_node(edev);
136 struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
177 u32 cfg; 137 u32 cfg;
178 int cap, i; 138 int cap, i;
179 int n = 0; 139 int n = 0;
180 140
181 n += scnprintf(buf+n, len-n, "%s\n", pdn->node->full_name); 141 n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
182 printk(KERN_WARNING "EEH: of node=%s\n", pdn->node->full_name); 142 printk(KERN_WARNING "EEH: of node=%s\n", dn->full_name);
183 143
184 rtas_read_config(pdn, PCI_VENDOR_ID, 4, &cfg); 144 eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg);
185 n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg); 145 n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
186 printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg); 146 printk(KERN_WARNING "EEH: PCI device/vendor: %08x\n", cfg);
187 147
188 rtas_read_config(pdn, PCI_COMMAND, 4, &cfg); 148 eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg);
189 n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); 149 n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
190 printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); 150 printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg);
191 151
@@ -196,11 +156,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
196 156
197 /* Gather bridge-specific registers */ 157 /* Gather bridge-specific registers */
198 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { 158 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
199 rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg); 159 eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);
200 n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg); 160 n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
201 printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg); 161 printk(KERN_WARNING "EEH: Bridge secondary status: %04x\n", cfg);
202 162
203 rtas_read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg); 163 eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg);
204 n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg); 164 n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
205 printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg); 165 printk(KERN_WARNING "EEH: Bridge control: %04x\n", cfg);
206 } 166 }
@@ -208,11 +168,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
208 /* Dump out the PCI-X command and status regs */ 168 /* Dump out the PCI-X command and status regs */
209 cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 169 cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
210 if (cap) { 170 if (cap) {
211 rtas_read_config(pdn, cap, 4, &cfg); 171 eeh_ops->read_config(dn, cap, 4, &cfg);
212 n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); 172 n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
213 printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg); 173 printk(KERN_WARNING "EEH: PCI-X cmd: %08x\n", cfg);
214 174
215 rtas_read_config(pdn, cap+4, 4, &cfg); 175 eeh_ops->read_config(dn, cap+4, 4, &cfg);
216 n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg); 176 n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
217 printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg); 177 printk(KERN_WARNING "EEH: PCI-X status: %08x\n", cfg);
218 } 178 }
@@ -225,7 +185,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
225 "EEH: PCI-E capabilities and status follow:\n"); 185 "EEH: PCI-E capabilities and status follow:\n");
226 186
227 for (i=0; i<=8; i++) { 187 for (i=0; i<=8; i++) {
228 rtas_read_config(pdn, cap+4*i, 4, &cfg); 188 eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
229 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); 189 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
230 printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); 190 printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg);
231 } 191 }
@@ -237,7 +197,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
237 "EEH: PCI-E AER capability register set follows:\n"); 197 "EEH: PCI-E AER capability register set follows:\n");
238 198
239 for (i=0; i<14; i++) { 199 for (i=0; i<14; i++) {
240 rtas_read_config(pdn, cap+4*i, 4, &cfg); 200 eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
241 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); 201 n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
242 printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg); 202 printk(KERN_WARNING "EEH: PCI-E AER %02x: %08x\n", i, cfg);
243 } 203 }
@@ -246,111 +206,46 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
246 206
247 /* Gather status on devices under the bridge */ 207 /* Gather status on devices under the bridge */
248 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { 208 if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
249 struct device_node *dn; 209 struct device_node *child;
250 210
251 for_each_child_of_node(pdn->node, dn) { 211 for_each_child_of_node(dn, child) {
252 pdn = PCI_DN(dn); 212 if (of_node_to_eeh_dev(child))
253 if (pdn) 213 n += eeh_gather_pci_data(of_node_to_eeh_dev(child), buf+n, len-n);
254 n += gather_pci_data(pdn, buf+n, len-n);
255 } 214 }
256 } 215 }
257 216
258 return n; 217 return n;
259} 218}
260 219
261void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
262{
263 size_t loglen = 0;
264 pci_regs_buf[0] = 0;
265
266 rtas_pci_enable(pdn, EEH_THAW_MMIO);
267 rtas_configure_bridge(pdn);
268 eeh_restore_bars(pdn);
269 loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
270
271 rtas_slot_error_detail(pdn, severity, pci_regs_buf, loglen);
272}
273
274/** 220/**
275 * read_slot_reset_state - Read the reset state of a device node's slot 221 * eeh_slot_error_detail - Generate combined log including driver log and error log
276 * @dn: device node to read 222 * @edev: device to report error log for
277 * @rets: array to return results in 223 * @severity: temporary or permanent error log
278 */
279static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
280{
281 int token, outputs;
282 int config_addr;
283
284 if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
285 token = ibm_read_slot_reset_state2;
286 outputs = 4;
287 } else {
288 token = ibm_read_slot_reset_state;
289 rets[2] = 0; /* fake PE Unavailable info */
290 outputs = 3;
291 }
292
293 /* Use PE configuration address, if present */
294 config_addr = pdn->eeh_config_addr;
295 if (pdn->eeh_pe_config_addr)
296 config_addr = pdn->eeh_pe_config_addr;
297
298 return rtas_call(token, 3, outputs, rets, config_addr,
299 BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
300}
301
302/**
303 * eeh_wait_for_slot_status - returns error status of slot
304 * @pdn pci device node
305 * @max_wait_msecs maximum number to millisecs to wait
306 *
307 * Return negative value if a permanent error, else return
308 * Partition Endpoint (PE) status value.
309 * 224 *
310 * If @max_wait_msecs is positive, then this routine will 225 * This routine should be called to generate the combined log, which
311 * sleep until a valid status can be obtained, or until 226 * is comprised of driver log and error log. The driver log is figured
312 * the max allowed wait time is exceeded, in which case 227 * out from the config space of the corresponding PCI device, while
313 * a -2 is returned. 228 * the error log is fetched through platform dependent function call.
314 */ 229 */
315int 230void eeh_slot_error_detail(struct eeh_dev *edev, int severity)
316eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
317{ 231{
318 int rc; 232 size_t loglen = 0;
319 int rets[3]; 233 pci_regs_buf[0] = 0;
320 int mwait;
321
322 while (1) {
323 rc = read_slot_reset_state(pdn, rets);
324 if (rc) return rc;
325 if (rets[1] == 0) return -1; /* EEH is not supported */
326
327 if (rets[0] != 5) return rets[0]; /* return actual status */
328
329 if (rets[2] == 0) return -1; /* permanently unavailable */
330 234
331 if (max_wait_msecs <= 0) break; 235 eeh_pci_enable(edev, EEH_OPT_THAW_MMIO);
236 eeh_ops->configure_bridge(eeh_dev_to_of_node(edev));
237 eeh_restore_bars(edev);
238 loglen = eeh_gather_pci_data(edev, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
332 239
333 mwait = rets[2]; 240 eeh_ops->get_log(eeh_dev_to_of_node(edev), severity, pci_regs_buf, loglen);
334 if (mwait <= 0) {
335 printk (KERN_WARNING
336 "EEH: Firmware returned bad wait value=%d\n", mwait);
337 mwait = 1000;
338 } else if (mwait > 300*1000) {
339 printk (KERN_WARNING
340 "EEH: Firmware is taking too long, time=%d\n", mwait);
341 mwait = 300*1000;
342 }
343 max_wait_msecs -= mwait;
344 msleep (mwait);
345 }
346
347 printk(KERN_WARNING "EEH: Timed out waiting for slot status\n");
348 return -2;
349} 241}
350 242
351/** 243/**
352 * eeh_token_to_phys - convert EEH address token to phys address 244 * eeh_token_to_phys - Convert EEH address token to phys address
353 * @token i/o token, should be address in the form 0xA.... 245 * @token: I/O token, should be address in the form 0xA....
246 *
247 * This routine should be called to convert virtual I/O address
248 * to physical one.
354 */ 249 */
355static inline unsigned long eeh_token_to_phys(unsigned long token) 250static inline unsigned long eeh_token_to_phys(unsigned long token)
356{ 251{
@@ -365,36 +260,43 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
365 return pa | (token & (PAGE_SIZE-1)); 260 return pa | (token & (PAGE_SIZE-1));
366} 261}
367 262
368/** 263/**
369 * Return the "partitionable endpoint" (pe) under which this device lies 264 * eeh_find_device_pe - Retrieve the PE for the given device
265 * @dn: device node
266 *
267 * Return the PE under which this device lies
370 */ 268 */
371struct device_node * find_device_pe(struct device_node *dn) 269struct device_node *eeh_find_device_pe(struct device_node *dn)
372{ 270{
373 while ((dn->parent) && PCI_DN(dn->parent) && 271 while (dn->parent && of_node_to_eeh_dev(dn->parent) &&
374 (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { 272 (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
375 dn = dn->parent; 273 dn = dn->parent;
376 } 274 }
377 return dn; 275 return dn;
378} 276}
379 277
380/** Mark all devices that are children of this device as failed. 278/**
381 * Mark the device driver too, so that it can see the failure 279 * __eeh_mark_slot - Mark all child devices as failed
382 * immediately; this is critical, since some drivers poll 280 * @parent: parent device
383 * status registers in interrupts ... If a driver is polling, 281 * @mode_flag: failure flag
384 * and the slot is frozen, then the driver can deadlock in 282 *
385 * an interrupt context, which is bad. 283 * Mark all devices that are children of this device as failed.
284 * Mark the device driver too, so that it can see the failure
285 * immediately; this is critical, since some drivers poll
286 * status registers in interrupts ... If a driver is polling,
287 * and the slot is frozen, then the driver can deadlock in
288 * an interrupt context, which is bad.
386 */ 289 */
387
388static void __eeh_mark_slot(struct device_node *parent, int mode_flag) 290static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
389{ 291{
390 struct device_node *dn; 292 struct device_node *dn;
391 293
392 for_each_child_of_node(parent, dn) { 294 for_each_child_of_node(parent, dn) {
393 if (PCI_DN(dn)) { 295 if (of_node_to_eeh_dev(dn)) {
394 /* Mark the pci device driver too */ 296 /* Mark the pci device driver too */
395 struct pci_dev *dev = PCI_DN(dn)->pcidev; 297 struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
396 298
397 PCI_DN(dn)->eeh_mode |= mode_flag; 299 of_node_to_eeh_dev(dn)->mode |= mode_flag;
398 300
399 if (dev && dev->driver) 301 if (dev && dev->driver)
400 dev->error_state = pci_channel_io_frozen; 302 dev->error_state = pci_channel_io_frozen;
@@ -404,92 +306,81 @@ static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
404 } 306 }
405} 307}
406 308
407void eeh_mark_slot (struct device_node *dn, int mode_flag) 309/**
310 * eeh_mark_slot - Mark the indicated device and its children as failed
311 * @dn: parent device
312 * @mode_flag: failure flag
313 *
314 * Mark the indicated device and its child devices as failed.
315 * The device drivers are marked as failed as well.
316 */
317void eeh_mark_slot(struct device_node *dn, int mode_flag)
408{ 318{
409 struct pci_dev *dev; 319 struct pci_dev *dev;
410 dn = find_device_pe (dn); 320 dn = eeh_find_device_pe(dn);
411 321
412 /* Back up one, since config addrs might be shared */ 322 /* Back up one, since config addrs might be shared */
413 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) 323 if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
414 dn = dn->parent; 324 dn = dn->parent;
415 325
416 PCI_DN(dn)->eeh_mode |= mode_flag; 326 of_node_to_eeh_dev(dn)->mode |= mode_flag;
417 327
418 /* Mark the pci device too */ 328 /* Mark the pci device too */
419 dev = PCI_DN(dn)->pcidev; 329 dev = of_node_to_eeh_dev(dn)->pdev;
420 if (dev) 330 if (dev)
421 dev->error_state = pci_channel_io_frozen; 331 dev->error_state = pci_channel_io_frozen;
422 332
423 __eeh_mark_slot(dn, mode_flag); 333 __eeh_mark_slot(dn, mode_flag);
424} 334}
425 335
336/**
337 * __eeh_clear_slot - Clear failure flag for the child devices
338 * @parent: parent device
339 * @mode_flag: flag to be cleared
340 *
341 * Clear failure flag for the child devices.
342 */
426static void __eeh_clear_slot(struct device_node *parent, int mode_flag) 343static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
427{ 344{
428 struct device_node *dn; 345 struct device_node *dn;
429 346
430 for_each_child_of_node(parent, dn) { 347 for_each_child_of_node(parent, dn) {
431 if (PCI_DN(dn)) { 348 if (of_node_to_eeh_dev(dn)) {
432 PCI_DN(dn)->eeh_mode &= ~mode_flag; 349 of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
433 PCI_DN(dn)->eeh_check_count = 0; 350 of_node_to_eeh_dev(dn)->check_count = 0;
434 __eeh_clear_slot(dn, mode_flag); 351 __eeh_clear_slot(dn, mode_flag);
435 } 352 }
436 } 353 }
437} 354}
438 355
439void eeh_clear_slot (struct device_node *dn, int mode_flag) 356/**
357 * eeh_clear_slot - Clear failure flag for the indicated device and its children
358 * @dn: parent device
359 * @mode_flag: flag to be cleared
360 *
361 * Clear failure flag for the indicated device and its children.
362 */
363void eeh_clear_slot(struct device_node *dn, int mode_flag)
440{ 364{
441 unsigned long flags; 365 unsigned long flags;
442 raw_spin_lock_irqsave(&confirm_error_lock, flags); 366 raw_spin_lock_irqsave(&confirm_error_lock, flags);
443 367
444 dn = find_device_pe (dn); 368 dn = eeh_find_device_pe(dn);
445 369
446 /* Back up one, since config addrs might be shared */ 370 /* Back up one, since config addrs might be shared */
447 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) 371 if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
448 dn = dn->parent; 372 dn = dn->parent;
449 373
450 PCI_DN(dn)->eeh_mode &= ~mode_flag; 374 of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
451 PCI_DN(dn)->eeh_check_count = 0; 375 of_node_to_eeh_dev(dn)->check_count = 0;
452 __eeh_clear_slot(dn, mode_flag); 376 __eeh_clear_slot(dn, mode_flag);
453 raw_spin_unlock_irqrestore(&confirm_error_lock, flags); 377 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
454} 378}
455 379
456void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
457{
458 struct device_node *dn;
459
460 for_each_child_of_node(parent, dn) {
461 if (PCI_DN(dn)) {
462
463 struct pci_dev *dev = PCI_DN(dn)->pcidev;
464
465 if (dev && dev->driver)
466 *freset |= dev->needs_freset;
467
468 __eeh_set_pe_freset(dn, freset);
469 }
470 }
471}
472
473void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
474{
475 struct pci_dev *dev;
476 dn = find_device_pe(dn);
477
478 /* Back up one, since config addrs might be shared */
479 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
480 dn = dn->parent;
481
482 dev = PCI_DN(dn)->pcidev;
483 if (dev)
484 *freset |= dev->needs_freset;
485
486 __eeh_set_pe_freset(dn, freset);
487}
488
489/** 380/**
490 * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze 381 * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
491 * @dn device node 382 * @dn: device node
492 * @dev pci device, if known 383 * @dev: pci device, if known
493 * 384 *
494 * Check for an EEH failure for the given device node. Call this 385 * Check for an EEH failure for the given device node. Call this
495 * routine if the result of a read was all 0xff's and you want to 386 * routine if the result of a read was all 0xff's and you want to
@@ -504,35 +395,34 @@ void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
504int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) 395int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
505{ 396{
506 int ret; 397 int ret;
507 int rets[3];
508 unsigned long flags; 398 unsigned long flags;
509 struct pci_dn *pdn; 399 struct eeh_dev *edev;
510 int rc = 0; 400 int rc = 0;
511 const char *location; 401 const char *location;
512 402
513 total_mmio_ffs++; 403 eeh_stats.total_mmio_ffs++;
514 404
515 if (!eeh_subsystem_enabled) 405 if (!eeh_subsystem_enabled)
516 return 0; 406 return 0;
517 407
518 if (!dn) { 408 if (!dn) {
519 no_dn++; 409 eeh_stats.no_dn++;
520 return 0; 410 return 0;
521 } 411 }
522 dn = find_device_pe(dn); 412 dn = eeh_find_device_pe(dn);
523 pdn = PCI_DN(dn); 413 edev = of_node_to_eeh_dev(dn);
524 414
525 /* Access to IO BARs might get this far and still not want checking. */ 415 /* Access to IO BARs might get this far and still not want checking. */
526 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || 416 if (!(edev->mode & EEH_MODE_SUPPORTED) ||
527 pdn->eeh_mode & EEH_MODE_NOCHECK) { 417 edev->mode & EEH_MODE_NOCHECK) {
528 ignored_check++; 418 eeh_stats.ignored_check++;
529 pr_debug("EEH: Ignored check (%x) for %s %s\n", 419 pr_debug("EEH: Ignored check (%x) for %s %s\n",
530 pdn->eeh_mode, eeh_pci_name(dev), dn->full_name); 420 edev->mode, eeh_pci_name(dev), dn->full_name);
531 return 0; 421 return 0;
532 } 422 }
533 423
534 if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) { 424 if (!edev->config_addr && !edev->pe_config_addr) {
535 no_cfg_addr++; 425 eeh_stats.no_cfg_addr++;
536 return 0; 426 return 0;
537 } 427 }
538 428
@@ -544,15 +434,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
544 */ 434 */
545 raw_spin_lock_irqsave(&confirm_error_lock, flags); 435 raw_spin_lock_irqsave(&confirm_error_lock, flags);
546 rc = 1; 436 rc = 1;
547 if (pdn->eeh_mode & EEH_MODE_ISOLATED) { 437 if (edev->mode & EEH_MODE_ISOLATED) {
548 pdn->eeh_check_count ++; 438 edev->check_count++;
549 if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) { 439 if (edev->check_count % EEH_MAX_FAILS == 0) {
550 location = of_get_property(dn, "ibm,loc-code", NULL); 440 location = of_get_property(dn, "ibm,loc-code", NULL);
551 printk (KERN_ERR "EEH: %d reads ignored for recovering device at " 441 printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
552 "location=%s driver=%s pci addr=%s\n", 442 "location=%s driver=%s pci addr=%s\n",
553 pdn->eeh_check_count, location, 443 edev->check_count, location,
554 eeh_driver_name(dev), eeh_pci_name(dev)); 444 eeh_driver_name(dev), eeh_pci_name(dev));
555 printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n", 445 printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
556 eeh_driver_name(dev)); 446 eeh_driver_name(dev));
557 dump_stack(); 447 dump_stack();
558 } 448 }
@@ -566,58 +456,39 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
566 * function zero of a multi-function device. 456 * function zero of a multi-function device.
567 * In any case they must share a common PHB. 457 * In any case they must share a common PHB.
568 */ 458 */
569 ret = read_slot_reset_state(pdn, rets); 459 ret = eeh_ops->get_state(dn, NULL);
570
571 /* If the call to firmware failed, punt */
572 if (ret != 0) {
573 printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
574 ret, dn->full_name);
575 false_positives++;
576 pdn->eeh_false_positives ++;
577 rc = 0;
578 goto dn_unlock;
579 }
580 460
581 /* Note that config-io to empty slots may fail; 461 /* Note that config-io to empty slots may fail;
582 * they are empty when they don't have children. */ 462 * they are empty when they don't have children.
583 if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) { 463 * We will punt with the following conditions: Failure to get
584 false_positives++; 464 * PE's state, EEH not support and Permanently unavailable
585 pdn->eeh_false_positives ++; 465 * state, PE is in good state.
586 rc = 0; 466 */
587 goto dn_unlock; 467 if ((ret < 0) ||
588 } 468 (ret == EEH_STATE_NOT_SUPPORT) ||
589 469 (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
590 /* If EEH is not supported on this device, punt. */ 470 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
591 if (rets[1] != 1) { 471 eeh_stats.false_positives++;
592 printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", 472 edev->false_positives ++;
593 ret, dn->full_name);
594 false_positives++;
595 pdn->eeh_false_positives ++;
596 rc = 0;
597 goto dn_unlock;
598 }
599
600 /* If not the kind of error we know about, punt. */
601 if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
602 false_positives++;
603 pdn->eeh_false_positives ++;
604 rc = 0; 473 rc = 0;
605 goto dn_unlock; 474 goto dn_unlock;
606 } 475 }
607 476
608 slot_resets++; 477 eeh_stats.slot_resets++;
609 478
610 /* Avoid repeated reports of this failure, including problems 479 /* Avoid repeated reports of this failure, including problems
611 * with other functions on this device, and functions under 480 * with other functions on this device, and functions under
612 * bridges. */ 481 * bridges.
613 eeh_mark_slot (dn, EEH_MODE_ISOLATED); 482 */
483 eeh_mark_slot(dn, EEH_MODE_ISOLATED);
614 raw_spin_unlock_irqrestore(&confirm_error_lock, flags); 484 raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
615 485
616 eeh_send_failure_event (dn, dev); 486 eeh_send_failure_event(edev);
617 487
618 /* Most EEH events are due to device driver bugs. Having 488 /* Most EEH events are due to device driver bugs. Having
619 * a stack trace will help the device-driver authors figure 489 * a stack trace will help the device-driver authors figure
620 * out what happened. So print that out. */ 490 * out what happened. So print that out.
491 */
621 dump_stack(); 492 dump_stack();
622 return 1; 493 return 1;
623 494
@@ -629,9 +500,9 @@ dn_unlock:
629EXPORT_SYMBOL_GPL(eeh_dn_check_failure); 500EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
630 501
631/** 502/**
632 * eeh_check_failure - check if all 1's data is due to EEH slot freeze 503 * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
633 * @token i/o token, should be address in the form 0xA.... 504 * @token: I/O token, should be address in the form 0xA....
634 * @val value, should be all 1's (XXX why do we need this arg??) 505 * @val: value, should be all 1's (XXX why do we need this arg??)
635 * 506 *
636 * Check for an EEH failure at the given token address. Call this 507 * Check for an EEH failure at the given token address. Call this
637 * routine if the result of a read was all 0xff's and you want to 508 * routine if the result of a read was all 0xff's and you want to
@@ -648,14 +519,14 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon
648 519
649 /* Finding the phys addr + pci device; this is pretty quick. */ 520 /* Finding the phys addr + pci device; this is pretty quick. */
650 addr = eeh_token_to_phys((unsigned long __force) token); 521 addr = eeh_token_to_phys((unsigned long __force) token);
651 dev = pci_get_device_by_addr(addr); 522 dev = pci_addr_cache_get_device(addr);
652 if (!dev) { 523 if (!dev) {
653 no_device++; 524 eeh_stats.no_device++;
654 return val; 525 return val;
655 } 526 }
656 527
657 dn = pci_device_to_OF_node(dev); 528 dn = pci_device_to_OF_node(dev);
658 eeh_dn_check_failure (dn, dev); 529 eeh_dn_check_failure(dn, dev);
659 530
660 pci_dev_put(dev); 531 pci_dev_put(dev);
661 return val; 532 return val;
@@ -663,115 +534,54 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon
663 534
664EXPORT_SYMBOL(eeh_check_failure); 535EXPORT_SYMBOL(eeh_check_failure);
665 536
666/* ------------------------------------------------------------- */
667/* The code below deals with error recovery */
668 537
669/** 538/**
670 * rtas_pci_enable - enable MMIO or DMA transfers for this slot 539 * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
671 * @pdn pci device node 540 * @edev: pci device node
541 *
542 * This routine should be called to reenable frozen MMIO or DMA
543 * so that it would work correctly again. It's useful while doing
544 * recovery or log collection on the indicated device.
672 */ 545 */
673 546int eeh_pci_enable(struct eeh_dev *edev, int function)
674int
675rtas_pci_enable(struct pci_dn *pdn, int function)
676{ 547{
677 int config_addr;
678 int rc; 548 int rc;
549 struct device_node *dn = eeh_dev_to_of_node(edev);
679 550
680 /* Use PE configuration address, if present */ 551 rc = eeh_ops->set_option(dn, function);
681 config_addr = pdn->eeh_config_addr;
682 if (pdn->eeh_pe_config_addr)
683 config_addr = pdn->eeh_pe_config_addr;
684
685 rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
686 config_addr,
687 BUID_HI(pdn->phb->buid),
688 BUID_LO(pdn->phb->buid),
689 function);
690
691 if (rc) 552 if (rc)
692 printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n", 553 printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",
693 function, rc, pdn->node->full_name); 554 function, rc, dn->full_name);
694 555
695 rc = eeh_wait_for_slot_status (pdn, PCI_BUS_RESET_WAIT_MSEC); 556 rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
696 if ((rc == 4) && (function == EEH_THAW_MMIO)) 557 if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
558 (function == EEH_OPT_THAW_MMIO))
697 return 0; 559 return 0;
698 560
699 return rc; 561 return rc;
700} 562}
701 563
702/** 564/**
703 * rtas_pci_slot_reset - raises/lowers the pci #RST line
704 * @pdn pci device node
705 * @state: 1/0 to raise/lower the #RST
706 *
707 * Clear the EEH-frozen condition on a slot. This routine
708 * asserts the PCI #RST line if the 'state' argument is '1',
709 * and drops the #RST line if 'state is '0'. This routine is
710 * safe to call in an interrupt context.
711 *
712 */
713
714static void
715rtas_pci_slot_reset(struct pci_dn *pdn, int state)
716{
717 int config_addr;
718 int rc;
719
720 BUG_ON (pdn==NULL);
721
722 if (!pdn->phb) {
723 printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n",
724 pdn->node->full_name);
725 return;
726 }
727
728 /* Use PE configuration address, if present */
729 config_addr = pdn->eeh_config_addr;
730 if (pdn->eeh_pe_config_addr)
731 config_addr = pdn->eeh_pe_config_addr;
732
733 rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
734 config_addr,
735 BUID_HI(pdn->phb->buid),
736 BUID_LO(pdn->phb->buid),
737 state);
738
739 /* Fundamental-reset not supported on this PE, try hot-reset */
740 if (rc == -8 && state == 3) {
741 rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
742 config_addr,
743 BUID_HI(pdn->phb->buid),
744 BUID_LO(pdn->phb->buid), 1);
745 if (rc)
746 printk(KERN_WARNING
747 "EEH: Unable to reset the failed slot,"
748 " #RST=%d dn=%s\n",
749 rc, pdn->node->full_name);
750 }
751}
752
753/**
754 * pcibios_set_pcie_slot_reset - Set PCI-E reset state 565 * pcibios_set_pcie_slot_reset - Set PCI-E reset state
755 * @dev: pci device struct 566 * @dev: pci device struct
756 * @state: reset state to enter 567 * @state: reset state to enter
757 * 568 *
758 * Return value: 569 * Return value:
759 * 0 if success 570 * 0 if success
760 **/ 571 */
761int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) 572int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
762{ 573{
763 struct device_node *dn = pci_device_to_OF_node(dev); 574 struct device_node *dn = pci_device_to_OF_node(dev);
764 struct pci_dn *pdn = PCI_DN(dn);
765 575
766 switch (state) { 576 switch (state) {
767 case pcie_deassert_reset: 577 case pcie_deassert_reset:
768 rtas_pci_slot_reset(pdn, 0); 578 eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
769 break; 579 break;
770 case pcie_hot_reset: 580 case pcie_hot_reset:
771 rtas_pci_slot_reset(pdn, 1); 581 eeh_ops->reset(dn, EEH_RESET_HOT);
772 break; 582 break;
773 case pcie_warm_reset: 583 case pcie_warm_reset:
774 rtas_pci_slot_reset(pdn, 3); 584 eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
775 break; 585 break;
776 default: 586 default:
777 return -EINVAL; 587 return -EINVAL;
@@ -781,13 +591,66 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
781} 591}
782 592
783/** 593/**
784 * rtas_set_slot_reset -- assert the pci #RST line for 1/4 second 594 * __eeh_set_pe_freset - Check the required reset for child devices
785 * @pdn: pci device node to be reset. 595 * @parent: parent device
596 * @freset: return value
597 *
598 * Each device might have its preferred reset type: fundamental or
599 * hot reset. The routine is used to collect the information from
600 * the child devices so that they could be reset accordingly.
601 */
602void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
603{
604 struct device_node *dn;
605
606 for_each_child_of_node(parent, dn) {
607 if (of_node_to_eeh_dev(dn)) {
608 struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
609
610 if (dev && dev->driver)
611 *freset |= dev->needs_freset;
612
613 __eeh_set_pe_freset(dn, freset);
614 }
615 }
616}
617
618/**
619 * eeh_set_pe_freset - Check the required reset for the indicated device and its children
620 * @dn: parent device
621 * @freset: return value
622 *
623 * Each device might have its preferred reset type: fundamental or
624 * hot reset. The routine is used to collected the information for
625 * the indicated device and its children so that the bunch of the
626 * devices could be reset properly.
786 */ 627 */
628void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
629{
630 struct pci_dev *dev;
631 dn = eeh_find_device_pe(dn);
632
633 /* Back up one, since config addrs might be shared */
634 if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
635 dn = dn->parent;
636
637 dev = of_node_to_eeh_dev(dn)->pdev;
638 if (dev)
639 *freset |= dev->needs_freset;
787 640
788static void __rtas_set_slot_reset(struct pci_dn *pdn) 641 __eeh_set_pe_freset(dn, freset);
642}
643
644/**
645 * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
646 * @edev: pci device node to be reset.
647 *
648 * Assert the PCI #RST line for 1/4 second.
649 */
650static void eeh_reset_pe_once(struct eeh_dev *edev)
789{ 651{
790 unsigned int freset = 0; 652 unsigned int freset = 0;
653 struct device_node *dn = eeh_dev_to_of_node(edev);
791 654
792 /* Determine type of EEH reset required for 655 /* Determine type of EEH reset required for
793 * Partitionable Endpoint, a hot-reset (1) 656 * Partitionable Endpoint, a hot-reset (1)
@@ -795,58 +658,68 @@ static void __rtas_set_slot_reset(struct pci_dn *pdn)
795 * A fundamental reset required by any device under 658 * A fundamental reset required by any device under
796 * Partitionable Endpoint trumps hot-reset. 659 * Partitionable Endpoint trumps hot-reset.
797 */ 660 */
798 eeh_set_pe_freset(pdn->node, &freset); 661 eeh_set_pe_freset(dn, &freset);
799 662
800 if (freset) 663 if (freset)
801 rtas_pci_slot_reset(pdn, 3); 664 eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
802 else 665 else
803 rtas_pci_slot_reset(pdn, 1); 666 eeh_ops->reset(dn, EEH_RESET_HOT);
804 667
805 /* The PCI bus requires that the reset be held high for at least 668 /* The PCI bus requires that the reset be held high for at least
806 * a 100 milliseconds. We wait a bit longer 'just in case'. */ 669 * a 100 milliseconds. We wait a bit longer 'just in case'.
807 670 */
808#define PCI_BUS_RST_HOLD_TIME_MSEC 250 671#define PCI_BUS_RST_HOLD_TIME_MSEC 250
809 msleep (PCI_BUS_RST_HOLD_TIME_MSEC); 672 msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
810 673
811 /* We might get hit with another EEH freeze as soon as the 674 /* We might get hit with another EEH freeze as soon as the
812 * pci slot reset line is dropped. Make sure we don't miss 675 * pci slot reset line is dropped. Make sure we don't miss
813 * these, and clear the flag now. */ 676 * these, and clear the flag now.
814 eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED); 677 */
678 eeh_clear_slot(dn, EEH_MODE_ISOLATED);
815 679
816 rtas_pci_slot_reset (pdn, 0); 680 eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
817 681
818 /* After a PCI slot has been reset, the PCI Express spec requires 682 /* After a PCI slot has been reset, the PCI Express spec requires
819 * a 1.5 second idle time for the bus to stabilize, before starting 683 * a 1.5 second idle time for the bus to stabilize, before starting
820 * up traffic. */ 684 * up traffic.
685 */
821#define PCI_BUS_SETTLE_TIME_MSEC 1800 686#define PCI_BUS_SETTLE_TIME_MSEC 1800
822 msleep (PCI_BUS_SETTLE_TIME_MSEC); 687 msleep(PCI_BUS_SETTLE_TIME_MSEC);
823} 688}
824 689
825int rtas_set_slot_reset(struct pci_dn *pdn) 690/**
691 * eeh_reset_pe - Reset the indicated PE
692 * @edev: PCI device associated EEH device
693 *
694 * This routine should be called to reset indicated device, including
695 * PE. A PE might include multiple PCI devices and sometimes PCI bridges
696 * might be involved as well.
697 */
698int eeh_reset_pe(struct eeh_dev *edev)
826{ 699{
827 int i, rc; 700 int i, rc;
701 struct device_node *dn = eeh_dev_to_of_node(edev);
828 702
829 /* Take three shots at resetting the bus */ 703 /* Take three shots at resetting the bus */
830 for (i=0; i<3; i++) { 704 for (i=0; i<3; i++) {
831 __rtas_set_slot_reset(pdn); 705 eeh_reset_pe_once(edev);
832 706
833 rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); 707 rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
834 if (rc == 0) 708 if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
835 return 0; 709 return 0;
836 710
837 if (rc < 0) { 711 if (rc < 0) {
838 printk(KERN_ERR "EEH: unrecoverable slot failure %s\n", 712 printk(KERN_ERR "EEH: unrecoverable slot failure %s\n",
839 pdn->node->full_name); 713 dn->full_name);
840 return -1; 714 return -1;
841 } 715 }
842 printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n", 716 printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n",
843 i+1, pdn->node->full_name, rc); 717 i+1, dn->full_name, rc);
844 } 718 }
845 719
846 return -1; 720 return -1;
847} 721}
848 722
849/* ------------------------------------------------------- */
850/** Save and restore of PCI BARs 723/** Save and restore of PCI BARs
851 * 724 *
852 * Although firmware will set up BARs during boot, it doesn't 725 * Although firmware will set up BARs during boot, it doesn't
@@ -856,181 +729,122 @@ int rtas_set_slot_reset(struct pci_dn *pdn)
856 */ 729 */
857 730
858/** 731/**
859 * __restore_bars - Restore the Base Address Registers 732 * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
860 * @pdn: pci device node 733 * @edev: PCI device associated EEH device
861 * 734 *
862 * Loads the PCI configuration space base address registers, 735 * Loads the PCI configuration space base address registers,
863 * the expansion ROM base address, the latency timer, and etc. 736 * the expansion ROM base address, the latency timer, and etc.
864 * from the saved values in the device node. 737 * from the saved values in the device node.
865 */ 738 */
866static inline void __restore_bars (struct pci_dn *pdn) 739static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)
867{ 740{
868 int i; 741 int i;
869 u32 cmd; 742 u32 cmd;
743 struct device_node *dn = eeh_dev_to_of_node(edev);
744
745 if (!edev->phb)
746 return;
870 747
871 if (NULL==pdn->phb) return;
872 for (i=4; i<10; i++) { 748 for (i=4; i<10; i++) {
873 rtas_write_config(pdn, i*4, 4, pdn->config_space[i]); 749 eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
874 } 750 }
875 751
876 /* 12 == Expansion ROM Address */ 752 /* 12 == Expansion ROM Address */
877 rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]); 753 eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
878 754
879#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) 755#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
880#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)]) 756#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
881 757
882 rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1, 758 eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
883 SAVED_BYTE(PCI_CACHE_LINE_SIZE)); 759 SAVED_BYTE(PCI_CACHE_LINE_SIZE));
884 760
885 rtas_write_config (pdn, PCI_LATENCY_TIMER, 1, 761 eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
886 SAVED_BYTE(PCI_LATENCY_TIMER)); 762 SAVED_BYTE(PCI_LATENCY_TIMER));
887 763
888 /* max latency, min grant, interrupt pin and line */ 764 /* max latency, min grant, interrupt pin and line */
889 rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); 765 eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
890 766
891 /* Restore PERR & SERR bits, some devices require it, 767 /* Restore PERR & SERR bits, some devices require it,
892 don't touch the other command bits */ 768 * don't touch the other command bits
893 rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); 769 */
894 if (pdn->config_space[1] & PCI_COMMAND_PARITY) 770 eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
771 if (edev->config_space[1] & PCI_COMMAND_PARITY)
895 cmd |= PCI_COMMAND_PARITY; 772 cmd |= PCI_COMMAND_PARITY;
896 else 773 else
897 cmd &= ~PCI_COMMAND_PARITY; 774 cmd &= ~PCI_COMMAND_PARITY;
898 if (pdn->config_space[1] & PCI_COMMAND_SERR) 775 if (edev->config_space[1] & PCI_COMMAND_SERR)
899 cmd |= PCI_COMMAND_SERR; 776 cmd |= PCI_COMMAND_SERR;
900 else 777 else
901 cmd &= ~PCI_COMMAND_SERR; 778 cmd &= ~PCI_COMMAND_SERR;
902 rtas_write_config(pdn, PCI_COMMAND, 4, cmd); 779 eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
903} 780}
904 781
905/** 782/**
906 * eeh_restore_bars - restore the PCI config space info 783 * eeh_restore_bars - Restore the PCI config space info
784 * @edev: EEH device
907 * 785 *
908 * This routine performs a recursive walk to the children 786 * This routine performs a recursive walk to the children
909 * of this device as well. 787 * of this device as well.
910 */ 788 */
911void eeh_restore_bars(struct pci_dn *pdn) 789void eeh_restore_bars(struct eeh_dev *edev)
912{ 790{
913 struct device_node *dn; 791 struct device_node *dn;
914 if (!pdn) 792 if (!edev)
915 return; 793 return;
916 794
917 if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) 795 if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))
918 __restore_bars (pdn); 796 eeh_restore_one_device_bars(edev);
919 797
920 for_each_child_of_node(pdn->node, dn) 798 for_each_child_of_node(eeh_dev_to_of_node(edev), dn)
921 eeh_restore_bars (PCI_DN(dn)); 799 eeh_restore_bars(of_node_to_eeh_dev(dn));
922} 800}
923 801
924/** 802/**
925 * eeh_save_bars - save device bars 803 * eeh_save_bars - Save device bars
804 * @edev: PCI device associated EEH device
926 * 805 *
927 * Save the values of the device bars. Unlike the restore 806 * Save the values of the device bars. Unlike the restore
928 * routine, this routine is *not* recursive. This is because 807 * routine, this routine is *not* recursive. This is because
929 * PCI devices are added individually; but, for the restore, 808 * PCI devices are added individually; but, for the restore,
930 * an entire slot is reset at a time. 809 * an entire slot is reset at a time.
931 */ 810 */
932static void eeh_save_bars(struct pci_dn *pdn) 811static void eeh_save_bars(struct eeh_dev *edev)
933{ 812{
934 int i; 813 int i;
814 struct device_node *dn;
935 815
936 if (!pdn ) 816 if (!edev)
937 return; 817 return;
818 dn = eeh_dev_to_of_node(edev);
938 819
939 for (i = 0; i < 16; i++) 820 for (i = 0; i < 16; i++)
940 rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); 821 eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);
941}
942
943void
944rtas_configure_bridge(struct pci_dn *pdn)
945{
946 int config_addr;
947 int rc;
948 int token;
949
950 /* Use PE configuration address, if present */
951 config_addr = pdn->eeh_config_addr;
952 if (pdn->eeh_pe_config_addr)
953 config_addr = pdn->eeh_pe_config_addr;
954
955 /* Use new configure-pe function, if supported */
956 if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE)
957 token = ibm_configure_pe;
958 else
959 token = ibm_configure_bridge;
960
961 rc = rtas_call(token, 3, 1, NULL,
962 config_addr,
963 BUID_HI(pdn->phb->buid),
964 BUID_LO(pdn->phb->buid));
965 if (rc) {
966 printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n",
967 rc, pdn->node->full_name);
968 }
969} 822}
970 823
971/* ------------------------------------------------------------- */ 824/**
972/* The code below deals with enabling EEH for devices during the 825 * eeh_early_enable - Early enable EEH on the indicated device
973 * early boot sequence. EEH must be enabled before any PCI probing 826 * @dn: device node
974 * can be done. 827 * @data: BUID
828 *
829 * Enable EEH functionality on the specified PCI device. The function
830 * is expected to be called before real PCI probing is done. However,
831 * the PHBs have been initialized at this point.
975 */ 832 */
976 833static void *eeh_early_enable(struct device_node *dn, void *data)
977#define EEH_ENABLE 1
978
979struct eeh_early_enable_info {
980 unsigned int buid_hi;
981 unsigned int buid_lo;
982};
983
984static int get_pe_addr (int config_addr,
985 struct eeh_early_enable_info *info)
986{ 834{
987 unsigned int rets[3];
988 int ret;
989
990 /* Use latest config-addr token on power6 */
991 if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
992 /* Make sure we have a PE in hand */
993 ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,
994 config_addr, info->buid_hi, info->buid_lo, 1);
995 if (ret || (rets[0]==0))
996 return 0;
997
998 ret = rtas_call (ibm_get_config_addr_info2, 4, 2, rets,
999 config_addr, info->buid_hi, info->buid_lo, 0);
1000 if (ret)
1001 return 0;
1002 return rets[0];
1003 }
1004
1005 /* Use older config-addr token on power5 */
1006 if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
1007 ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets,
1008 config_addr, info->buid_hi, info->buid_lo, 0);
1009 if (ret)
1010 return 0;
1011 return rets[0];
1012 }
1013 return 0;
1014}
1015
1016/* Enable eeh for the given device node. */
1017static void *early_enable_eeh(struct device_node *dn, void *data)
1018{
1019 unsigned int rets[3];
1020 struct eeh_early_enable_info *info = data;
1021 int ret; 835 int ret;
1022 const u32 *class_code = of_get_property(dn, "class-code", NULL); 836 const u32 *class_code = of_get_property(dn, "class-code", NULL);
1023 const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL); 837 const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
1024 const u32 *device_id = of_get_property(dn, "device-id", NULL); 838 const u32 *device_id = of_get_property(dn, "device-id", NULL);
1025 const u32 *regs; 839 const u32 *regs;
1026 int enable; 840 int enable;
1027 struct pci_dn *pdn = PCI_DN(dn); 841 struct eeh_dev *edev = of_node_to_eeh_dev(dn);
1028 842
1029 pdn->class_code = 0; 843 edev->class_code = 0;
1030 pdn->eeh_mode = 0; 844 edev->mode = 0;
1031 pdn->eeh_check_count = 0; 845 edev->check_count = 0;
1032 pdn->eeh_freeze_count = 0; 846 edev->freeze_count = 0;
1033 pdn->eeh_false_positives = 0; 847 edev->false_positives = 0;
1034 848
1035 if (!of_device_is_available(dn)) 849 if (!of_device_is_available(dn))
1036 return NULL; 850 return NULL;
@@ -1041,54 +855,56 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
1041 855
1042 /* There is nothing to check on PCI to ISA bridges */ 856 /* There is nothing to check on PCI to ISA bridges */
1043 if (dn->type && !strcmp(dn->type, "isa")) { 857 if (dn->type && !strcmp(dn->type, "isa")) {
1044 pdn->eeh_mode |= EEH_MODE_NOCHECK; 858 edev->mode |= EEH_MODE_NOCHECK;
1045 return NULL; 859 return NULL;
1046 } 860 }
1047 pdn->class_code = *class_code; 861 edev->class_code = *class_code;
1048 862
1049 /* Ok... see if this device supports EEH. Some do, some don't, 863 /* Ok... see if this device supports EEH. Some do, some don't,
1050 * and the only way to find out is to check each and every one. */ 864 * and the only way to find out is to check each and every one.
865 */
1051 regs = of_get_property(dn, "reg", NULL); 866 regs = of_get_property(dn, "reg", NULL);
1052 if (regs) { 867 if (regs) {
1053 /* First register entry is addr (00BBSS00) */ 868 /* First register entry is addr (00BBSS00) */
1054 /* Try to enable eeh */ 869 /* Try to enable eeh */
1055 ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, 870 ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE);
1056 regs[0], info->buid_hi, info->buid_lo,
1057 EEH_ENABLE);
1058 871
1059 enable = 0; 872 enable = 0;
1060 if (ret == 0) { 873 if (ret == 0) {
1061 pdn->eeh_config_addr = regs[0]; 874 edev->config_addr = regs[0];
1062 875
1063 /* If the newer, better, ibm,get-config-addr-info is supported, 876 /* If the newer, better, ibm,get-config-addr-info is supported,
1064 * then use that instead. */ 877 * then use that instead.
1065 pdn->eeh_pe_config_addr = get_pe_addr(pdn->eeh_config_addr, info); 878 */
879 edev->pe_config_addr = eeh_ops->get_pe_addr(dn);
1066 880
1067 /* Some older systems (Power4) allow the 881 /* Some older systems (Power4) allow the
1068 * ibm,set-eeh-option call to succeed even on nodes 882 * ibm,set-eeh-option call to succeed even on nodes
1069 * where EEH is not supported. Verify support 883 * where EEH is not supported. Verify support
1070 * explicitly. */ 884 * explicitly.
1071 ret = read_slot_reset_state(pdn, rets); 885 */
1072 if ((ret == 0) && (rets[1] == 1)) 886 ret = eeh_ops->get_state(dn, NULL);
887 if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
1073 enable = 1; 888 enable = 1;
1074 } 889 }
1075 890
1076 if (enable) { 891 if (enable) {
1077 eeh_subsystem_enabled = 1; 892 eeh_subsystem_enabled = 1;
1078 pdn->eeh_mode |= EEH_MODE_SUPPORTED; 893 edev->mode |= EEH_MODE_SUPPORTED;
1079 894
1080 pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n", 895 pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
1081 dn->full_name, pdn->eeh_config_addr, 896 dn->full_name, edev->config_addr,
1082 pdn->eeh_pe_config_addr); 897 edev->pe_config_addr);
1083 } else { 898 } else {
1084 899
1085 /* This device doesn't support EEH, but it may have an 900 /* This device doesn't support EEH, but it may have an
1086 * EEH parent, in which case we mark it as supported. */ 901 * EEH parent, in which case we mark it as supported.
1087 if (dn->parent && PCI_DN(dn->parent) 902 */
1088 && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) { 903 if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
904 (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
1089 /* Parent supports EEH. */ 905 /* Parent supports EEH. */
1090 pdn->eeh_mode |= EEH_MODE_SUPPORTED; 906 edev->mode |= EEH_MODE_SUPPORTED;
1091 pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr; 907 edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
1092 return NULL; 908 return NULL;
1093 } 909 }
1094 } 910 }
@@ -1097,11 +913,63 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
1097 dn->full_name); 913 dn->full_name);
1098 } 914 }
1099 915
1100 eeh_save_bars(pdn); 916 eeh_save_bars(edev);
1101 return NULL; 917 return NULL;
1102} 918}
1103 919
1104/* 920/**
921 * eeh_ops_register - Register platform dependent EEH operations
922 * @ops: platform dependent EEH operations
923 *
924 * Register the platform dependent EEH operation callback
925 * functions. The platform should call this function before
926 * any other EEH operations.
927 */
928int __init eeh_ops_register(struct eeh_ops *ops)
929{
930 if (!ops->name) {
931 pr_warning("%s: Invalid EEH ops name for %p\n",
932 __func__, ops);
933 return -EINVAL;
934 }
935
936 if (eeh_ops && eeh_ops != ops) {
937 pr_warning("%s: EEH ops of platform %s already existing (%s)\n",
938 __func__, eeh_ops->name, ops->name);
939 return -EEXIST;
940 }
941
942 eeh_ops = ops;
943
944 return 0;
945}
946
947/**
948 * eeh_ops_unregister - Unreigster platform dependent EEH operations
949 * @name: name of EEH platform operations
950 *
951 * Unregister the platform dependent EEH operation callback
952 * functions.
953 */
954int __exit eeh_ops_unregister(const char *name)
955{
956 if (!name || !strlen(name)) {
957 pr_warning("%s: Invalid EEH ops name\n",
958 __func__);
959 return -EINVAL;
960 }
961
962 if (eeh_ops && !strcmp(eeh_ops->name, name)) {
963 eeh_ops = NULL;
964 return 0;
965 }
966
967 return -EEXIST;
968}
969
970/**
971 * eeh_init - EEH initialization
972 *
1105 * Initialize EEH by trying to enable it for all of the adapters in the system. 973 * Initialize EEH by trying to enable it for all of the adapters in the system.
1106 * As a side effect we can determine here if eeh is supported at all. 974 * As a side effect we can determine here if eeh is supported at all.
1107 * Note that we leave EEH on so failed config cycles won't cause a machine 975 * Note that we leave EEH on so failed config cycles won't cause a machine
@@ -1117,50 +985,35 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
1117void __init eeh_init(void) 985void __init eeh_init(void)
1118{ 986{
1119 struct device_node *phb, *np; 987 struct device_node *phb, *np;
1120 struct eeh_early_enable_info info; 988 int ret;
989
990 /* call platform initialization function */
991 if (!eeh_ops) {
992 pr_warning("%s: Platform EEH operation not found\n",
993 __func__);
994 return;
995 } else if ((ret = eeh_ops->init())) {
996 pr_warning("%s: Failed to call platform init function (%d)\n",
997 __func__, ret);
998 return;
999 }
1121 1000
1122 raw_spin_lock_init(&confirm_error_lock); 1001 raw_spin_lock_init(&confirm_error_lock);
1123 spin_lock_init(&slot_errbuf_lock);
1124 1002
1125 np = of_find_node_by_path("/rtas"); 1003 np = of_find_node_by_path("/rtas");
1126 if (np == NULL) 1004 if (np == NULL)
1127 return; 1005 return;
1128 1006
1129 ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
1130 ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
1131 ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");
1132 ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
1133 ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
1134 ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
1135 ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
1136 ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
1137 ibm_configure_pe = rtas_token("ibm,configure-pe");
1138
1139 if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
1140 return;
1141
1142 eeh_error_buf_size = rtas_token("rtas-error-log-max");
1143 if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {
1144 eeh_error_buf_size = 1024;
1145 }
1146 if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
1147 printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than allocated "
1148 "buffer ! (%d vs %d)", eeh_error_buf_size, RTAS_ERROR_LOG_MAX);
1149 eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
1150 }
1151
1152 /* Enable EEH for all adapters. Note that eeh requires buid's */ 1007 /* Enable EEH for all adapters. Note that eeh requires buid's */
1153 for (phb = of_find_node_by_name(NULL, "pci"); phb; 1008 for (phb = of_find_node_by_name(NULL, "pci"); phb;
1154 phb = of_find_node_by_name(phb, "pci")) { 1009 phb = of_find_node_by_name(phb, "pci")) {
1155 unsigned long buid; 1010 unsigned long buid;
1156 1011
1157 buid = get_phb_buid(phb); 1012 buid = get_phb_buid(phb);
1158 if (buid == 0 || PCI_DN(phb) == NULL) 1013 if (buid == 0 || !of_node_to_eeh_dev(phb))
1159 continue; 1014 continue;
1160 1015
1161 info.buid_lo = BUID_LO(buid); 1016 traverse_pci_devices(phb, eeh_early_enable, NULL);
1162 info.buid_hi = BUID_HI(buid);
1163 traverse_pci_devices(phb, early_enable_eeh, &info);
1164 } 1017 }
1165 1018
1166 if (eeh_subsystem_enabled) 1019 if (eeh_subsystem_enabled)
@@ -1170,7 +1023,7 @@ void __init eeh_init(void)
1170} 1023}
1171 1024
1172/** 1025/**
1173 * eeh_add_device_early - enable EEH for the indicated device_node 1026 * eeh_add_device_early - Enable EEH for the indicated device_node
1174 * @dn: device node for which to set up EEH 1027 * @dn: device node for which to set up EEH
1175 * 1028 *
1176 * This routine must be used to perform EEH initialization for PCI 1029 * This routine must be used to perform EEH initialization for PCI
@@ -1184,21 +1037,26 @@ void __init eeh_init(void)
1184static void eeh_add_device_early(struct device_node *dn) 1037static void eeh_add_device_early(struct device_node *dn)
1185{ 1038{
1186 struct pci_controller *phb; 1039 struct pci_controller *phb;
1187 struct eeh_early_enable_info info;
1188 1040
1189 if (!dn || !PCI_DN(dn)) 1041 if (!dn || !of_node_to_eeh_dev(dn))
1190 return; 1042 return;
1191 phb = PCI_DN(dn)->phb; 1043 phb = of_node_to_eeh_dev(dn)->phb;
1192 1044
1193 /* USB Bus children of PCI devices will not have BUID's */ 1045 /* USB Bus children of PCI devices will not have BUID's */
1194 if (NULL == phb || 0 == phb->buid) 1046 if (NULL == phb || 0 == phb->buid)
1195 return; 1047 return;
1196 1048
1197 info.buid_hi = BUID_HI(phb->buid); 1049 eeh_early_enable(dn, NULL);
1198 info.buid_lo = BUID_LO(phb->buid);
1199 early_enable_eeh(dn, &info);
1200} 1050}
1201 1051
1052/**
1053 * eeh_add_device_tree_early - Enable EEH for the indicated device
1054 * @dn: device node
1055 *
1056 * This routine must be used to perform EEH initialization for the
1057 * indicated PCI device that was added after system boot (e.g.
1058 * hotplug, dlpar).
1059 */
1202void eeh_add_device_tree_early(struct device_node *dn) 1060void eeh_add_device_tree_early(struct device_node *dn)
1203{ 1061{
1204 struct device_node *sib; 1062 struct device_node *sib;
@@ -1210,7 +1068,7 @@ void eeh_add_device_tree_early(struct device_node *dn)
1210EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); 1068EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
1211 1069
1212/** 1070/**
1213 * eeh_add_device_late - perform EEH initialization for the indicated pci device 1071 * eeh_add_device_late - Perform EEH initialization for the indicated pci device
1214 * @dev: pci device for which to set up EEH 1072 * @dev: pci device for which to set up EEH
1215 * 1073 *
1216 * This routine must be used to complete EEH initialization for PCI 1074 * This routine must be used to complete EEH initialization for PCI
@@ -1219,7 +1077,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
1219static void eeh_add_device_late(struct pci_dev *dev) 1077static void eeh_add_device_late(struct pci_dev *dev)
1220{ 1078{
1221 struct device_node *dn; 1079 struct device_node *dn;
1222 struct pci_dn *pdn; 1080 struct eeh_dev *edev;
1223 1081
1224 if (!dev || !eeh_subsystem_enabled) 1082 if (!dev || !eeh_subsystem_enabled)
1225 return; 1083 return;
@@ -1227,20 +1085,29 @@ static void eeh_add_device_late(struct pci_dev *dev)
1227 pr_debug("EEH: Adding device %s\n", pci_name(dev)); 1085 pr_debug("EEH: Adding device %s\n", pci_name(dev));
1228 1086
1229 dn = pci_device_to_OF_node(dev); 1087 dn = pci_device_to_OF_node(dev);
1230 pdn = PCI_DN(dn); 1088 edev = pci_dev_to_eeh_dev(dev);
1231 if (pdn->pcidev == dev) { 1089 if (edev->pdev == dev) {
1232 pr_debug("EEH: Already referenced !\n"); 1090 pr_debug("EEH: Already referenced !\n");
1233 return; 1091 return;
1234 } 1092 }
1235 WARN_ON(pdn->pcidev); 1093 WARN_ON(edev->pdev);
1236 1094
1237 pci_dev_get (dev); 1095 pci_dev_get(dev);
1238 pdn->pcidev = dev; 1096 edev->pdev = dev;
1097 dev->dev.archdata.edev = edev;
1239 1098
1240 pci_addr_cache_insert_device(dev); 1099 pci_addr_cache_insert_device(dev);
1241 eeh_sysfs_add_device(dev); 1100 eeh_sysfs_add_device(dev);
1242} 1101}
1243 1102
1103/**
1104 * eeh_add_device_tree_late - Perform EEH initialization for the indicated PCI bus
1105 * @bus: PCI bus
1106 *
1107 * This routine must be used to perform EEH initialization for PCI
1108 * devices which are attached to the indicated PCI bus. The PCI bus
1109 * is added after system boot through hotplug or dlpar.
1110 */
1244void eeh_add_device_tree_late(struct pci_bus *bus) 1111void eeh_add_device_tree_late(struct pci_bus *bus)
1245{ 1112{
1246 struct pci_dev *dev; 1113 struct pci_dev *dev;
@@ -1257,7 +1124,7 @@ void eeh_add_device_tree_late(struct pci_bus *bus)
1257EXPORT_SYMBOL_GPL(eeh_add_device_tree_late); 1124EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
1258 1125
1259/** 1126/**
1260 * eeh_remove_device - undo EEH setup for the indicated pci device 1127 * eeh_remove_device - Undo EEH setup for the indicated pci device
1261 * @dev: pci device to be removed 1128 * @dev: pci device to be removed
1262 * 1129 *
1263 * This routine should be called when a device is removed from 1130 * This routine should be called when a device is removed from
@@ -1268,25 +1135,35 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
1268 */ 1135 */
1269static void eeh_remove_device(struct pci_dev *dev) 1136static void eeh_remove_device(struct pci_dev *dev)
1270{ 1137{
1271 struct device_node *dn; 1138 struct eeh_dev *edev;
1139
1272 if (!dev || !eeh_subsystem_enabled) 1140 if (!dev || !eeh_subsystem_enabled)
1273 return; 1141 return;
1142 edev = pci_dev_to_eeh_dev(dev);
1274 1143
1275 /* Unregister the device with the EEH/PCI address search system */ 1144 /* Unregister the device with the EEH/PCI address search system */
1276 pr_debug("EEH: Removing device %s\n", pci_name(dev)); 1145 pr_debug("EEH: Removing device %s\n", pci_name(dev));
1277 1146
1278 dn = pci_device_to_OF_node(dev); 1147 if (!edev || !edev->pdev) {
1279 if (PCI_DN(dn)->pcidev == NULL) {
1280 pr_debug("EEH: Not referenced !\n"); 1148 pr_debug("EEH: Not referenced !\n");
1281 return; 1149 return;
1282 } 1150 }
1283 PCI_DN(dn)->pcidev = NULL; 1151 edev->pdev = NULL;
1284 pci_dev_put (dev); 1152 dev->dev.archdata.edev = NULL;
1153 pci_dev_put(dev);
1285 1154
1286 pci_addr_cache_remove_device(dev); 1155 pci_addr_cache_remove_device(dev);
1287 eeh_sysfs_remove_device(dev); 1156 eeh_sysfs_remove_device(dev);
1288} 1157}
1289 1158
1159/**
1160 * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
1161 * @dev: PCI device
1162 *
1163 * This routine must be called when a device is removed from the
1164 * running system through hotplug or dlpar. The corresponding
1165 * PCI address cache will be removed.
1166 */
1290void eeh_remove_bus_device(struct pci_dev *dev) 1167void eeh_remove_bus_device(struct pci_dev *dev)
1291{ 1168{
1292 struct pci_bus *bus = dev->subordinate; 1169 struct pci_bus *bus = dev->subordinate;
@@ -1305,21 +1182,24 @@ static int proc_eeh_show(struct seq_file *m, void *v)
1305{ 1182{
1306 if (0 == eeh_subsystem_enabled) { 1183 if (0 == eeh_subsystem_enabled) {
1307 seq_printf(m, "EEH Subsystem is globally disabled\n"); 1184 seq_printf(m, "EEH Subsystem is globally disabled\n");
1308 seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs); 1185 seq_printf(m, "eeh_total_mmio_ffs=%llu\n", eeh_stats.total_mmio_ffs);
1309 } else { 1186 } else {
1310 seq_printf(m, "EEH Subsystem is enabled\n"); 1187 seq_printf(m, "EEH Subsystem is enabled\n");
1311 seq_printf(m, 1188 seq_printf(m,
1312 "no device=%ld\n" 1189 "no device=%llu\n"
1313 "no device node=%ld\n" 1190 "no device node=%llu\n"
1314 "no config address=%ld\n" 1191 "no config address=%llu\n"
1315 "check not wanted=%ld\n" 1192 "check not wanted=%llu\n"
1316 "eeh_total_mmio_ffs=%ld\n" 1193 "eeh_total_mmio_ffs=%llu\n"
1317 "eeh_false_positives=%ld\n" 1194 "eeh_false_positives=%llu\n"
1318 "eeh_slot_resets=%ld\n", 1195 "eeh_slot_resets=%llu\n",
1319 no_device, no_dn, no_cfg_addr, 1196 eeh_stats.no_device,
1320 ignored_check, total_mmio_ffs, 1197 eeh_stats.no_dn,
1321 false_positives, 1198 eeh_stats.no_cfg_addr,
1322 slot_resets); 1199 eeh_stats.ignored_check,
1200 eeh_stats.total_mmio_ffs,
1201 eeh_stats.false_positives,
1202 eeh_stats.slot_resets);
1323 } 1203 }
1324 1204
1325 return 0; 1205 return 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index fc5ae767989e..e5ae1c687c66 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -1,5 +1,4 @@
1/* 1/*
2 * eeh_cache.c
3 * PCI address cache; allows the lookup of PCI devices based on I/O address 2 * PCI address cache; allows the lookup of PCI devices based on I/O address
4 * 3 *
5 * Copyright IBM Corporation 2004 4 * Copyright IBM Corporation 2004
@@ -47,8 +46,7 @@
47 * than any hash algo I could think of for this problem, even 46 * than any hash algo I could think of for this problem, even
48 * with the penalty of slow pointer chases for d-cache misses). 47 * with the penalty of slow pointer chases for d-cache misses).
49 */ 48 */
50struct pci_io_addr_range 49struct pci_io_addr_range {
51{
52 struct rb_node rb_node; 50 struct rb_node rb_node;
53 unsigned long addr_lo; 51 unsigned long addr_lo;
54 unsigned long addr_hi; 52 unsigned long addr_hi;
@@ -56,13 +54,12 @@ struct pci_io_addr_range
56 unsigned int flags; 54 unsigned int flags;
57}; 55};
58 56
59static struct pci_io_addr_cache 57static struct pci_io_addr_cache {
60{
61 struct rb_root rb_root; 58 struct rb_root rb_root;
62 spinlock_t piar_lock; 59 spinlock_t piar_lock;
63} pci_io_addr_cache_root; 60} pci_io_addr_cache_root;
64 61
65static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr) 62static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
66{ 63{
67 struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node; 64 struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
68 65
@@ -86,7 +83,7 @@ static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
86} 83}
87 84
88/** 85/**
89 * pci_get_device_by_addr - Get device, given only address 86 * pci_addr_cache_get_device - Get device, given only address
90 * @addr: mmio (PIO) phys address or i/o port number 87 * @addr: mmio (PIO) phys address or i/o port number
91 * 88 *
92 * Given an mmio phys address, or a port number, find a pci device 89 * Given an mmio phys address, or a port number, find a pci device
@@ -95,13 +92,13 @@ static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
95 * from zero (that is, they do *not* have pci_io_addr added in). 92 * from zero (that is, they do *not* have pci_io_addr added in).
96 * It is safe to call this function within an interrupt. 93 * It is safe to call this function within an interrupt.
97 */ 94 */
98struct pci_dev *pci_get_device_by_addr(unsigned long addr) 95struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
99{ 96{
100 struct pci_dev *dev; 97 struct pci_dev *dev;
101 unsigned long flags; 98 unsigned long flags;
102 99
103 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags); 100 spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
104 dev = __pci_get_device_by_addr(addr); 101 dev = __pci_addr_cache_get_device(addr);
105 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags); 102 spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
106 return dev; 103 return dev;
107} 104}
@@ -166,7 +163,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
166 163
167#ifdef DEBUG 164#ifdef DEBUG
168 printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n", 165 printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
169 alo, ahi, pci_name (dev)); 166 alo, ahi, pci_name(dev));
170#endif 167#endif
171 168
172 rb_link_node(&piar->rb_node, parent, p); 169 rb_link_node(&piar->rb_node, parent, p);
@@ -178,7 +175,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
178static void __pci_addr_cache_insert_device(struct pci_dev *dev) 175static void __pci_addr_cache_insert_device(struct pci_dev *dev)
179{ 176{
180 struct device_node *dn; 177 struct device_node *dn;
181 struct pci_dn *pdn; 178 struct eeh_dev *edev;
182 int i; 179 int i;
183 180
184 dn = pci_device_to_OF_node(dev); 181 dn = pci_device_to_OF_node(dev);
@@ -187,13 +184,19 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
187 return; 184 return;
188 } 185 }
189 186
187 edev = of_node_to_eeh_dev(dn);
188 if (!edev) {
189 pr_warning("PCI: no EEH dev found for dn=%s\n",
190 dn->full_name);
191 return;
192 }
193
190 /* Skip any devices for which EEH is not enabled. */ 194 /* Skip any devices for which EEH is not enabled. */
191 pdn = PCI_DN(dn); 195 if (!(edev->mode & EEH_MODE_SUPPORTED) ||
192 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || 196 edev->mode & EEH_MODE_NOCHECK) {
193 pdn->eeh_mode & EEH_MODE_NOCHECK) {
194#ifdef DEBUG 197#ifdef DEBUG
195 printk(KERN_INFO "PCI: skip building address cache for=%s - %s\n", 198 pr_info("PCI: skip building address cache for=%s - %s\n",
196 pci_name(dev), pdn->node->full_name); 199 pci_name(dev), dn->full_name);
197#endif 200#endif
198 return; 201 return;
199 } 202 }
@@ -284,6 +287,7 @@ void pci_addr_cache_remove_device(struct pci_dev *dev)
284void __init pci_addr_cache_build(void) 287void __init pci_addr_cache_build(void)
285{ 288{
286 struct device_node *dn; 289 struct device_node *dn;
290 struct eeh_dev *edev;
287 struct pci_dev *dev = NULL; 291 struct pci_dev *dev = NULL;
288 292
289 spin_lock_init(&pci_io_addr_cache_root.piar_lock); 293 spin_lock_init(&pci_io_addr_cache_root.piar_lock);
@@ -294,8 +298,14 @@ void __init pci_addr_cache_build(void)
294 dn = pci_device_to_OF_node(dev); 298 dn = pci_device_to_OF_node(dev);
295 if (!dn) 299 if (!dn)
296 continue; 300 continue;
301
302 edev = of_node_to_eeh_dev(dn);
303 if (!edev)
304 continue;
305
297 pci_dev_get(dev); /* matching put is in eeh_remove_device() */ 306 pci_dev_get(dev); /* matching put is in eeh_remove_device() */
298 PCI_DN(dn)->pcidev = dev; 307 dev->dev.archdata.edev = edev;
308 edev->pdev = dev;
299 309
300 eeh_sysfs_add_device(dev); 310 eeh_sysfs_add_device(dev);
301 } 311 }
diff --git a/arch/powerpc/platforms/pseries/eeh_dev.c b/arch/powerpc/platforms/pseries/eeh_dev.c
new file mode 100644
index 000000000000..f3aed7dcae95
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_dev.c
@@ -0,0 +1,102 @@
1/*
2 * The file intends to implement dynamic creation of EEH device, which will
3 * be bound with OF node and PCI device simutaneously. The EEH devices would
4 * be foundamental information for EEH core components to work proerly. Besides,
5 * We have to support multiple situations where dynamic creation of EEH device
6 * is required:
7 *
8 * 1) Before PCI emunation starts, we need create EEH devices according to the
9 * PCI sensitive OF nodes.
10 * 2) When PCI emunation is done, we need do the binding between PCI device and
11 * the associated EEH device.
12 * 3) DR (Dynamic Reconfiguration) would create PCI sensitive OF node. EEH device
13 * will be created while PCI sensitive OF node is detected from DR.
14 * 4) PCI hotplug needs redoing the binding between PCI device and EEH device. If
15 * PHB is newly inserted, we also need create EEH devices accordingly.
16 *
17 * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2012.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#include <linux/export.h>
35#include <linux/gfp.h>
36#include <linux/init.h>
37#include <linux/kernel.h>
38#include <linux/pci.h>
39#include <linux/string.h>
40
41#include <asm/pci-bridge.h>
42#include <asm/ppc-pci.h>
43
44/**
45 * eeh_dev_init - Create EEH device according to OF node
46 * @dn: device node
47 * @data: PHB
48 *
49 * It will create EEH device according to the given OF node. The function
50 * might be called by PCI emunation, DR, PHB hotplug.
51 */
52void * __devinit eeh_dev_init(struct device_node *dn, void *data)
53{
54 struct pci_controller *phb = data;
55 struct eeh_dev *edev;
56
57 /* Allocate EEH device */
58 edev = zalloc_maybe_bootmem(sizeof(*edev), GFP_KERNEL);
59 if (!edev) {
60 pr_warning("%s: out of memory\n", __func__);
61 return NULL;
62 }
63
64 /* Associate EEH device with OF node */
65 dn->edev = edev;
66 edev->dn = dn;
67 edev->phb = phb;
68
69 return NULL;
70}
71
72/**
73 * eeh_dev_phb_init_dynamic - Create EEH devices for devices included in PHB
74 * @phb: PHB
75 *
76 * Scan the PHB OF node and its child association, then create the
77 * EEH devices accordingly
78 */
79void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
80{
81 struct device_node *dn = phb->dn;
82
83 /* EEH device for PHB */
84 eeh_dev_init(dn, phb);
85
86 /* EEH devices for children OF nodes */
87 traverse_pci_devices(dn, eeh_dev_init, phb);
88}
89
90/**
91 * eeh_dev_phb_init - Create EEH devices for devices included in existing PHBs
92 *
93 * Scan all the existing PHBs and create EEH devices for their OF
94 * nodes and their children OF nodes
95 */
96void __init eeh_dev_phb_init(void)
97{
98 struct pci_controller *phb, *tmp;
99
100 list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
101 eeh_dev_phb_init_dynamic(phb);
102}
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 1b6cb10589e0..baf92cd9dfab 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -33,8 +33,14 @@
33#include <asm/prom.h> 33#include <asm/prom.h>
34#include <asm/rtas.h> 34#include <asm/rtas.h>
35 35
36 36/**
37static inline const char * pcid_name (struct pci_dev *pdev) 37 * eeh_pcid_name - Retrieve name of PCI device driver
38 * @pdev: PCI device
39 *
40 * This routine is used to retrieve the name of PCI device driver
41 * if that's valid.
42 */
43static inline const char *eeh_pcid_name(struct pci_dev *pdev)
38{ 44{
39 if (pdev && pdev->dev.driver) 45 if (pdev && pdev->dev.driver)
40 return pdev->dev.driver->name; 46 return pdev->dev.driver->name;
@@ -64,48 +70,59 @@ static void print_device_node_tree(struct pci_dn *pdn, int dent)
64#endif 70#endif
65 71
66/** 72/**
67 * eeh_disable_irq - disable interrupt for the recovering device 73 * eeh_disable_irq - Disable interrupt for the recovering device
74 * @dev: PCI device
75 *
76 * This routine must be called when reporting temporary or permanent
77 * error to the particular PCI device to disable interrupt of that
78 * device. If the device has enabled MSI or MSI-X interrupt, we needn't
79 * do real work because EEH should freeze DMA transfers for those PCI
80 * devices encountering EEH errors, which includes MSI or MSI-X.
68 */ 81 */
69static void eeh_disable_irq(struct pci_dev *dev) 82static void eeh_disable_irq(struct pci_dev *dev)
70{ 83{
71 struct device_node *dn = pci_device_to_OF_node(dev); 84 struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
72 85
73 /* Don't disable MSI and MSI-X interrupts. They are 86 /* Don't disable MSI and MSI-X interrupts. They are
74 * effectively disabled by the DMA Stopped state 87 * effectively disabled by the DMA Stopped state
75 * when an EEH error occurs. 88 * when an EEH error occurs.
76 */ 89 */
77 if (dev->msi_enabled || dev->msix_enabled) 90 if (dev->msi_enabled || dev->msix_enabled)
78 return; 91 return;
79 92
80 if (!irq_has_action(dev->irq)) 93 if (!irq_has_action(dev->irq))
81 return; 94 return;
82 95
83 PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED; 96 edev->mode |= EEH_MODE_IRQ_DISABLED;
84 disable_irq_nosync(dev->irq); 97 disable_irq_nosync(dev->irq);
85} 98}
86 99
87/** 100/**
88 * eeh_enable_irq - enable interrupt for the recovering device 101 * eeh_enable_irq - Enable interrupt for the recovering device
102 * @dev: PCI device
103 *
104 * This routine must be called to enable interrupt while failed
105 * device could be resumed.
89 */ 106 */
90static void eeh_enable_irq(struct pci_dev *dev) 107static void eeh_enable_irq(struct pci_dev *dev)
91{ 108{
92 struct device_node *dn = pci_device_to_OF_node(dev); 109 struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
93 110
94 if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) { 111 if ((edev->mode) & EEH_MODE_IRQ_DISABLED) {
95 PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED; 112 edev->mode &= ~EEH_MODE_IRQ_DISABLED;
96 enable_irq(dev->irq); 113 enable_irq(dev->irq);
97 } 114 }
98} 115}
99 116
100/* ------------------------------------------------------- */
101/** 117/**
102 * eeh_report_error - report pci error to each device driver 118 * eeh_report_error - Report pci error to each device driver
119 * @dev: PCI device
120 * @userdata: return value
103 * 121 *
104 * Report an EEH error to each device driver, collect up and 122 * Report an EEH error to each device driver, collect up and
105 * merge the device driver responses. Cumulative response 123 * merge the device driver responses. Cumulative response
106 * passed back in "userdata". 124 * passed back in "userdata".
107 */ 125 */
108
109static int eeh_report_error(struct pci_dev *dev, void *userdata) 126static int eeh_report_error(struct pci_dev *dev, void *userdata)
110{ 127{
111 enum pci_ers_result rc, *res = userdata; 128 enum pci_ers_result rc, *res = userdata;
@@ -122,7 +139,7 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata)
122 !driver->err_handler->error_detected) 139 !driver->err_handler->error_detected)
123 return 0; 140 return 0;
124 141
125 rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); 142 rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
126 143
127 /* A driver that needs a reset trumps all others */ 144 /* A driver that needs a reset trumps all others */
128 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; 145 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
@@ -132,13 +149,14 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata)
132} 149}
133 150
134/** 151/**
135 * eeh_report_mmio_enabled - tell drivers that MMIO has been enabled 152 * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled
153 * @dev: PCI device
154 * @userdata: return value
136 * 155 *
137 * Tells each device driver that IO ports, MMIO and config space I/O 156 * Tells each device driver that IO ports, MMIO and config space I/O
138 * are now enabled. Collects up and merges the device driver responses. 157 * are now enabled. Collects up and merges the device driver responses.
139 * Cumulative response passed back in "userdata". 158 * Cumulative response passed back in "userdata".
140 */ 159 */
141
142static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) 160static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
143{ 161{
144 enum pci_ers_result rc, *res = userdata; 162 enum pci_ers_result rc, *res = userdata;
@@ -149,7 +167,7 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
149 !driver->err_handler->mmio_enabled) 167 !driver->err_handler->mmio_enabled)
150 return 0; 168 return 0;
151 169
152 rc = driver->err_handler->mmio_enabled (dev); 170 rc = driver->err_handler->mmio_enabled(dev);
153 171
154 /* A driver that needs a reset trumps all others */ 172 /* A driver that needs a reset trumps all others */
155 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; 173 if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
@@ -159,9 +177,15 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
159} 177}
160 178
161/** 179/**
162 * eeh_report_reset - tell device that slot has been reset 180 * eeh_report_reset - Tell device that slot has been reset
181 * @dev: PCI device
182 * @userdata: return value
183 *
184 * This routine must be called while EEH tries to reset particular
185 * PCI device so that the associated PCI device driver could take
186 * some actions, usually to save data the driver needs so that the
187 * driver can work again while the device is recovered.
163 */ 188 */
164
165static int eeh_report_reset(struct pci_dev *dev, void *userdata) 189static int eeh_report_reset(struct pci_dev *dev, void *userdata)
166{ 190{
167 enum pci_ers_result rc, *res = userdata; 191 enum pci_ers_result rc, *res = userdata;
@@ -188,9 +212,14 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata)
188} 212}
189 213
190/** 214/**
191 * eeh_report_resume - tell device to resume normal operations 215 * eeh_report_resume - Tell device to resume normal operations
216 * @dev: PCI device
217 * @userdata: return value
218 *
219 * This routine must be called to notify the device driver that it
220 * could resume so that the device driver can do some initialization
221 * to make the recovered device work again.
192 */ 222 */
193
194static int eeh_report_resume(struct pci_dev *dev, void *userdata) 223static int eeh_report_resume(struct pci_dev *dev, void *userdata)
195{ 224{
196 struct pci_driver *driver = dev->driver; 225 struct pci_driver *driver = dev->driver;
@@ -212,12 +241,13 @@ static int eeh_report_resume(struct pci_dev *dev, void *userdata)
212} 241}
213 242
214/** 243/**
215 * eeh_report_failure - tell device driver that device is dead. 244 * eeh_report_failure - Tell device driver that device is dead.
245 * @dev: PCI device
246 * @userdata: return value
216 * 247 *
217 * This informs the device driver that the device is permanently 248 * This informs the device driver that the device is permanently
218 * dead, and that no further recovery attempts will be made on it. 249 * dead, and that no further recovery attempts will be made on it.
219 */ 250 */
220
221static int eeh_report_failure(struct pci_dev *dev, void *userdata) 251static int eeh_report_failure(struct pci_dev *dev, void *userdata)
222{ 252{
223 struct pci_driver *driver = dev->driver; 253 struct pci_driver *driver = dev->driver;
@@ -238,65 +268,46 @@ static int eeh_report_failure(struct pci_dev *dev, void *userdata)
238 return 0; 268 return 0;
239} 269}
240 270
241/* ------------------------------------------------------- */
242/** 271/**
243 * handle_eeh_events -- reset a PCI device after hard lockup. 272 * eeh_reset_device - Perform actual reset of a pci slot
244 * 273 * @edev: PE associated EEH device
245 * pSeries systems will isolate a PCI slot if the PCI-Host 274 * @bus: PCI bus corresponding to the isolcated slot
246 * bridge detects address or data parity errors, DMA's
247 * occurring to wild addresses (which usually happen due to
248 * bugs in device drivers or in PCI adapter firmware).
249 * Slot isolations also occur if #SERR, #PERR or other misc
250 * PCI-related errors are detected.
251 * 275 *
252 * Recovery process consists of unplugging the device driver 276 * This routine must be called to do reset on the indicated PE.
253 * (which generated hotplug events to userspace), then issuing 277 * During the reset, udev might be invoked because those affected
254 * a PCI #RST to the device, then reconfiguring the PCI config 278 * PCI devices will be removed and then added.
255 * space for all bridges & devices under this slot, and then
256 * finally restarting the device drivers (which cause a second
257 * set of hotplug events to go out to userspace).
258 */ 279 */
259 280static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
260/**
261 * eeh_reset_device() -- perform actual reset of a pci slot
262 * @bus: pointer to the pci bus structure corresponding
263 * to the isolated slot. A non-null value will
264 * cause all devices under the bus to be removed
265 * and then re-added.
266 * @pe_dn: pointer to a "Partionable Endpoint" device node.
267 * This is the top-level structure on which pci
268 * bus resets can be performed.
269 */
270
271static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
272{ 281{
273 struct device_node *dn; 282 struct device_node *dn;
274 int cnt, rc; 283 int cnt, rc;
275 284
276 /* pcibios will clear the counter; save the value */ 285 /* pcibios will clear the counter; save the value */
277 cnt = pe_dn->eeh_freeze_count; 286 cnt = edev->freeze_count;
278 287
279 if (bus) 288 if (bus)
280 pcibios_remove_pci_devices(bus); 289 pcibios_remove_pci_devices(bus);
281 290
282 /* Reset the pci controller. (Asserts RST#; resets config space). 291 /* Reset the pci controller. (Asserts RST#; resets config space).
283 * Reconfigure bridges and devices. Don't try to bring the system 292 * Reconfigure bridges and devices. Don't try to bring the system
284 * up if the reset failed for some reason. */ 293 * up if the reset failed for some reason.
285 rc = rtas_set_slot_reset(pe_dn); 294 */
295 rc = eeh_reset_pe(edev);
286 if (rc) 296 if (rc)
287 return rc; 297 return rc;
288 298
289 /* Walk over all functions on this device. */ 299 /* Walk over all functions on this device. */
290 dn = pe_dn->node; 300 dn = eeh_dev_to_of_node(edev);
291 if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent)) 301 if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
292 dn = dn->parent->child; 302 dn = dn->parent->child;
293 303
294 while (dn) { 304 while (dn) {
295 struct pci_dn *ppe = PCI_DN(dn); 305 struct eeh_dev *pedev = of_node_to_eeh_dev(dn);
306
296 /* On Power4, always true because eeh_pe_config_addr=0 */ 307 /* On Power4, always true because eeh_pe_config_addr=0 */
297 if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { 308 if (edev->pe_config_addr == pedev->pe_config_addr) {
298 rtas_configure_bridge(ppe); 309 eeh_ops->configure_bridge(dn);
299 eeh_restore_bars(ppe); 310 eeh_restore_bars(pedev);
300 } 311 }
301 dn = dn->sibling; 312 dn = dn->sibling;
302 } 313 }
@@ -308,10 +319,10 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
308 * potentially weird things happen. 319 * potentially weird things happen.
309 */ 320 */
310 if (bus) { 321 if (bus) {
311 ssleep (5); 322 ssleep(5);
312 pcibios_add_pci_devices(bus); 323 pcibios_add_pci_devices(bus);
313 } 324 }
314 pe_dn->eeh_freeze_count = cnt; 325 edev->freeze_count = cnt;
315 326
316 return 0; 327 return 0;
317} 328}
@@ -321,23 +332,39 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
321 */ 332 */
322#define MAX_WAIT_FOR_RECOVERY 150 333#define MAX_WAIT_FOR_RECOVERY 150
323 334
324struct pci_dn * handle_eeh_events (struct eeh_event *event) 335/**
336 * eeh_handle_event - Reset a PCI device after hard lockup.
337 * @event: EEH event
338 *
339 * While PHB detects address or data parity errors on particular PCI
340 * slot, the associated PE will be frozen. Besides, DMA's occurring
341 * to wild addresses (which usually happen due to bugs in device
342 * drivers or in PCI adapter firmware) can cause EEH error. #SERR,
343 * #PERR or other misc PCI-related errors also can trigger EEH errors.
344 *
345 * Recovery process consists of unplugging the device driver (which
346 * generated hotplug events to userspace), then issuing a PCI #RST to
347 * the device, then reconfiguring the PCI config space for all bridges
348 * & devices under this slot, and then finally restarting the device
349 * drivers (which cause a second set of hotplug events to go out to
350 * userspace).
351 */
352struct eeh_dev *handle_eeh_events(struct eeh_event *event)
325{ 353{
326 struct device_node *frozen_dn; 354 struct device_node *frozen_dn;
327 struct pci_dn *frozen_pdn; 355 struct eeh_dev *frozen_edev;
328 struct pci_bus *frozen_bus; 356 struct pci_bus *frozen_bus;
329 int rc = 0; 357 int rc = 0;
330 enum pci_ers_result result = PCI_ERS_RESULT_NONE; 358 enum pci_ers_result result = PCI_ERS_RESULT_NONE;
331 const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str; 359 const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;
332 360
333 frozen_dn = find_device_pe(event->dn); 361 frozen_dn = eeh_find_device_pe(eeh_dev_to_of_node(event->edev));
334 if (!frozen_dn) { 362 if (!frozen_dn) {
335 363 location = of_get_property(eeh_dev_to_of_node(event->edev), "ibm,loc-code", NULL);
336 location = of_get_property(event->dn, "ibm,loc-code", NULL);
337 location = location ? location : "unknown"; 364 location = location ? location : "unknown";
338 printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " 365 printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
339 "for location=%s pci addr=%s\n", 366 "for location=%s pci addr=%s\n",
340 location, eeh_pci_name(event->dev)); 367 location, eeh_pci_name(eeh_dev_to_pci_dev(event->edev)));
341 return NULL; 368 return NULL;
342 } 369 }
343 370
@@ -350,9 +377,10 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
350 * which was always an EADS pci bridge. In the new style, 377 * which was always an EADS pci bridge. In the new style,
351 * there might not be any EADS bridges, and even when there are, 378 * there might not be any EADS bridges, and even when there are,
352 * the firmware marks them as "EEH incapable". So another 379 * the firmware marks them as "EEH incapable". So another
353 * two-step is needed to find the pci bus.. */ 380 * two-step is needed to find the pci bus..
381 */
354 if (!frozen_bus) 382 if (!frozen_bus)
355 frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); 383 frozen_bus = pcibios_find_pci_bus(frozen_dn->parent);
356 384
357 if (!frozen_bus) { 385 if (!frozen_bus) {
358 printk(KERN_ERR "EEH: Cannot find PCI bus " 386 printk(KERN_ERR "EEH: Cannot find PCI bus "
@@ -361,22 +389,21 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
361 return NULL; 389 return NULL;
362 } 390 }
363 391
364 frozen_pdn = PCI_DN(frozen_dn); 392 frozen_edev = of_node_to_eeh_dev(frozen_dn);
365 frozen_pdn->eeh_freeze_count++; 393 frozen_edev->freeze_count++;
394 pci_str = eeh_pci_name(eeh_dev_to_pci_dev(event->edev));
395 drv_str = eeh_pcid_name(eeh_dev_to_pci_dev(event->edev));
366 396
367 pci_str = eeh_pci_name(event->dev); 397 if (frozen_edev->freeze_count > EEH_MAX_ALLOWED_FREEZES)
368 drv_str = pcid_name(event->dev);
369
370 if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
371 goto excess_failures; 398 goto excess_failures;
372 399
373 printk(KERN_WARNING 400 printk(KERN_WARNING
374 "EEH: This PCI device has failed %d times in the last hour:\n", 401 "EEH: This PCI device has failed %d times in the last hour:\n",
375 frozen_pdn->eeh_freeze_count); 402 frozen_edev->freeze_count);
376 403
377 if (frozen_pdn->pcidev) { 404 if (frozen_edev->pdev) {
378 bus_pci_str = pci_name(frozen_pdn->pcidev); 405 bus_pci_str = pci_name(frozen_edev->pdev);
379 bus_drv_str = pcid_name(frozen_pdn->pcidev); 406 bus_drv_str = eeh_pcid_name(frozen_edev->pdev);
380 printk(KERN_WARNING 407 printk(KERN_WARNING
381 "EEH: Bus location=%s driver=%s pci addr=%s\n", 408 "EEH: Bus location=%s driver=%s pci addr=%s\n",
382 location, bus_drv_str, bus_pci_str); 409 location, bus_drv_str, bus_pci_str);
@@ -395,9 +422,10 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
395 pci_walk_bus(frozen_bus, eeh_report_error, &result); 422 pci_walk_bus(frozen_bus, eeh_report_error, &result);
396 423
397 /* Get the current PCI slot state. This can take a long time, 424 /* Get the current PCI slot state. This can take a long time,
398 * sometimes over 3 seconds for certain systems. */ 425 * sometimes over 3 seconds for certain systems.
399 rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000); 426 */
400 if (rc < 0) { 427 rc = eeh_ops->wait_state(eeh_dev_to_of_node(frozen_edev), MAX_WAIT_FOR_RECOVERY*1000);
428 if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {
401 printk(KERN_WARNING "EEH: Permanent failure\n"); 429 printk(KERN_WARNING "EEH: Permanent failure\n");
402 goto hard_fail; 430 goto hard_fail;
403 } 431 }
@@ -406,14 +434,14 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
406 * don't post the error log until after all dev drivers 434 * don't post the error log until after all dev drivers
407 * have been informed. 435 * have been informed.
408 */ 436 */
409 eeh_slot_error_detail(frozen_pdn, EEH_LOG_TEMP_FAILURE); 437 eeh_slot_error_detail(frozen_edev, EEH_LOG_TEMP);
410 438
411 /* If all device drivers were EEH-unaware, then shut 439 /* If all device drivers were EEH-unaware, then shut
412 * down all of the device drivers, and hope they 440 * down all of the device drivers, and hope they
413 * go down willingly, without panicing the system. 441 * go down willingly, without panicing the system.
414 */ 442 */
415 if (result == PCI_ERS_RESULT_NONE) { 443 if (result == PCI_ERS_RESULT_NONE) {
416 rc = eeh_reset_device(frozen_pdn, frozen_bus); 444 rc = eeh_reset_device(frozen_edev, frozen_bus);
417 if (rc) { 445 if (rc) {
418 printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc); 446 printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc);
419 goto hard_fail; 447 goto hard_fail;
@@ -422,7 +450,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
422 450
423 /* If all devices reported they can proceed, then re-enable MMIO */ 451 /* If all devices reported they can proceed, then re-enable MMIO */
424 if (result == PCI_ERS_RESULT_CAN_RECOVER) { 452 if (result == PCI_ERS_RESULT_CAN_RECOVER) {
425 rc = rtas_pci_enable(frozen_pdn, EEH_THAW_MMIO); 453 rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_MMIO);
426 454
427 if (rc < 0) 455 if (rc < 0)
428 goto hard_fail; 456 goto hard_fail;
@@ -436,7 +464,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
436 464
437 /* If all devices reported they can proceed, then re-enable DMA */ 465 /* If all devices reported they can proceed, then re-enable DMA */
438 if (result == PCI_ERS_RESULT_CAN_RECOVER) { 466 if (result == PCI_ERS_RESULT_CAN_RECOVER) {
439 rc = rtas_pci_enable(frozen_pdn, EEH_THAW_DMA); 467 rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_DMA);
440 468
441 if (rc < 0) 469 if (rc < 0)
442 goto hard_fail; 470 goto hard_fail;
@@ -454,7 +482,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
454 482
455 /* If any device called out for a reset, then reset the slot */ 483 /* If any device called out for a reset, then reset the slot */
456 if (result == PCI_ERS_RESULT_NEED_RESET) { 484 if (result == PCI_ERS_RESULT_NEED_RESET) {
457 rc = eeh_reset_device(frozen_pdn, NULL); 485 rc = eeh_reset_device(frozen_edev, NULL);
458 if (rc) { 486 if (rc) {
459 printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc); 487 printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc);
460 goto hard_fail; 488 goto hard_fail;
@@ -473,7 +501,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
473 /* Tell all device drivers that they can resume operations */ 501 /* Tell all device drivers that they can resume operations */
474 pci_walk_bus(frozen_bus, eeh_report_resume, NULL); 502 pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
475 503
476 return frozen_pdn; 504 return frozen_edev;
477 505
478excess_failures: 506excess_failures:
479 /* 507 /*
@@ -486,7 +514,7 @@ excess_failures:
486 "has failed %d times in the last hour " 514 "has failed %d times in the last hour "
487 "and has been permanently disabled.\n" 515 "and has been permanently disabled.\n"
488 "Please try reseating this device or replacing it.\n", 516 "Please try reseating this device or replacing it.\n",
489 location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); 517 location, drv_str, pci_str, frozen_edev->freeze_count);
490 goto perm_error; 518 goto perm_error;
491 519
492hard_fail: 520hard_fail:
@@ -497,7 +525,7 @@ hard_fail:
497 location, drv_str, pci_str); 525 location, drv_str, pci_str);
498 526
499perm_error: 527perm_error:
500 eeh_slot_error_detail(frozen_pdn, EEH_LOG_PERM_FAILURE); 528 eeh_slot_error_detail(frozen_edev, EEH_LOG_PERM);
501 529
502 /* Notify all devices that they're about to go down. */ 530 /* Notify all devices that they're about to go down. */
503 pci_walk_bus(frozen_bus, eeh_report_failure, NULL); 531 pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
@@ -508,4 +536,3 @@ perm_error:
508 return NULL; 536 return NULL;
509} 537}
510 538
511/* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index d2383cfb6dfd..4a4752565856 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * eeh_event.c
3 *
4 * This program is free software; you can redistribute it and/or modify 2 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 3 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or 4 * the Free Software Foundation; either version 2 of the License, or
@@ -46,7 +44,7 @@ DECLARE_WORK(eeh_event_wq, eeh_thread_launcher);
46DEFINE_MUTEX(eeh_event_mutex); 44DEFINE_MUTEX(eeh_event_mutex);
47 45
48/** 46/**
49 * eeh_event_handler - dispatch EEH events. 47 * eeh_event_handler - Dispatch EEH events.
50 * @dummy - unused 48 * @dummy - unused
51 * 49 *
52 * The detection of a frozen slot can occur inside an interrupt, 50 * The detection of a frozen slot can occur inside an interrupt,
@@ -58,10 +56,10 @@ DEFINE_MUTEX(eeh_event_mutex);
58static int eeh_event_handler(void * dummy) 56static int eeh_event_handler(void * dummy)
59{ 57{
60 unsigned long flags; 58 unsigned long flags;
61 struct eeh_event *event; 59 struct eeh_event *event;
62 struct pci_dn *pdn; 60 struct eeh_dev *edev;
63 61
64 daemonize ("eehd"); 62 daemonize("eehd");
65 set_current_state(TASK_INTERRUPTIBLE); 63 set_current_state(TASK_INTERRUPTIBLE);
66 64
67 spin_lock_irqsave(&eeh_eventlist_lock, flags); 65 spin_lock_irqsave(&eeh_eventlist_lock, flags);
@@ -79,31 +77,37 @@ static int eeh_event_handler(void * dummy)
79 77
80 /* Serialize processing of EEH events */ 78 /* Serialize processing of EEH events */
81 mutex_lock(&eeh_event_mutex); 79 mutex_lock(&eeh_event_mutex);
82 eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); 80 edev = event->edev;
81 eeh_mark_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
83 82
84 printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", 83 printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
85 eeh_pci_name(event->dev)); 84 eeh_pci_name(edev->pdev));
85
86 edev = handle_eeh_events(event);
86 87
87 pdn = handle_eeh_events(event); 88 eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
89 pci_dev_put(edev->pdev);
88 90
89 eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
90 pci_dev_put(event->dev);
91 kfree(event); 91 kfree(event);
92 mutex_unlock(&eeh_event_mutex); 92 mutex_unlock(&eeh_event_mutex);
93 93
94 /* If there are no new errors after an hour, clear the counter. */ 94 /* If there are no new errors after an hour, clear the counter. */
95 if (pdn && pdn->eeh_freeze_count>0) { 95 if (edev && edev->freeze_count>0) {
96 msleep_interruptible (3600*1000); 96 msleep_interruptible(3600*1000);
97 if (pdn->eeh_freeze_count>0) 97 if (edev->freeze_count>0)
98 pdn->eeh_freeze_count--; 98 edev->freeze_count--;
99
99 } 100 }
100 101
101 return 0; 102 return 0;
102} 103}
103 104
104/** 105/**
105 * eeh_thread_launcher 106 * eeh_thread_launcher - Start kernel thread to handle EEH events
106 * @dummy - unused 107 * @dummy - unused
108 *
109 * This routine is called to start the kernel thread for processing
110 * EEH event.
107 */ 111 */
108static void eeh_thread_launcher(struct work_struct *dummy) 112static void eeh_thread_launcher(struct work_struct *dummy)
109{ 113{
@@ -112,18 +116,18 @@ static void eeh_thread_launcher(struct work_struct *dummy)
112} 116}
113 117
114/** 118/**
115 * eeh_send_failure_event - generate a PCI error event 119 * eeh_send_failure_event - Generate a PCI error event
116 * @dev pci device 120 * @edev: EEH device
117 * 121 *
118 * This routine can be called within an interrupt context; 122 * This routine can be called within an interrupt context;
119 * the actual event will be delivered in a normal context 123 * the actual event will be delivered in a normal context
120 * (from a workqueue). 124 * (from a workqueue).
121 */ 125 */
122int eeh_send_failure_event (struct device_node *dn, 126int eeh_send_failure_event(struct eeh_dev *edev)
123 struct pci_dev *dev)
124{ 127{
125 unsigned long flags; 128 unsigned long flags;
126 struct eeh_event *event; 129 struct eeh_event *event;
130 struct device_node *dn = eeh_dev_to_of_node(edev);
127 const char *location; 131 const char *location;
128 132
129 if (!mem_init_done) { 133 if (!mem_init_done) {
@@ -135,15 +139,14 @@ int eeh_send_failure_event (struct device_node *dn,
135 } 139 }
136 event = kmalloc(sizeof(*event), GFP_ATOMIC); 140 event = kmalloc(sizeof(*event), GFP_ATOMIC);
137 if (event == NULL) { 141 if (event == NULL) {
138 printk (KERN_ERR "EEH: out of memory, event not handled\n"); 142 printk(KERN_ERR "EEH: out of memory, event not handled\n");
139 return 1; 143 return 1;
140 } 144 }
141 145
142 if (dev) 146 if (edev->pdev)
143 pci_dev_get(dev); 147 pci_dev_get(edev->pdev);
144 148
145 event->dn = dn; 149 event->edev = edev;
146 event->dev = dev;
147 150
148 /* We may or may not be called in an interrupt context */ 151 /* We may or may not be called in an interrupt context */
149 spin_lock_irqsave(&eeh_eventlist_lock, flags); 152 spin_lock_irqsave(&eeh_eventlist_lock, flags);
@@ -154,5 +157,3 @@ int eeh_send_failure_event (struct device_node *dn,
154 157
155 return 0; 158 return 0;
156} 159}
157
158/********************** END OF FILE ******************************/
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
new file mode 100644
index 000000000000..8752f79a6af8
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -0,0 +1,565 @@
1/*
2 * The file intends to implement the platform dependent EEH operations on pseries.
3 * Actually, the pseries platform is built based on RTAS heavily. That means the
4 * pseries platform dependent EEH operations will be built on RTAS calls. The functions
5 * are devired from arch/powerpc/platforms/pseries/eeh.c and necessary cleanup has
6 * been done.
7 *
8 * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2011.
9 * Copyright IBM Corporation 2001, 2005, 2006
10 * Copyright Dave Engebretsen & Todd Inglett 2001
11 * Copyright Linas Vepstas 2005, 2006
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28#include <linux/atomic.h>
29#include <linux/delay.h>
30#include <linux/export.h>
31#include <linux/init.h>
32#include <linux/list.h>
33#include <linux/of.h>
34#include <linux/pci.h>
35#include <linux/proc_fs.h>
36#include <linux/rbtree.h>
37#include <linux/sched.h>
38#include <linux/seq_file.h>
39#include <linux/spinlock.h>
40
41#include <asm/eeh.h>
42#include <asm/eeh_event.h>
43#include <asm/io.h>
44#include <asm/machdep.h>
45#include <asm/ppc-pci.h>
46#include <asm/rtas.h>
47
48/* RTAS tokens */
49static int ibm_set_eeh_option;
50static int ibm_set_slot_reset;
51static int ibm_read_slot_reset_state;
52static int ibm_read_slot_reset_state2;
53static int ibm_slot_error_detail;
54static int ibm_get_config_addr_info;
55static int ibm_get_config_addr_info2;
56static int ibm_configure_bridge;
57static int ibm_configure_pe;
58
59/*
60 * Buffer for reporting slot-error-detail rtas calls. Its here
61 * in BSS, and not dynamically alloced, so that it ends up in
62 * RMO where RTAS can access it.
63 */
64static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
65static DEFINE_SPINLOCK(slot_errbuf_lock);
66static int eeh_error_buf_size;
67
68/**
69 * pseries_eeh_init - EEH platform dependent initialization
70 *
71 * EEH platform dependent initialization on pseries.
72 */
73static int pseries_eeh_init(void)
74{
75 /* figure out EEH RTAS function call tokens */
76 ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
77 ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
78 ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");
79 ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
80 ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
81 ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
82 ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
83 ibm_configure_pe = rtas_token("ibm,configure-pe");
84 ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
85
86 /* necessary sanity check */
87 if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
88 pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n",
89 __func__);
90 return -EINVAL;
91 } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {
92 pr_warning("%s: RTAS service <ibm, set-slot-reset> invalid\n",
93 __func__);
94 return -EINVAL;
95 } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
96 ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) {
97 pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and "
98 "<ibm,read-slot-reset-state> invalid\n",
99 __func__);
100 return -EINVAL;
101 } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) {
102 pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n",
103 __func__);
104 return -EINVAL;
105 } else if (ibm_get_config_addr_info2 == RTAS_UNKNOWN_SERVICE &&
106 ibm_get_config_addr_info == RTAS_UNKNOWN_SERVICE) {
107 pr_warning("%s: RTAS service <ibm,get-config-addr-info2> and "
108 "<ibm,get-config-addr-info> invalid\n",
109 __func__);
110 return -EINVAL;
111 } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
112 ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) {
113 pr_warning("%s: RTAS service <ibm,configure-pe> and "
114 "<ibm,configure-bridge> invalid\n",
115 __func__);
116 return -EINVAL;
117 }
118
119 /* Initialize error log lock and size */
120 spin_lock_init(&slot_errbuf_lock);
121 eeh_error_buf_size = rtas_token("rtas-error-log-max");
122 if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) {
123 pr_warning("%s: unknown EEH error log size\n",
124 __func__);
125 eeh_error_buf_size = 1024;
126 } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
127 pr_warning("%s: EEH error log size %d exceeds the maximal %d\n",
128 __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX);
129 eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
130 }
131
132 return 0;
133}
134
135/**
136 * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
137 * @dn: device node
138 * @option: operation to be issued
139 *
140 * The function is used to control the EEH functionality globally.
141 * Currently, following options are support according to PAPR:
142 * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
143 */
144static int pseries_eeh_set_option(struct device_node *dn, int option)
145{
146 int ret = 0;
147 struct eeh_dev *edev;
148 const u32 *reg;
149 int config_addr;
150
151 edev = of_node_to_eeh_dev(dn);
152
153 /*
154 * When we're enabling or disabling EEH functioality on
155 * the particular PE, the PE config address is possibly
156 * unavailable. Therefore, we have to figure it out from
157 * the FDT node.
158 */
159 switch (option) {
160 case EEH_OPT_DISABLE:
161 case EEH_OPT_ENABLE:
162 reg = of_get_property(dn, "reg", NULL);
163 config_addr = reg[0];
164 break;
165
166 case EEH_OPT_THAW_MMIO:
167 case EEH_OPT_THAW_DMA:
168 config_addr = edev->config_addr;
169 if (edev->pe_config_addr)
170 config_addr = edev->pe_config_addr;
171 break;
172
173 default:
174 pr_err("%s: Invalid option %d\n",
175 __func__, option);
176 return -EINVAL;
177 }
178
179 ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
180 config_addr, BUID_HI(edev->phb->buid),
181 BUID_LO(edev->phb->buid), option);
182
183 return ret;
184}
185
186/**
187 * pseries_eeh_get_pe_addr - Retrieve PE address
188 * @dn: device node
189 *
190 * Retrieve the assocated PE address. Actually, there're 2 RTAS
191 * function calls dedicated for the purpose. We need implement
192 * it through the new function and then the old one. Besides,
193 * you should make sure the config address is figured out from
194 * FDT node before calling the function.
195 *
196 * It's notable that zero'ed return value means invalid PE config
197 * address.
198 */
199static int pseries_eeh_get_pe_addr(struct device_node *dn)
200{
201 struct eeh_dev *edev;
202 int ret = 0;
203 int rets[3];
204
205 edev = of_node_to_eeh_dev(dn);
206
207 if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
208 /*
209 * First of all, we need to make sure there has one PE
210 * associated with the device. Otherwise, PE address is
211 * meaningless.
212 */
213 ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
214 edev->config_addr, BUID_HI(edev->phb->buid),
215 BUID_LO(edev->phb->buid), 1);
216 if (ret || (rets[0] == 0))
217 return 0;
218
219 /* Retrieve the associated PE config address */
220 ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
221 edev->config_addr, BUID_HI(edev->phb->buid),
222 BUID_LO(edev->phb->buid), 0);
223 if (ret) {
224 pr_warning("%s: Failed to get PE address for %s\n",
225 __func__, dn->full_name);
226 return 0;
227 }
228
229 return rets[0];
230 }
231
232 if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
233 ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets,
234 edev->config_addr, BUID_HI(edev->phb->buid),
235 BUID_LO(edev->phb->buid), 0);
236 if (ret) {
237 pr_warning("%s: Failed to get PE address for %s\n",
238 __func__, dn->full_name);
239 return 0;
240 }
241
242 return rets[0];
243 }
244
245 return ret;
246}
247
248/**
249 * pseries_eeh_get_state - Retrieve PE state
250 * @dn: PE associated device node
251 * @state: return value
252 *
253 * Retrieve the state of the specified PE. On RTAS compliant
254 * pseries platform, there already has one dedicated RTAS function
255 * for the purpose. It's notable that the associated PE config address
256 * might be ready when calling the function. Therefore, endeavour to
257 * use the PE config address if possible. Further more, there're 2
258 * RTAS calls for the purpose, we need to try the new one and back
259 * to the old one if the new one couldn't work properly.
260 */
261static int pseries_eeh_get_state(struct device_node *dn, int *state)
262{
263 struct eeh_dev *edev;
264 int config_addr;
265 int ret;
266 int rets[4];
267 int result;
268
269 /* Figure out PE config address if possible */
270 edev = of_node_to_eeh_dev(dn);
271 config_addr = edev->config_addr;
272 if (edev->pe_config_addr)
273 config_addr = edev->pe_config_addr;
274
275 if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
276 ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets,
277 config_addr, BUID_HI(edev->phb->buid),
278 BUID_LO(edev->phb->buid));
279 } else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) {
280 /* Fake PE unavailable info */
281 rets[2] = 0;
282 ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
283 config_addr, BUID_HI(edev->phb->buid),
284 BUID_LO(edev->phb->buid));
285 } else {
286 return EEH_STATE_NOT_SUPPORT;
287 }
288
289 if (ret)
290 return ret;
291
292 /* Parse the result out */
293 result = 0;
294 if (rets[1]) {
295 switch(rets[0]) {
296 case 0:
297 result &= ~EEH_STATE_RESET_ACTIVE;
298 result |= EEH_STATE_MMIO_ACTIVE;
299 result |= EEH_STATE_DMA_ACTIVE;
300 break;
301 case 1:
302 result |= EEH_STATE_RESET_ACTIVE;
303 result |= EEH_STATE_MMIO_ACTIVE;
304 result |= EEH_STATE_DMA_ACTIVE;
305 break;
306 case 2:
307 result &= ~EEH_STATE_RESET_ACTIVE;
308 result &= ~EEH_STATE_MMIO_ACTIVE;
309 result &= ~EEH_STATE_DMA_ACTIVE;
310 break;
311 case 4:
312 result &= ~EEH_STATE_RESET_ACTIVE;
313 result &= ~EEH_STATE_MMIO_ACTIVE;
314 result &= ~EEH_STATE_DMA_ACTIVE;
315 result |= EEH_STATE_MMIO_ENABLED;
316 break;
317 case 5:
318 if (rets[2]) {
319 if (state) *state = rets[2];
320 result = EEH_STATE_UNAVAILABLE;
321 } else {
322 result = EEH_STATE_NOT_SUPPORT;
323 }
324 default:
325 result = EEH_STATE_NOT_SUPPORT;
326 }
327 } else {
328 result = EEH_STATE_NOT_SUPPORT;
329 }
330
331 return result;
332}
333
334/**
335 * pseries_eeh_reset - Reset the specified PE
336 * @dn: PE associated device node
337 * @option: reset option
338 *
339 * Reset the specified PE
340 */
341static int pseries_eeh_reset(struct device_node *dn, int option)
342{
343 struct eeh_dev *edev;
344 int config_addr;
345 int ret;
346
347 /* Figure out PE address */
348 edev = of_node_to_eeh_dev(dn);
349 config_addr = edev->config_addr;
350 if (edev->pe_config_addr)
351 config_addr = edev->pe_config_addr;
352
353 /* Reset PE through RTAS call */
354 ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
355 config_addr, BUID_HI(edev->phb->buid),
356 BUID_LO(edev->phb->buid), option);
357
358 /* If fundamental-reset not supported, try hot-reset */
359 if (option == EEH_RESET_FUNDAMENTAL &&
360 ret == -8) {
361 ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
362 config_addr, BUID_HI(edev->phb->buid),
363 BUID_LO(edev->phb->buid), EEH_RESET_HOT);
364 }
365
366 return ret;
367}
368
369/**
370 * pseries_eeh_wait_state - Wait for PE state
371 * @dn: PE associated device node
372 * @max_wait: maximal period in microsecond
373 *
374 * Wait for the state of associated PE. It might take some time
375 * to retrieve the PE's state.
376 */
377static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
378{
379 int ret;
380 int mwait;
381
382 /*
383 * According to PAPR, the state of PE might be temporarily
384 * unavailable. Under the circumstance, we have to wait
385 * for indicated time determined by firmware. The maximal
386 * wait time is 5 minutes, which is acquired from the original
387 * EEH implementation. Also, the original implementation
388 * also defined the minimal wait time as 1 second.
389 */
390#define EEH_STATE_MIN_WAIT_TIME (1000)
391#define EEH_STATE_MAX_WAIT_TIME (300 * 1000)
392
393 while (1) {
394 ret = pseries_eeh_get_state(dn, &mwait);
395
396 /*
397 * If the PE's state is temporarily unavailable,
398 * we have to wait for the specified time. Otherwise,
399 * the PE's state will be returned immediately.
400 */
401 if (ret != EEH_STATE_UNAVAILABLE)
402 return ret;
403
404 if (max_wait <= 0) {
405 pr_warning("%s: Timeout when getting PE's state (%d)\n",
406 __func__, max_wait);
407 return EEH_STATE_NOT_SUPPORT;
408 }
409
410 if (mwait <= 0) {
411 pr_warning("%s: Firmware returned bad wait value %d\n",
412 __func__, mwait);
413 mwait = EEH_STATE_MIN_WAIT_TIME;
414 } else if (mwait > EEH_STATE_MAX_WAIT_TIME) {
415 pr_warning("%s: Firmware returned too long wait value %d\n",
416 __func__, mwait);
417 mwait = EEH_STATE_MAX_WAIT_TIME;
418 }
419
420 max_wait -= mwait;
421 msleep(mwait);
422 }
423
424 return EEH_STATE_NOT_SUPPORT;
425}
426
427/**
428 * pseries_eeh_get_log - Retrieve error log
429 * @dn: device node
430 * @severity: temporary or permanent error log
431 * @drv_log: driver log to be combined with retrieved error log
432 * @len: length of driver log
433 *
434 * Retrieve the temporary or permanent error from the PE.
435 * Actually, the error will be retrieved through the dedicated
436 * RTAS call.
437 */
438static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len)
439{
440 struct eeh_dev *edev;
441 int config_addr;
442 unsigned long flags;
443 int ret;
444
445 edev = of_node_to_eeh_dev(dn);
446 spin_lock_irqsave(&slot_errbuf_lock, flags);
447 memset(slot_errbuf, 0, eeh_error_buf_size);
448
449 /* Figure out the PE address */
450 config_addr = edev->config_addr;
451 if (edev->pe_config_addr)
452 config_addr = edev->pe_config_addr;
453
454 ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
455 BUID_HI(edev->phb->buid), BUID_LO(edev->phb->buid),
456 virt_to_phys(drv_log), len,
457 virt_to_phys(slot_errbuf), eeh_error_buf_size,
458 severity);
459 if (!ret)
460 log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
461 spin_unlock_irqrestore(&slot_errbuf_lock, flags);
462
463 return ret;
464}
465
466/**
467 * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE
468 * @dn: PE associated device node
469 *
470 * The function will be called to reconfigure the bridges included
471 * in the specified PE so that the mulfunctional PE would be recovered
472 * again.
473 */
474static int pseries_eeh_configure_bridge(struct device_node *dn)
475{
476 struct eeh_dev *edev;
477 int config_addr;
478 int ret;
479
480 /* Figure out the PE address */
481 edev = of_node_to_eeh_dev(dn);
482 config_addr = edev->config_addr;
483 if (edev->pe_config_addr)
484 config_addr = edev->pe_config_addr;
485
486 /* Use new configure-pe function, if supported */
487 if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
488 ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
489 config_addr, BUID_HI(edev->phb->buid),
490 BUID_LO(edev->phb->buid));
491 } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
492 ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
493 config_addr, BUID_HI(edev->phb->buid),
494 BUID_LO(edev->phb->buid));
495 } else {
496 return -EFAULT;
497 }
498
499 if (ret)
500 pr_warning("%s: Unable to configure bridge %d for %s\n",
501 __func__, ret, dn->full_name);
502
503 return ret;
504}
505
506/**
507 * pseries_eeh_read_config - Read PCI config space
508 * @dn: device node
509 * @where: PCI address
510 * @size: size to read
511 * @val: return value
512 *
513 * Read config space from the speicifed device
514 */
515static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val)
516{
517 struct pci_dn *pdn;
518
519 pdn = PCI_DN(dn);
520
521 return rtas_read_config(pdn, where, size, val);
522}
523
524/**
525 * pseries_eeh_write_config - Write PCI config space
526 * @dn: device node
527 * @where: PCI address
528 * @size: size to write
529 * @val: value to be written
530 *
531 * Write config space to the specified device
532 */
533static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val)
534{
535 struct pci_dn *pdn;
536
537 pdn = PCI_DN(dn);
538
539 return rtas_write_config(pdn, where, size, val);
540}
541
542static struct eeh_ops pseries_eeh_ops = {
543 .name = "pseries",
544 .init = pseries_eeh_init,
545 .set_option = pseries_eeh_set_option,
546 .get_pe_addr = pseries_eeh_get_pe_addr,
547 .get_state = pseries_eeh_get_state,
548 .reset = pseries_eeh_reset,
549 .wait_state = pseries_eeh_wait_state,
550 .get_log = pseries_eeh_get_log,
551 .configure_bridge = pseries_eeh_configure_bridge,
552 .read_config = pseries_eeh_read_config,
553 .write_config = pseries_eeh_write_config
554};
555
556/**
557 * eeh_pseries_init - Register platform dependent EEH operations
558 *
559 * EEH initialization on pseries platform. This function should be
560 * called before any EEH related functions.
561 */
562int __init eeh_pseries_init(void)
563{
564 return eeh_ops_register(&pseries_eeh_ops);
565}
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
index eb744ee234da..243b3510d70f 100644
--- a/arch/powerpc/platforms/pseries/eeh_sysfs.c
+++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c
@@ -28,7 +28,7 @@
28#include <asm/pci-bridge.h> 28#include <asm/pci-bridge.h>
29 29
30/** 30/**
31 * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic 31 * EEH_SHOW_ATTR -- Create sysfs entry for eeh statistic
32 * @_name: name of file in sysfs directory 32 * @_name: name of file in sysfs directory
33 * @_memb: name of member in struct pci_dn to access 33 * @_memb: name of member in struct pci_dn to access
34 * @_format: printf format for display 34 * @_format: printf format for display
@@ -41,24 +41,21 @@ static ssize_t eeh_show_##_name(struct device *dev, \
41 struct device_attribute *attr, char *buf) \ 41 struct device_attribute *attr, char *buf) \
42{ \ 42{ \
43 struct pci_dev *pdev = to_pci_dev(dev); \ 43 struct pci_dev *pdev = to_pci_dev(dev); \
44 struct device_node *dn = pci_device_to_OF_node(pdev); \ 44 struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev); \
45 struct pci_dn *pdn; \
46 \ 45 \
47 if (!dn || PCI_DN(dn) == NULL) \ 46 if (!edev) \
48 return 0; \ 47 return 0; \
49 \ 48 \
50 pdn = PCI_DN(dn); \ 49 return sprintf(buf, _format "\n", edev->_memb); \
51 return sprintf(buf, _format "\n", pdn->_memb); \
52} \ 50} \
53static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL); 51static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
54 52
55 53EEH_SHOW_ATTR(eeh_mode, mode, "0x%x");
56EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x"); 54EEH_SHOW_ATTR(eeh_config_addr, config_addr, "0x%x");
57EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x"); 55EEH_SHOW_ATTR(eeh_pe_config_addr, pe_config_addr, "0x%x");
58EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x"); 56EEH_SHOW_ATTR(eeh_check_count, check_count, "%d" );
59EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d"); 57EEH_SHOW_ATTR(eeh_freeze_count, freeze_count, "%d" );
60EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d"); 58EEH_SHOW_ATTR(eeh_false_positives, false_positives, "%d" );
61EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d");
62 59
63void eeh_sysfs_add_device(struct pci_dev *pdev) 60void eeh_sysfs_add_device(struct pci_dev *pdev)
64{ 61{
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 7bc73af6c7b9..5f3ef876ded2 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -41,6 +41,7 @@
41#include <asm/udbg.h> 41#include <asm/udbg.h>
42#include <asm/smp.h> 42#include <asm/smp.h>
43#include <asm/trace.h> 43#include <asm/trace.h>
44#include <asm/firmware.h>
44 45
45#include "plpar_wrappers.h" 46#include "plpar_wrappers.h"
46#include "pseries.h" 47#include "pseries.h"
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 38d24e7e7bb1..109fdb75578d 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -217,7 +217,7 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
217 if (!dn) 217 if (!dn)
218 return NULL; 218 return NULL;
219 219
220 dn = find_device_pe(dn); 220 dn = eeh_find_device_pe(dn);
221 if (!dn) 221 if (!dn)
222 return NULL; 222 return NULL;
223 223
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 55d4ec1bd1ac..fbb21fc3080b 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -147,6 +147,9 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
147 147
148 pci_devs_phb_init_dynamic(phb); 148 pci_devs_phb_init_dynamic(phb);
149 149
150 /* Create EEH devices for the PHB */
151 eeh_dev_phb_init_dynamic(phb);
152
150 if (dn->child) 153 if (dn->child)
151 eeh_add_device_tree_early(dn); 154 eeh_add_device_tree_early(dn);
152 155
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
deleted file mode 100644
index 6e7742da0072..000000000000
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ /dev/null
@@ -1,513 +0,0 @@
1/*
2 * Hypervisor-assisted dump
3 *
4 * Linas Vepstas, Manish Ahuja 2008
5 * Copyright 2008 IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#include <linux/gfp.h>
15#include <linux/init.h>
16#include <linux/kobject.h>
17#include <linux/mm.h>
18#include <linux/of.h>
19#include <linux/pfn.h>
20#include <linux/swap.h>
21#include <linux/sysfs.h>
22
23#include <asm/page.h>
24#include <asm/phyp_dump.h>
25#include <asm/machdep.h>
26#include <asm/prom.h>
27#include <asm/rtas.h>
28
29/* Variables, used to communicate data between early boot and late boot */
30static struct phyp_dump phyp_dump_vars;
31struct phyp_dump *phyp_dump_info = &phyp_dump_vars;
32
33static int ibm_configure_kernel_dump;
34/* ------------------------------------------------- */
35/* RTAS interfaces to declare the dump regions */
36
37struct dump_section {
38 u32 dump_flags;
39 u16 source_type;
40 u16 error_flags;
41 u64 source_address;
42 u64 source_length;
43 u64 length_copied;
44 u64 destination_address;
45};
46
47struct phyp_dump_header {
48 u32 version;
49 u16 num_of_sections;
50 u16 status;
51
52 u32 first_offset_section;
53 u32 dump_disk_section;
54 u64 block_num_dd;
55 u64 num_of_blocks_dd;
56 u32 offset_dd;
57 u32 maxtime_to_auto;
58 /* No dump disk path string used */
59
60 struct dump_section cpu_data;
61 struct dump_section hpte_data;
62 struct dump_section kernel_data;
63};
64
65/* The dump header *must be* in low memory, so .bss it */
66static struct phyp_dump_header phdr;
67
68#define NUM_DUMP_SECTIONS 3
69#define DUMP_HEADER_VERSION 0x1
70#define DUMP_REQUEST_FLAG 0x1
71#define DUMP_SOURCE_CPU 0x0001
72#define DUMP_SOURCE_HPTE 0x0002
73#define DUMP_SOURCE_RMO 0x0011
74#define DUMP_ERROR_FLAG 0x2000
75#define DUMP_TRIGGERED 0x4000
76#define DUMP_PERFORMED 0x8000
77
78
79/**
80 * init_dump_header() - initialize the header declaring a dump
81 * Returns: length of dump save area.
82 *
83 * When the hypervisor saves crashed state, it needs to put
84 * it somewhere. The dump header tells the hypervisor where
85 * the data can be saved.
86 */
87static unsigned long init_dump_header(struct phyp_dump_header *ph)
88{
89 unsigned long addr_offset = 0;
90
91 /* Set up the dump header */
92 ph->version = DUMP_HEADER_VERSION;
93 ph->num_of_sections = NUM_DUMP_SECTIONS;
94 ph->status = 0;
95
96 ph->first_offset_section =
97 (u32)offsetof(struct phyp_dump_header, cpu_data);
98 ph->dump_disk_section = 0;
99 ph->block_num_dd = 0;
100 ph->num_of_blocks_dd = 0;
101 ph->offset_dd = 0;
102
103 ph->maxtime_to_auto = 0; /* disabled */
104
105 /* The first two sections are mandatory */
106 ph->cpu_data.dump_flags = DUMP_REQUEST_FLAG;
107 ph->cpu_data.source_type = DUMP_SOURCE_CPU;
108 ph->cpu_data.source_address = 0;
109 ph->cpu_data.source_length = phyp_dump_info->cpu_state_size;
110 ph->cpu_data.destination_address = addr_offset;
111 addr_offset += phyp_dump_info->cpu_state_size;
112
113 ph->hpte_data.dump_flags = DUMP_REQUEST_FLAG;
114 ph->hpte_data.source_type = DUMP_SOURCE_HPTE;
115 ph->hpte_data.source_address = 0;
116 ph->hpte_data.source_length = phyp_dump_info->hpte_region_size;
117 ph->hpte_data.destination_address = addr_offset;
118 addr_offset += phyp_dump_info->hpte_region_size;
119
120 /* This section describes the low kernel region */
121 ph->kernel_data.dump_flags = DUMP_REQUEST_FLAG;
122 ph->kernel_data.source_type = DUMP_SOURCE_RMO;
123 ph->kernel_data.source_address = PHYP_DUMP_RMR_START;
124 ph->kernel_data.source_length = PHYP_DUMP_RMR_END;
125 ph->kernel_data.destination_address = addr_offset;
126 addr_offset += ph->kernel_data.source_length;
127
128 return addr_offset;
129}
130
131static void print_dump_header(const struct phyp_dump_header *ph)
132{
133#ifdef DEBUG
134 if (ph == NULL)
135 return;
136
137 printk(KERN_INFO "dump header:\n");
138 /* setup some ph->sections required */
139 printk(KERN_INFO "version = %d\n", ph->version);
140 printk(KERN_INFO "Sections = %d\n", ph->num_of_sections);
141 printk(KERN_INFO "Status = 0x%x\n", ph->status);
142
143 /* No ph->disk, so all should be set to 0 */
144 printk(KERN_INFO "Offset to first section 0x%x\n",
145 ph->first_offset_section);
146 printk(KERN_INFO "dump disk sections should be zero\n");
147 printk(KERN_INFO "dump disk section = %d\n", ph->dump_disk_section);
148 printk(KERN_INFO "block num = %lld\n", ph->block_num_dd);
149 printk(KERN_INFO "number of blocks = %lld\n", ph->num_of_blocks_dd);
150 printk(KERN_INFO "dump disk offset = %d\n", ph->offset_dd);
151 printk(KERN_INFO "Max auto time= %d\n", ph->maxtime_to_auto);
152
153 /*set cpu state and hpte states as well scratch pad area */
154 printk(KERN_INFO " CPU AREA\n");
155 printk(KERN_INFO "cpu dump_flags =%d\n", ph->cpu_data.dump_flags);
156 printk(KERN_INFO "cpu source_type =%d\n", ph->cpu_data.source_type);
157 printk(KERN_INFO "cpu error_flags =%d\n", ph->cpu_data.error_flags);
158 printk(KERN_INFO "cpu source_address =%llx\n",
159 ph->cpu_data.source_address);
160 printk(KERN_INFO "cpu source_length =%llx\n",
161 ph->cpu_data.source_length);
162 printk(KERN_INFO "cpu length_copied =%llx\n",
163 ph->cpu_data.length_copied);
164
165 printk(KERN_INFO " HPTE AREA\n");
166 printk(KERN_INFO "HPTE dump_flags =%d\n", ph->hpte_data.dump_flags);
167 printk(KERN_INFO "HPTE source_type =%d\n", ph->hpte_data.source_type);
168 printk(KERN_INFO "HPTE error_flags =%d\n", ph->hpte_data.error_flags);
169 printk(KERN_INFO "HPTE source_address =%llx\n",
170 ph->hpte_data.source_address);
171 printk(KERN_INFO "HPTE source_length =%llx\n",
172 ph->hpte_data.source_length);
173 printk(KERN_INFO "HPTE length_copied =%llx\n",
174 ph->hpte_data.length_copied);
175
176 printk(KERN_INFO " SRSD AREA\n");
177 printk(KERN_INFO "SRSD dump_flags =%d\n", ph->kernel_data.dump_flags);
178 printk(KERN_INFO "SRSD source_type =%d\n", ph->kernel_data.source_type);
179 printk(KERN_INFO "SRSD error_flags =%d\n", ph->kernel_data.error_flags);
180 printk(KERN_INFO "SRSD source_address =%llx\n",
181 ph->kernel_data.source_address);
182 printk(KERN_INFO "SRSD source_length =%llx\n",
183 ph->kernel_data.source_length);
184 printk(KERN_INFO "SRSD length_copied =%llx\n",
185 ph->kernel_data.length_copied);
186#endif
187}
188
189static ssize_t show_phyp_dump_active(struct kobject *kobj,
190 struct kobj_attribute *attr, char *buf)
191{
192
193 /* create filesystem entry so kdump is phyp-dump aware */
194 return sprintf(buf, "%lx\n", phyp_dump_info->phyp_dump_at_boot);
195}
196
197static struct kobj_attribute pdl = __ATTR(phyp_dump_active, 0600,
198 show_phyp_dump_active,
199 NULL);
200
201static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
202{
203 int rc;
204
205 /* Add addr value if not initialized before */
206 if (ph->cpu_data.destination_address == 0) {
207 ph->cpu_data.destination_address += addr;
208 ph->hpte_data.destination_address += addr;
209 ph->kernel_data.destination_address += addr;
210 }
211
212 /* ToDo Invalidate kdump and free memory range. */
213
214 do {
215 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
216 1, ph, sizeof(struct phyp_dump_header));
217 } while (rtas_busy_delay(rc));
218
219 if (rc) {
220 printk(KERN_ERR "phyp-dump: unexpected error (%d) on "
221 "register\n", rc);
222 print_dump_header(ph);
223 return;
224 }
225
226 rc = sysfs_create_file(kernel_kobj, &pdl.attr);
227 if (rc)
228 printk(KERN_ERR "phyp-dump: unable to create sysfs"
229 " file (%d)\n", rc);
230}
231
232static
233void invalidate_last_dump(struct phyp_dump_header *ph, unsigned long addr)
234{
235 int rc;
236
237 /* Add addr value if not initialized before */
238 if (ph->cpu_data.destination_address == 0) {
239 ph->cpu_data.destination_address += addr;
240 ph->hpte_data.destination_address += addr;
241 ph->kernel_data.destination_address += addr;
242 }
243
244 do {
245 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
246 2, ph, sizeof(struct phyp_dump_header));
247 } while (rtas_busy_delay(rc));
248
249 if (rc) {
250 printk(KERN_ERR "phyp-dump: unexpected error (%d) "
251 "on invalidate\n", rc);
252 print_dump_header(ph);
253 }
254}
255
256/* ------------------------------------------------- */
257/**
258 * release_memory_range -- release memory previously memblock_reserved
259 * @start_pfn: starting physical frame number
260 * @nr_pages: number of pages to free.
261 *
262 * This routine will release memory that had been previously
263 * memblock_reserved in early boot. The released memory becomes
264 * available for genreal use.
265 */
266static void release_memory_range(unsigned long start_pfn,
267 unsigned long nr_pages)
268{
269 struct page *rpage;
270 unsigned long end_pfn;
271 long i;
272
273 end_pfn = start_pfn + nr_pages;
274
275 for (i = start_pfn; i <= end_pfn; i++) {
276 rpage = pfn_to_page(i);
277 if (PageReserved(rpage)) {
278 ClearPageReserved(rpage);
279 init_page_count(rpage);
280 __free_page(rpage);
281 totalram_pages++;
282 }
283 }
284}
285
286/**
287 * track_freed_range -- Counts the range being freed.
288 * Once the counter goes to zero, it re-registers dump for
289 * future use.
290 */
291static void
292track_freed_range(unsigned long addr, unsigned long length)
293{
294 static unsigned long scratch_area_size, reserved_area_size;
295
296 if (addr < phyp_dump_info->init_reserve_start)
297 return;
298
299 if ((addr >= phyp_dump_info->init_reserve_start) &&
300 (addr <= phyp_dump_info->init_reserve_start +
301 phyp_dump_info->init_reserve_size))
302 reserved_area_size += length;
303
304 if ((addr >= phyp_dump_info->reserved_scratch_addr) &&
305 (addr <= phyp_dump_info->reserved_scratch_addr +
306 phyp_dump_info->reserved_scratch_size))
307 scratch_area_size += length;
308
309 if ((reserved_area_size == phyp_dump_info->init_reserve_size) &&
310 (scratch_area_size == phyp_dump_info->reserved_scratch_size)) {
311
312 invalidate_last_dump(&phdr,
313 phyp_dump_info->reserved_scratch_addr);
314 register_dump_area(&phdr,
315 phyp_dump_info->reserved_scratch_addr);
316 }
317}
318
319/* ------------------------------------------------- */
320/**
321 * sysfs_release_region -- sysfs interface to release memory range.
322 *
323 * Usage:
324 * "echo <start addr> <length> > /sys/kernel/release_region"
325 *
326 * Example:
327 * "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
328 *
329 * will release 256MB starting at 1GB.
330 */
331static ssize_t store_release_region(struct kobject *kobj,
332 struct kobj_attribute *attr,
333 const char *buf, size_t count)
334{
335 unsigned long start_addr, length, end_addr;
336 unsigned long start_pfn, nr_pages;
337 ssize_t ret;
338
339 ret = sscanf(buf, "%lx %lx", &start_addr, &length);
340 if (ret != 2)
341 return -EINVAL;
342
343 track_freed_range(start_addr, length);
344
345 /* Range-check - don't free any reserved memory that
346 * wasn't reserved for phyp-dump */
347 if (start_addr < phyp_dump_info->init_reserve_start)
348 start_addr = phyp_dump_info->init_reserve_start;
349
350 end_addr = phyp_dump_info->init_reserve_start +
351 phyp_dump_info->init_reserve_size;
352 if (start_addr+length > end_addr)
353 length = end_addr - start_addr;
354
355 /* Release the region of memory assed in by user */
356 start_pfn = PFN_DOWN(start_addr);
357 nr_pages = PFN_DOWN(length);
358 release_memory_range(start_pfn, nr_pages);
359
360 return count;
361}
362
363static ssize_t show_release_region(struct kobject *kobj,
364 struct kobj_attribute *attr, char *buf)
365{
366 u64 second_addr_range;
367
368 /* total reserved size - start of scratch area */
369 second_addr_range = phyp_dump_info->init_reserve_size -
370 phyp_dump_info->reserved_scratch_size;
371 return sprintf(buf, "CPU:0x%llx-0x%llx: HPTE:0x%llx-0x%llx:"
372 " DUMP:0x%llx-0x%llx, 0x%lx-0x%llx:\n",
373 phdr.cpu_data.destination_address,
374 phdr.cpu_data.length_copied,
375 phdr.hpte_data.destination_address,
376 phdr.hpte_data.length_copied,
377 phdr.kernel_data.destination_address,
378 phdr.kernel_data.length_copied,
379 phyp_dump_info->init_reserve_start,
380 second_addr_range);
381}
382
383static struct kobj_attribute rr = __ATTR(release_region, 0600,
384 show_release_region,
385 store_release_region);
386
387static int __init phyp_dump_setup(void)
388{
389 struct device_node *rtas;
390 const struct phyp_dump_header *dump_header = NULL;
391 unsigned long dump_area_start;
392 unsigned long dump_area_length;
393 int header_len = 0;
394 int rc;
395
396 /* If no memory was reserved in early boot, there is nothing to do */
397 if (phyp_dump_info->init_reserve_size == 0)
398 return 0;
399
400 /* Return if phyp dump not supported */
401 if (!phyp_dump_info->phyp_dump_configured)
402 return -ENOSYS;
403
404 /* Is there dump data waiting for us? If there isn't,
405 * then register a new dump area, and release all of
406 * the rest of the reserved ram.
407 *
408 * The /rtas/ibm,kernel-dump rtas node is present only
409 * if there is dump data waiting for us.
410 */
411 rtas = of_find_node_by_path("/rtas");
412 if (rtas) {
413 dump_header = of_get_property(rtas, "ibm,kernel-dump",
414 &header_len);
415 of_node_put(rtas);
416 }
417
418 ibm_configure_kernel_dump = rtas_token("ibm,configure-kernel-dump");
419
420 print_dump_header(dump_header);
421 dump_area_length = init_dump_header(&phdr);
422 /* align down */
423 dump_area_start = phyp_dump_info->init_reserve_start & PAGE_MASK;
424
425 if (dump_header == NULL) {
426 register_dump_area(&phdr, dump_area_start);
427 return 0;
428 }
429
430 /* re-register the dump area, if old dump was invalid */
431 if ((dump_header) && (dump_header->status & DUMP_ERROR_FLAG)) {
432 invalidate_last_dump(&phdr, dump_area_start);
433 register_dump_area(&phdr, dump_area_start);
434 return 0;
435 }
436
437 if (dump_header) {
438 phyp_dump_info->reserved_scratch_addr =
439 dump_header->cpu_data.destination_address;
440 phyp_dump_info->reserved_scratch_size =
441 dump_header->cpu_data.source_length +
442 dump_header->hpte_data.source_length +
443 dump_header->kernel_data.source_length;
444 }
445
446 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */
447 rc = sysfs_create_file(kernel_kobj, &rr.attr);
448 if (rc)
449 printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n",
450 rc);
451
452 /* ToDo: re-register the dump area, for next time. */
453 return 0;
454}
455machine_subsys_initcall(pseries, phyp_dump_setup);
456
457int __init early_init_dt_scan_phyp_dump(unsigned long node,
458 const char *uname, int depth, void *data)
459{
460 const unsigned int *sizes;
461
462 phyp_dump_info->phyp_dump_configured = 0;
463 phyp_dump_info->phyp_dump_is_active = 0;
464
465 if (depth != 1 || strcmp(uname, "rtas") != 0)
466 return 0;
467
468 if (of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL))
469 phyp_dump_info->phyp_dump_configured++;
470
471 if (of_get_flat_dt_prop(node, "ibm,dump-kernel", NULL))
472 phyp_dump_info->phyp_dump_is_active++;
473
474 sizes = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
475 NULL);
476 if (!sizes)
477 return 0;
478
479 if (sizes[0] == 1)
480 phyp_dump_info->cpu_state_size = *((unsigned long *)&sizes[1]);
481
482 if (sizes[3] == 2)
483 phyp_dump_info->hpte_region_size =
484 *((unsigned long *)&sizes[4]);
485 return 1;
486}
487
488/* Look for phyp_dump= cmdline option */
489static int __init early_phyp_dump_enabled(char *p)
490{
491 phyp_dump_info->phyp_dump_at_boot = 1;
492
493 if (!p)
494 return 0;
495
496 if (strncmp(p, "1", 1) == 0)
497 phyp_dump_info->phyp_dump_at_boot = 1;
498 else if (strncmp(p, "0", 1) == 0)
499 phyp_dump_info->phyp_dump_at_boot = 0;
500
501 return 0;
502}
503early_param("phyp_dump", early_phyp_dump_enabled);
504
505/* Look for phyp_dump_reserve_size= cmdline option */
506static int __init early_phyp_dump_reserve_size(char *p)
507{
508 if (p)
509 phyp_dump_info->reserve_bootvar = memparse(p, &p);
510
511 return 0;
512}
513early_param("phyp_dump_reserve_size", early_phyp_dump_reserve_size);
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
index 085fd3f45ad2..a12e95af6933 100644
--- a/arch/powerpc/platforms/pseries/processor_idle.c
+++ b/arch/powerpc/platforms/pseries/processor_idle.c
@@ -96,6 +96,20 @@ out:
96 return index; 96 return index;
97} 97}
98 98
99static void check_and_cede_processor(void)
100{
101 /*
102 * Interrupts are soft-disabled at this point,
103 * but not hard disabled. So an interrupt might have
104 * occurred before entering NAP, and would be potentially
105 * lost (edge events, decrementer events, etc...) unless
106 * we first hard disable then check.
107 */
108 hard_irq_disable();
109 if (get_paca()->irq_happened == 0)
110 cede_processor();
111}
112
99static int dedicated_cede_loop(struct cpuidle_device *dev, 113static int dedicated_cede_loop(struct cpuidle_device *dev,
100 struct cpuidle_driver *drv, 114 struct cpuidle_driver *drv,
101 int index) 115 int index)
@@ -108,7 +122,7 @@ static int dedicated_cede_loop(struct cpuidle_device *dev,
108 122
109 ppc64_runlatch_off(); 123 ppc64_runlatch_off();
110 HMT_medium(); 124 HMT_medium();
111 cede_processor(); 125 check_and_cede_processor();
112 126
113 get_lppaca()->donate_dedicated_cpu = 0; 127 get_lppaca()->donate_dedicated_cpu = 0;
114 dev->last_residency = 128 dev->last_residency =
@@ -132,7 +146,7 @@ static int shared_cede_loop(struct cpuidle_device *dev,
132 * processor. When returning here, external interrupts 146 * processor. When returning here, external interrupts
133 * are enabled. 147 * are enabled.
134 */ 148 */
135 cede_processor(); 149 check_and_cede_processor();
136 150
137 dev->last_residency = 151 dev->last_residency =
138 (int)idle_loop_epilog(in_purr, kt_before); 152 (int)idle_loop_epilog(in_purr, kt_before);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f79f1278dfca..8f137af616af 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -190,9 +190,8 @@ static void __init pseries_mpic_init_IRQ(void)
190 BUG_ON(openpic_addr == 0); 190 BUG_ON(openpic_addr == 0);
191 191
192 /* Setup the openpic driver */ 192 /* Setup the openpic driver */
193 mpic = mpic_alloc(pSeries_mpic_node, openpic_addr, 0, 193 mpic = mpic_alloc(pSeries_mpic_node, openpic_addr,
194 16, 250, /* isu size, irq count */ 194 MPIC_NO_RESET, 16, 0, " MPIC ");
195 " MPIC ");
196 BUG_ON(mpic == NULL); 195 BUG_ON(mpic == NULL);
197 196
198 /* Add ISUs */ 197 /* Add ISUs */
@@ -261,8 +260,12 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
261 switch (action) { 260 switch (action) {
262 case PSERIES_RECONFIG_ADD: 261 case PSERIES_RECONFIG_ADD:
263 pci = np->parent->data; 262 pci = np->parent->data;
264 if (pci) 263 if (pci) {
265 update_dn_pci_info(np, pci->phb); 264 update_dn_pci_info(np, pci->phb);
265
266 /* Create EEH device for the OF node */
267 eeh_dev_init(np, pci->phb);
268 }
266 break; 269 break;
267 default: 270 default:
268 err = NOTIFY_DONE; 271 err = NOTIFY_DONE;
@@ -382,6 +385,7 @@ static void __init pSeries_setup_arch(void)
382 385
383 /* Find and initialize PCI host bridges */ 386 /* Find and initialize PCI host bridges */
384 init_pci_config_tokens(); 387 init_pci_config_tokens();
388 eeh_pseries_init();
385 find_and_init_phbs(); 389 find_and_init_phbs();
386 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); 390 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
387 eeh_init(); 391 eeh_init();
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 7b4df37ac381..a84fecf63c4d 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -29,3 +29,7 @@ config SCOM_DEBUGFS
29 bool "Expose SCOM controllers via debugfs" 29 bool "Expose SCOM controllers via debugfs"
30 depends on PPC_SCOM 30 depends on PPC_SCOM
31 default n 31 default n
32
33config GE_FPGA
34 bool
35 default n
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5e37b4717864..1bd7ecb24620 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,8 @@ ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
4 4
5mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o 5mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
6obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) 6obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
7mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o
8obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y)
7obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o 9obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
8fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o 10fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o
9obj-$(CONFIG_PPC_MSI_BITMAP) += msi_bitmap.o 11obj-$(CONFIG_PPC_MSI_BITMAP) += msi_bitmap.o
@@ -65,3 +67,5 @@ obj-$(CONFIG_PPC_SCOM) += scom.o
65subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 67subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
66 68
67obj-$(CONFIG_PPC_XICS) += xics/ 69obj-$(CONFIG_PPC_XICS) += xics/
70
71obj-$(CONFIG_GE_FPGA) += ge/
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
index 116415899176..37a69097e022 100644
--- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
+++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c
@@ -24,6 +24,7 @@
24 */ 24 */
25 25
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/export.h>
27#include <linux/slab.h> 28#include <linux/slab.h>
28#include <linux/err.h> 29#include <linux/err.h>
29#include <linux/of_platform.h> 30#include <linux/of_platform.h>
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
index 5f88797dce73..cedabd0f4bfe 100644
--- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/module.h>
24#include <linux/of_platform.h> 25#include <linux/of_platform.h>
25#include <asm/io.h> 26#include <asm/io.h>
26 27
@@ -200,6 +201,9 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
200 { 201 {
201 .compatible = "fsl,p1022-l2-cache-controller", 202 .compatible = "fsl,p1022-l2-cache-controller",
202 }, 203 },
204 {
205 .compatible = "fsl,mpc8548-l2-cache-controller",
206 },
203 {}, 207 {},
204}; 208};
205 209
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 0c01debe963b..6e097de00e09 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -410,6 +410,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
410 410
411 msi->msi_regs = ioremap(res.start, resource_size(&res)); 411 msi->msi_regs = ioremap(res.start, resource_size(&res));
412 if (!msi->msi_regs) { 412 if (!msi->msi_regs) {
413 err = -ENOMEM;
413 dev_err(&dev->dev, "could not map node %s\n", 414 dev_err(&dev->dev, "could not map node %s\n",
414 dev->dev.of_node->full_name); 415 dev->dev.of_node->full_name);
415 goto error_out; 416 goto error_out;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index a4c4f4a932d8..5b6f556094dd 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -66,8 +66,8 @@
66 " li %0,%3\n" \ 66 " li %0,%3\n" \
67 " b 2b\n" \ 67 " b 2b\n" \
68 ".section __ex_table,\"a\"\n" \ 68 ".section __ex_table,\"a\"\n" \
69 " .align 2\n" \ 69 PPC_LONG_ALIGN "\n" \
70 " .long 1b,3b\n" \ 70 PPC_LONG "1b,3b\n" \
71 ".text" \ 71 ".text" \
72 : "=r" (err), "=r" (x) \ 72 : "=r" (err), "=r" (x) \
73 : "b" (addr), "i" (-EFAULT), "0" (err)) 73 : "b" (addr), "i" (-EFAULT), "0" (err))
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index 15485789e9db..14bd5221f28a 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -100,14 +100,8 @@
100#define DOORBELL_DSR_TE 0x00000080 100#define DOORBELL_DSR_TE 0x00000080
101#define DOORBELL_DSR_QFI 0x00000010 101#define DOORBELL_DSR_QFI 0x00000010
102#define DOORBELL_DSR_DIQI 0x00000001 102#define DOORBELL_DSR_DIQI 0x00000001
103#define DOORBELL_TID_OFFSET 0x02
104#define DOORBELL_SID_OFFSET 0x04
105#define DOORBELL_INFO_OFFSET 0x06
106 103
107#define DOORBELL_MESSAGE_SIZE 0x08 104#define DOORBELL_MESSAGE_SIZE 0x08
108#define DBELL_SID(x) (*(u16 *)(x + DOORBELL_SID_OFFSET))
109#define DBELL_TID(x) (*(u16 *)(x + DOORBELL_TID_OFFSET))
110#define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET))
111 105
112struct rio_msg_regs { 106struct rio_msg_regs {
113 u32 omr; 107 u32 omr;
@@ -193,6 +187,13 @@ struct fsl_rmu {
193 int rxirq; 187 int rxirq;
194}; 188};
195 189
190struct rio_dbell_msg {
191 u16 pad1;
192 u16 tid;
193 u16 sid;
194 u16 info;
195};
196
196/** 197/**
197 * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler 198 * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
198 * @irq: Linux interrupt number 199 * @irq: Linux interrupt number
@@ -311,8 +312,8 @@ fsl_rio_dbell_handler(int irq, void *dev_instance)
311 312
312 /* XXX Need to check/dispatch until queue empty */ 313 /* XXX Need to check/dispatch until queue empty */
313 if (dsr & DOORBELL_DSR_DIQI) { 314 if (dsr & DOORBELL_DSR_DIQI) {
314 u32 dmsg = 315 struct rio_dbell_msg *dmsg =
315 (u32) fsl_dbell->dbell_ring.virt + 316 fsl_dbell->dbell_ring.virt +
316 (in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff); 317 (in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff);
317 struct rio_dbell *dbell; 318 struct rio_dbell *dbell;
318 int found = 0; 319 int found = 0;
@@ -320,25 +321,25 @@ fsl_rio_dbell_handler(int irq, void *dev_instance)
320 pr_debug 321 pr_debug
321 ("RIO: processing doorbell," 322 ("RIO: processing doorbell,"
322 " sid %2.2x tid %2.2x info %4.4x\n", 323 " sid %2.2x tid %2.2x info %4.4x\n",
323 DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); 324 dmsg->sid, dmsg->tid, dmsg->info);
324 325
325 for (i = 0; i < MAX_PORT_NUM; i++) { 326 for (i = 0; i < MAX_PORT_NUM; i++) {
326 if (fsl_dbell->mport[i]) { 327 if (fsl_dbell->mport[i]) {
327 list_for_each_entry(dbell, 328 list_for_each_entry(dbell,
328 &fsl_dbell->mport[i]->dbells, node) { 329 &fsl_dbell->mport[i]->dbells, node) {
329 if ((dbell->res->start 330 if ((dbell->res->start
330 <= DBELL_INF(dmsg)) 331 <= dmsg->info)
331 && (dbell->res->end 332 && (dbell->res->end
332 >= DBELL_INF(dmsg))) { 333 >= dmsg->info)) {
333 found = 1; 334 found = 1;
334 break; 335 break;
335 } 336 }
336 } 337 }
337 if (found && dbell->dinb) { 338 if (found && dbell->dinb) {
338 dbell->dinb(fsl_dbell->mport[i], 339 dbell->dinb(fsl_dbell->mport[i],
339 dbell->dev_id, DBELL_SID(dmsg), 340 dbell->dev_id, dmsg->sid,
340 DBELL_TID(dmsg), 341 dmsg->tid,
341 DBELL_INF(dmsg)); 342 dmsg->info);
342 break; 343 break;
343 } 344 }
344 } 345 }
@@ -348,8 +349,8 @@ fsl_rio_dbell_handler(int irq, void *dev_instance)
348 pr_debug 349 pr_debug
349 ("RIO: spurious doorbell," 350 ("RIO: spurious doorbell,"
350 " sid %2.2x tid %2.2x info %4.4x\n", 351 " sid %2.2x tid %2.2x info %4.4x\n",
351 DBELL_SID(dmsg), DBELL_TID(dmsg), 352 dmsg->sid, dmsg->tid,
352 DBELL_INF(dmsg)); 353 dmsg->info);
353 } 354 }
354 setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI); 355 setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI);
355 out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI); 356 out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI);
@@ -657,7 +658,7 @@ fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
657 int ret = 0; 658 int ret = 0;
658 659
659 pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ 660 pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
660 "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); 661 "%p len %8.8zx\n", rdev->destid, mbox, buffer, len);
661 if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { 662 if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
662 ret = -EINVAL; 663 ret = -EINVAL;
663 goto out; 664 goto out;
@@ -972,7 +973,8 @@ out:
972void *fsl_get_inb_message(struct rio_mport *mport, int mbox) 973void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
973{ 974{
974 struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); 975 struct fsl_rmu *rmu = GET_RMM_HANDLE(mport);
975 u32 phys_buf, virt_buf; 976 u32 phys_buf;
977 void *virt_buf;
976 void *buf = NULL; 978 void *buf = NULL;
977 int buf_idx; 979 int buf_idx;
978 980
@@ -982,7 +984,7 @@ void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
982 if (phys_buf == in_be32(&rmu->msg_regs->ifqepar)) 984 if (phys_buf == in_be32(&rmu->msg_regs->ifqepar))
983 goto out2; 985 goto out2;
984 986
985 virt_buf = (u32) rmu->msg_rx_ring.virt + (phys_buf 987 virt_buf = rmu->msg_rx_ring.virt + (phys_buf
986 - rmu->msg_rx_ring.phys); 988 - rmu->msg_rx_ring.phys);
987 buf_idx = (phys_buf - rmu->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; 989 buf_idx = (phys_buf - rmu->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
988 buf = rmu->msg_rx_ring.virt_buffer[buf_idx]; 990 buf = rmu->msg_rx_ring.virt_buffer[buf_idx];
@@ -994,7 +996,7 @@ void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
994 } 996 }
995 997
996 /* Copy max message size, caller is expected to allocate that big */ 998 /* Copy max message size, caller is expected to allocate that big */
997 memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE); 999 memcpy(buf, virt_buf, RIO_MAX_MSG_SIZE);
998 1000
999 /* Clear the available buffer */ 1001 /* Clear the available buffer */
1000 rmu->msg_rx_ring.virt_buffer[buf_idx] = NULL; 1002 rmu->msg_rx_ring.virt_buffer[buf_idx] = NULL;
diff --git a/arch/powerpc/sysdev/ge/Makefile b/arch/powerpc/sysdev/ge/Makefile
new file mode 100644
index 000000000000..8731ffcb79b9
--- /dev/null
+++ b/arch/powerpc/sysdev/ge/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_GE_FPGA) += ge_pic.o
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/sysdev/ge/ge_pic.c
index af3fd697de82..2bcb78bb3a15 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/sysdev/ge/ge_pic.c
@@ -22,7 +22,7 @@
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/irq.h> 23#include <asm/irq.h>
24 24
25#include "gef_pic.h" 25#include "ge_pic.h"
26 26
27#define DEBUG 27#define DEBUG
28#undef DEBUG 28#undef DEBUG
diff --git a/arch/powerpc/platforms/86xx/gef_pic.h b/arch/powerpc/sysdev/ge/ge_pic.h
index 6149916da3f4..6149916da3f4 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.h
+++ b/arch/powerpc/sysdev/ge/ge_pic.h
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index c83a512fa175..9ac71ebd2c40 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -873,7 +873,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
873 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", 873 DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
874 mpic, d->irq, src, flow_type); 874 mpic, d->irq, src, flow_type);
875 875
876 if (src >= mpic->irq_count) 876 if (src >= mpic->num_sources)
877 return -EINVAL; 877 return -EINVAL;
878 878
879 if (flow_type == IRQ_TYPE_NONE) 879 if (flow_type == IRQ_TYPE_NONE)
@@ -909,7 +909,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
909 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", 909 DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
910 mpic, virq, src, vector); 910 mpic, virq, src, vector);
911 911
912 if (src >= mpic->irq_count) 912 if (src >= mpic->num_sources)
913 return; 913 return;
914 914
915 vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); 915 vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
@@ -926,7 +926,7 @@ void mpic_set_destination(unsigned int virq, unsigned int cpuid)
926 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", 926 DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
927 mpic, virq, src, cpuid); 927 mpic, virq, src, cpuid);
928 928
929 if (src >= mpic->irq_count) 929 if (src >= mpic->num_sources)
930 return; 930 return;
931 931
932 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); 932 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
@@ -1006,7 +1006,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
1006 return 0; 1006 return 0;
1007 } 1007 }
1008 1008
1009 if (hw >= mpic->irq_count) 1009 if (hw >= mpic->num_sources)
1010 return -EINVAL; 1010 return -EINVAL;
1011 1011
1012 mpic_msi_reserve_hwirq(mpic, hw); 1012 mpic_msi_reserve_hwirq(mpic, hw);
@@ -1149,6 +1149,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1149 u32 greg_feature; 1149 u32 greg_feature;
1150 const char *vers; 1150 const char *vers;
1151 const u32 *psrc; 1151 const u32 *psrc;
1152 u32 last_irq;
1152 1153
1153 /* Default MPIC search parameters */ 1154 /* Default MPIC search parameters */
1154 static const struct of_device_id __initconst mpic_device_id[] = { 1155 static const struct of_device_id __initconst mpic_device_id[] = {
@@ -1182,6 +1183,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1182 } 1183 }
1183 } 1184 }
1184 1185
1186 /* Read extra device-tree properties into the flags variable */
1187 if (of_get_property(node, "big-endian", NULL))
1188 flags |= MPIC_BIG_ENDIAN;
1189 if (of_get_property(node, "pic-no-reset", NULL))
1190 flags |= MPIC_NO_RESET;
1191 if (of_get_property(node, "single-cpu-affinity", NULL))
1192 flags |= MPIC_SINGLE_DEST_CPU;
1193 if (of_device_is_compatible(node, "fsl,mpic"))
1194 flags |= MPIC_FSL;
1195
1185 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); 1196 mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
1186 if (mpic == NULL) 1197 if (mpic == NULL)
1187 goto err_of_node_put; 1198 goto err_of_node_put;
@@ -1189,15 +1200,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1189 mpic->name = name; 1200 mpic->name = name;
1190 mpic->node = node; 1201 mpic->node = node;
1191 mpic->paddr = phys_addr; 1202 mpic->paddr = phys_addr;
1203 mpic->flags = flags;
1192 1204
1193 mpic->hc_irq = mpic_irq_chip; 1205 mpic->hc_irq = mpic_irq_chip;
1194 mpic->hc_irq.name = name; 1206 mpic->hc_irq.name = name;
1195 if (!(flags & MPIC_SECONDARY)) 1207 if (!(mpic->flags & MPIC_SECONDARY))
1196 mpic->hc_irq.irq_set_affinity = mpic_set_affinity; 1208 mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
1197#ifdef CONFIG_MPIC_U3_HT_IRQS 1209#ifdef CONFIG_MPIC_U3_HT_IRQS
1198 mpic->hc_ht_irq = mpic_irq_ht_chip; 1210 mpic->hc_ht_irq = mpic_irq_ht_chip;
1199 mpic->hc_ht_irq.name = name; 1211 mpic->hc_ht_irq.name = name;
1200 if (!(flags & MPIC_SECONDARY)) 1212 if (!(mpic->flags & MPIC_SECONDARY))
1201 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; 1213 mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
1202#endif /* CONFIG_MPIC_U3_HT_IRQS */ 1214#endif /* CONFIG_MPIC_U3_HT_IRQS */
1203 1215
@@ -1209,12 +1221,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1209 mpic->hc_tm = mpic_tm_chip; 1221 mpic->hc_tm = mpic_tm_chip;
1210 mpic->hc_tm.name = name; 1222 mpic->hc_tm.name = name;
1211 1223
1212 mpic->flags = flags;
1213 mpic->isu_size = isu_size;
1214 mpic->irq_count = irq_count;
1215 mpic->num_sources = 0; /* so far */ 1224 mpic->num_sources = 0; /* so far */
1216 1225
1217 if (flags & MPIC_LARGE_VECTORS) 1226 if (mpic->flags & MPIC_LARGE_VECTORS)
1218 intvec_top = 2047; 1227 intvec_top = 2047;
1219 else 1228 else
1220 intvec_top = 255; 1229 intvec_top = 255;
@@ -1233,12 +1242,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1233 mpic->ipi_vecs[3] = intvec_top - 1; 1242 mpic->ipi_vecs[3] = intvec_top - 1;
1234 mpic->spurious_vec = intvec_top; 1243 mpic->spurious_vec = intvec_top;
1235 1244
1236 /* Check for "big-endian" in device-tree */
1237 if (of_get_property(mpic->node, "big-endian", NULL) != NULL)
1238 mpic->flags |= MPIC_BIG_ENDIAN;
1239 if (of_device_is_compatible(mpic->node, "fsl,mpic"))
1240 mpic->flags |= MPIC_FSL;
1241
1242 /* Look for protected sources */ 1245 /* Look for protected sources */
1243 psrc = of_get_property(mpic->node, "protected-sources", &psize); 1246 psrc = of_get_property(mpic->node, "protected-sources", &psize);
1244 if (psrc) { 1247 if (psrc) {
@@ -1254,11 +1257,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1254 } 1257 }
1255 1258
1256#ifdef CONFIG_MPIC_WEIRD 1259#ifdef CONFIG_MPIC_WEIRD
1257 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; 1260 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(mpic->flags)];
1258#endif 1261#endif
1259 1262
1260 /* default register type */ 1263 /* default register type */
1261 if (flags & MPIC_BIG_ENDIAN) 1264 if (mpic->flags & MPIC_BIG_ENDIAN)
1262 mpic->reg_type = mpic_access_mmio_be; 1265 mpic->reg_type = mpic_access_mmio_be;
1263 else 1266 else
1264 mpic->reg_type = mpic_access_mmio_le; 1267 mpic->reg_type = mpic_access_mmio_le;
@@ -1268,10 +1271,10 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1268 * only if the kernel includes DCR support. 1271 * only if the kernel includes DCR support.
1269 */ 1272 */
1270#ifdef CONFIG_PPC_DCR 1273#ifdef CONFIG_PPC_DCR
1271 if (flags & MPIC_USES_DCR) 1274 if (mpic->flags & MPIC_USES_DCR)
1272 mpic->reg_type = mpic_access_dcr; 1275 mpic->reg_type = mpic_access_dcr;
1273#else 1276#else
1274 BUG_ON(flags & MPIC_USES_DCR); 1277 BUG_ON(mpic->flags & MPIC_USES_DCR);
1275#endif 1278#endif
1276 1279
1277 /* Map the global registers */ 1280 /* Map the global registers */
@@ -1283,10 +1286,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1283 /* When using a device-node, reset requests are only honored if the MPIC 1286 /* When using a device-node, reset requests are only honored if the MPIC
1284 * is allowed to reset. 1287 * is allowed to reset.
1285 */ 1288 */
1286 if (of_get_property(mpic->node, "pic-no-reset", NULL)) 1289 if (!(mpic->flags & MPIC_NO_RESET)) {
1287 mpic->flags |= MPIC_NO_RESET;
1288
1289 if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
1290 printk(KERN_DEBUG "mpic: Resetting\n"); 1290 printk(KERN_DEBUG "mpic: Resetting\n");
1291 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1291 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1292 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1292 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
@@ -1297,31 +1297,17 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1297 } 1297 }
1298 1298
1299 /* CoreInt */ 1299 /* CoreInt */
1300 if (flags & MPIC_ENABLE_COREINT) 1300 if (mpic->flags & MPIC_ENABLE_COREINT)
1301 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1301 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1302 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1302 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1303 | MPIC_GREG_GCONF_COREINT); 1303 | MPIC_GREG_GCONF_COREINT);
1304 1304
1305 if (flags & MPIC_ENABLE_MCK) 1305 if (mpic->flags & MPIC_ENABLE_MCK)
1306 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), 1306 mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
1307 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) 1307 mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
1308 | MPIC_GREG_GCONF_MCK); 1308 | MPIC_GREG_GCONF_MCK);
1309 1309
1310 /* 1310 /*
1311 * Read feature register. For non-ISU MPICs, num sources as well. On
1312 * ISU MPICs, sources are counted as ISUs are added
1313 */
1314 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1315 if (isu_size == 0) {
1316 if (flags & MPIC_BROKEN_FRR_NIRQS)
1317 mpic->num_sources = mpic->irq_count;
1318 else
1319 mpic->num_sources =
1320 ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1321 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
1322 }
1323
1324 /*
1325 * The MPIC driver will crash if there are more cores than we 1311 * The MPIC driver will crash if there are more cores than we
1326 * can initialize, so we may as well catch that problem here. 1312 * can initialize, so we may as well catch that problem here.
1327 */ 1313 */
@@ -1336,17 +1322,41 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1336 0x1000); 1322 0x1000);
1337 } 1323 }
1338 1324
1325 /*
1326 * Read feature register. For non-ISU MPICs, num sources as well. On
1327 * ISU MPICs, sources are counted as ISUs are added
1328 */
1329 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1330
1331 /*
1332 * By default, the last source number comes from the MPIC, but the
1333 * device-tree and board support code can override it on buggy hw.
1334 * If we get passed an isu_size (multi-isu MPIC) then we use that
1335 * as a default instead of the value read from the HW.
1336 */
1337 last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1338 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
1339 if (isu_size)
1340 last_irq = isu_size * MPIC_MAX_ISU - 1;
1341 of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
1342 if (irq_count)
1343 last_irq = irq_count - 1;
1344
1339 /* Initialize main ISU if none provided */ 1345 /* Initialize main ISU if none provided */
1340 if (mpic->isu_size == 0) { 1346 if (!isu_size) {
1341 mpic->isu_size = mpic->num_sources; 1347 isu_size = last_irq + 1;
1348 mpic->num_sources = isu_size;
1342 mpic_map(mpic, mpic->paddr, &mpic->isus[0], 1349 mpic_map(mpic, mpic->paddr, &mpic->isus[0],
1343 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1350 MPIC_INFO(IRQ_BASE),
1351 MPIC_INFO(IRQ_STRIDE) * isu_size);
1344 } 1352 }
1353
1354 mpic->isu_size = isu_size;
1345 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1355 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
1346 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1356 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1347 1357
1348 mpic->irqhost = irq_domain_add_linear(mpic->node, 1358 mpic->irqhost = irq_domain_add_linear(mpic->node,
1349 isu_size ? isu_size : mpic->num_sources, 1359 last_irq + 1,
1350 &mpic_host_ops, mpic); 1360 &mpic_host_ops, mpic);
1351 1361
1352 /* 1362 /*
@@ -1380,7 +1390,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1380 mpic->next = mpics; 1390 mpic->next = mpics;
1381 mpics = mpic; 1391 mpics = mpic;
1382 1392
1383 if (!(flags & MPIC_SECONDARY)) { 1393 if (!(mpic->flags & MPIC_SECONDARY)) {
1384 mpic_primary = mpic; 1394 mpic_primary = mpic;
1385 irq_set_default_host(mpic->irqhost); 1395 irq_set_default_host(mpic->irqhost);
1386 } 1396 }
@@ -1447,10 +1457,6 @@ void __init mpic_init(struct mpic *mpic)
1447 (mpic->ipi_vecs[0] + i)); 1457 (mpic->ipi_vecs[0] + i));
1448 } 1458 }
1449 1459
1450 /* Initialize interrupt sources */
1451 if (mpic->irq_count == 0)
1452 mpic->irq_count = mpic->num_sources;
1453
1454 /* Do the HT PIC fixups on U3 broken mpic */ 1460 /* Do the HT PIC fixups on U3 broken mpic */
1455 DBG("MPIC flags: %x\n", mpic->flags); 1461 DBG("MPIC flags: %x\n", mpic->flags);
1456 if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) { 1462 if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) {
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
new file mode 100644
index 000000000000..6e7fa386e76a
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -0,0 +1,282 @@
1/*
2 * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
3 *
4 * Some ideas based on un-pushed work done by Vivek Mahajan, Jason Jin, and
5 * Mingkai Hu from Freescale Semiconductor, Inc.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2 of the
10 * License.
11 *
12 */
13
14#include <linux/list.h>
15#include <linux/of_platform.h>
16#include <linux/errno.h>
17#include <asm/prom.h>
18#include <asm/hw_irq.h>
19#include <asm/ppc-pci.h>
20#include <asm/mpic_msgr.h>
21
22#define MPIC_MSGR_REGISTERS_PER_BLOCK 4
23#define MPIC_MSGR_STRIDE 0x10
24#define MPIC_MSGR_MER_OFFSET 0x100
25#define MSGR_INUSE 0
26#define MSGR_FREE 1
27
28static struct mpic_msgr **mpic_msgrs;
29static unsigned int mpic_msgr_count;
30
31static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
32{
33 out_be32(msgr->mer, value);
34}
35
36static inline u32 _mpic_msgr_mer_read(struct mpic_msgr *msgr)
37{
38 return in_be32(msgr->mer);
39}
40
41static inline void _mpic_msgr_disable(struct mpic_msgr *msgr)
42{
43 u32 mer = _mpic_msgr_mer_read(msgr);
44
45 _mpic_msgr_mer_write(msgr, mer & ~(1 << msgr->num));
46}
47
48struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
49{
50 unsigned long flags;
51 struct mpic_msgr *msgr;
52
53 /* Assume busy until proven otherwise. */
54 msgr = ERR_PTR(-EBUSY);
55
56 if (reg_num >= mpic_msgr_count)
57 return ERR_PTR(-ENODEV);
58
59 raw_spin_lock_irqsave(&msgr->lock, flags);
60 if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) {
61 msgr = mpic_msgrs[reg_num];
62 msgr->in_use = MSGR_INUSE;
63 }
64 raw_spin_unlock_irqrestore(&msgr->lock, flags);
65
66 return msgr;
67}
68EXPORT_SYMBOL_GPL(mpic_msgr_get);
69
70void mpic_msgr_put(struct mpic_msgr *msgr)
71{
72 unsigned long flags;
73
74 raw_spin_lock_irqsave(&msgr->lock, flags);
75 msgr->in_use = MSGR_FREE;
76 _mpic_msgr_disable(msgr);
77 raw_spin_unlock_irqrestore(&msgr->lock, flags);
78}
79EXPORT_SYMBOL_GPL(mpic_msgr_put);
80
81void mpic_msgr_enable(struct mpic_msgr *msgr)
82{
83 unsigned long flags;
84 u32 mer;
85
86 raw_spin_lock_irqsave(&msgr->lock, flags);
87 mer = _mpic_msgr_mer_read(msgr);
88 _mpic_msgr_mer_write(msgr, mer | (1 << msgr->num));
89 raw_spin_unlock_irqrestore(&msgr->lock, flags);
90}
91EXPORT_SYMBOL_GPL(mpic_msgr_enable);
92
93void mpic_msgr_disable(struct mpic_msgr *msgr)
94{
95 unsigned long flags;
96
97 raw_spin_lock_irqsave(&msgr->lock, flags);
98 _mpic_msgr_disable(msgr);
99 raw_spin_unlock_irqrestore(&msgr->lock, flags);
100}
101EXPORT_SYMBOL_GPL(mpic_msgr_disable);
102
103/* The following three functions are used to compute the order and number of
104 * the message register blocks. They are clearly very inefficent. However,
105 * they are called *only* a few times during device initialization.
106 */
107static unsigned int mpic_msgr_number_of_blocks(void)
108{
109 unsigned int count;
110 struct device_node *aliases;
111
112 count = 0;
113 aliases = of_find_node_by_name(NULL, "aliases");
114
115 if (aliases) {
116 char buf[32];
117
118 for (;;) {
119 snprintf(buf, sizeof(buf), "mpic-msgr-block%d", count);
120 if (!of_find_property(aliases, buf, NULL))
121 break;
122
123 count += 1;
124 }
125 }
126
127 return count;
128}
129
130static unsigned int mpic_msgr_number_of_registers(void)
131{
132 return mpic_msgr_number_of_blocks() * MPIC_MSGR_REGISTERS_PER_BLOCK;
133}
134
135static int mpic_msgr_block_number(struct device_node *node)
136{
137 struct device_node *aliases;
138 unsigned int index, number_of_blocks;
139 char buf[64];
140
141 number_of_blocks = mpic_msgr_number_of_blocks();
142 aliases = of_find_node_by_name(NULL, "aliases");
143 if (!aliases)
144 return -1;
145
146 for (index = 0; index < number_of_blocks; ++index) {
147 struct property *prop;
148
149 snprintf(buf, sizeof(buf), "mpic-msgr-block%d", index);
150 prop = of_find_property(aliases, buf, NULL);
151 if (node == of_find_node_by_path(prop->value))
152 break;
153 }
154
155 return index == number_of_blocks ? -1 : index;
156}
157
158/* The probe function for a single message register block.
159 */
160static __devinit int mpic_msgr_probe(struct platform_device *dev)
161{
162 void __iomem *msgr_block_addr;
163 int block_number;
164 struct resource rsrc;
165 unsigned int i;
166 unsigned int irq_index;
167 struct device_node *np = dev->dev.of_node;
168 unsigned int receive_mask;
169 const unsigned int *prop;
170
171 if (!np) {
172 dev_err(&dev->dev, "Device OF-Node is NULL");
173 return -EFAULT;
174 }
175
176 /* Allocate the message register array upon the first device
177 * registered.
178 */
179 if (!mpic_msgrs) {
180 mpic_msgr_count = mpic_msgr_number_of_registers();
181 dev_info(&dev->dev, "Found %d message registers\n",
182 mpic_msgr_count);
183
184 mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
185 GFP_KERNEL);
186 if (!mpic_msgrs) {
187 dev_err(&dev->dev,
188 "No memory for message register blocks\n");
189 return -ENOMEM;
190 }
191 }
192 dev_info(&dev->dev, "Of-device full name %s\n", np->full_name);
193
194 /* IO map the message register block. */
195 of_address_to_resource(np, 0, &rsrc);
196 msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start);
197 if (!msgr_block_addr) {
198 dev_err(&dev->dev, "Failed to iomap MPIC message registers");
199 return -EFAULT;
200 }
201
202 /* Ensure the block has a defined order. */
203 block_number = mpic_msgr_block_number(np);
204 if (block_number < 0) {
205 dev_err(&dev->dev,
206 "Failed to find message register block alias\n");
207 return -ENODEV;
208 }
209 dev_info(&dev->dev, "Setting up message register block %d\n",
210 block_number);
211
212 /* Grab the receive mask which specifies what registers can receive
213 * interrupts.
214 */
215 prop = of_get_property(np, "mpic-msgr-receive-mask", NULL);
216 receive_mask = (prop) ? *prop : 0xF;
217
218 /* Build up the appropriate message register data structures. */
219 for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) {
220 struct mpic_msgr *msgr;
221 unsigned int reg_number;
222
223 msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
224 if (!msgr) {
225 dev_err(&dev->dev, "No memory for message register\n");
226 return -ENOMEM;
227 }
228
229 reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
230 msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
231 msgr->mer = msgr->base + MPIC_MSGR_MER_OFFSET;
232 msgr->in_use = MSGR_FREE;
233 msgr->num = i;
234 raw_spin_lock_init(&msgr->lock);
235
236 if (receive_mask & (1 << i)) {
237 struct resource irq;
238
239 if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
240 dev_err(&dev->dev,
241 "Missing interrupt specifier");
242 kfree(msgr);
243 return -EFAULT;
244 }
245 msgr->irq = irq.start;
246 irq_index += 1;
247 } else {
248 msgr->irq = NO_IRQ;
249 }
250
251 mpic_msgrs[reg_number] = msgr;
252 mpic_msgr_disable(msgr);
253 dev_info(&dev->dev, "Register %d initialized: irq %d\n",
254 reg_number, msgr->irq);
255
256 }
257
258 return 0;
259}
260
261static const struct of_device_id mpic_msgr_ids[] = {
262 {
263 .compatible = "fsl,mpic-v3.1-msgr",
264 .data = NULL,
265 },
266 {}
267};
268
269static struct platform_driver mpic_msgr_driver = {
270 .driver = {
271 .name = "mpic-msgr",
272 .owner = THIS_MODULE,
273 .of_match_table = mpic_msgr_ids,
274 },
275 .probe = mpic_msgr_probe,
276};
277
278static __init int mpic_msgr_init(void)
279{
280 return platform_driver_register(&mpic_msgr_driver);
281}
282subsys_initcall(mpic_msgr_init);
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 0622aa91b18a..bbf342c88314 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -54,7 +54,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
54 for (i = 100; i < 105; i++) 54 for (i = 100; i < 105; i++)
55 msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 55 msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
56 56
57 for (i = 124; i < mpic->irq_count; i++) 57 for (i = 124; i < mpic->num_sources; i++)
58 msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); 58 msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
59 59
60 60
@@ -83,7 +83,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
83{ 83{
84 int rc; 84 int rc;
85 85
86 rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count, 86 rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->num_sources,
87 mpic->irqhost->of_node); 87 mpic->irqhost->of_node);
88 if (rc) 88 if (rc)
89 return rc; 89 return rc;
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 4f05f7542346..56e8b3c3c890 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1050,6 +1050,74 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
1050 .check_link = ppc4xx_pciex_check_link_sdr, 1050 .check_link = ppc4xx_pciex_check_link_sdr,
1051}; 1051};
1052 1052
1053static int __init apm821xx_pciex_core_init(struct device_node *np)
1054{
1055 /* Return the number of pcie port */
1056 return 1;
1057}
1058
1059static int apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
1060{
1061 u32 val;
1062
1063 /*
1064 * Do a software reset on PCIe ports.
1065 * This code is to fix the issue that pci drivers doesn't re-assign
1066 * bus number for PCIE devices after Uboot
1067 * scanned and configured all the buses (eg. PCIE NIC IntelPro/1000
1068 * PT quad port, SAS LSI 1064E)
1069 */
1070
1071 mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x0);
1072 mdelay(10);
1073
1074 if (port->endpoint)
1075 val = PTYPE_LEGACY_ENDPOINT << 20;
1076 else
1077 val = PTYPE_ROOT_PORT << 20;
1078
1079 val |= LNKW_X1 << 12;
1080
1081 mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
1082 mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000);
1083 mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000);
1084
1085 mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
1086 mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130);
1087 mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
1088
1089 mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x10000000);
1090 mdelay(50);
1091 mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x30000000);
1092
1093 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
1094 mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
1095 (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
1096
1097 /* Poll for PHY reset */
1098 val = PESDR0_460EX_RSTSTA - port->sdr_base;
1099 if (ppc4xx_pciex_wait_on_sdr(port, val, 0x1, 1, 100)) {
1100 printk(KERN_WARNING "%s: PCIE: Can't reset PHY\n", __func__);
1101 return -EBUSY;
1102 } else {
1103 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
1104 (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
1105 ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
1106 PESDRx_RCSSET_RSTPYN);
1107
1108 port->has_ibpre = 1;
1109 return 0;
1110 }
1111}
1112
1113static struct ppc4xx_pciex_hwops apm821xx_pcie_hwops __initdata = {
1114 .want_sdr = true,
1115 .core_init = apm821xx_pciex_core_init,
1116 .port_init_hw = apm821xx_pciex_init_port_hw,
1117 .setup_utl = ppc460ex_pciex_init_utl,
1118 .check_link = ppc4xx_pciex_check_link_sdr,
1119};
1120
1053static int __init ppc460sx_pciex_core_init(struct device_node *np) 1121static int __init ppc460sx_pciex_core_init(struct device_node *np)
1054{ 1122{
1055 /* HSS drive amplitude */ 1123 /* HSS drive amplitude */
@@ -1362,6 +1430,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
1362 ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops; 1430 ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
1363 if (of_device_is_compatible(np, "ibm,plb-pciex-460sx")) 1431 if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
1364 ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops; 1432 ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops;
1433 if (of_device_is_compatible(np, "ibm,plb-pciex-apm821xx"))
1434 ppc4xx_pciex_hwops = &apm821xx_pcie_hwops;
1365#endif /* CONFIG_44x */ 1435#endif /* CONFIG_44x */
1366#ifdef CONFIG_40x 1436#ifdef CONFIG_40x
1367 if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) 1437 if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index cb95eea74d3d..68a9cbbab450 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -39,7 +39,6 @@
39#include <asm/irq_regs.h> 39#include <asm/irq_regs.h>
40#include <asm/spu.h> 40#include <asm/spu.h>
41#include <asm/spu_priv1.h> 41#include <asm/spu_priv1.h>
42#include <asm/firmware.h>
43#include <asm/setjmp.h> 42#include <asm/setjmp.h>
44#include <asm/reg.h> 43#include <asm/reg.h>
45 44
@@ -1437,7 +1436,8 @@ static void excprint(struct pt_regs *fp)
1437 1436
1438 printf(" current = 0x%lx\n", current); 1437 printf(" current = 0x%lx\n", current);
1439#ifdef CONFIG_PPC64 1438#ifdef CONFIG_PPC64
1440 printf(" paca = 0x%lx\n", get_paca()); 1439 printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n",
1440 local_paca, local_paca->soft_enabled, local_paca->irq_happened);
1441#endif 1441#endif
1442 if (current) { 1442 if (current) {
1443 printf(" pid = %ld, comm = %s\n", 1443 printf(" pid = %ld, comm = %s\n",
@@ -1634,25 +1634,6 @@ static void super_regs(void)
1634 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2)); 1634 mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
1635 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); 1635 printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
1636 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); 1636 printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR));
1637#ifdef CONFIG_PPC_ISERIES
1638 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
1639 struct paca_struct *ptrPaca;
1640 struct lppaca *ptrLpPaca;
1641
1642 /* Dump out relevant Paca data areas. */
1643 printf("Paca: \n");
1644 ptrPaca = get_paca();
1645
1646 printf(" Local Processor Control Area (LpPaca): \n");
1647 ptrLpPaca = ptrPaca->lppaca_ptr;
1648 printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n",
1649 ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1);
1650 printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n",
1651 ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4);
1652 printf(" Saved Gpr5=%.16lx \n",
1653 ptrLpPaca->gpr5_dword.saved_gpr5);
1654 }
1655#endif
1656 1637
1657 return; 1638 return;
1658 } 1639 }
@@ -2644,7 +2625,7 @@ static void dump_slb(void)
2644static void dump_stab(void) 2625static void dump_stab(void)
2645{ 2626{
2646 int i; 2627 int i;
2647 unsigned long *tmp = (unsigned long *)get_paca()->stab_addr; 2628 unsigned long *tmp = (unsigned long *)local_paca->stab_addr;
2648 2629
2649 printf("Segment table contents of cpu %x\n", smp_processor_id()); 2630 printf("Segment table contents of cpu %x\n", smp_processor_id());
2650 2631
@@ -2855,10 +2836,6 @@ static void dump_tlb_book3e(void)
2855 2836
2856static void xmon_init(int enable) 2837static void xmon_init(int enable)
2857{ 2838{
2858#ifdef CONFIG_PPC_ISERIES
2859 if (firmware_has_feature(FW_FEATURE_ISERIES))
2860 return;
2861#endif
2862 if (enable) { 2839 if (enable) {
2863 __debugger = xmon; 2840 __debugger = xmon;
2864 __debugger_ipi = xmon_ipi; 2841 __debugger_ipi = xmon_ipi;
@@ -2895,10 +2872,6 @@ static struct sysrq_key_op sysrq_xmon_op = {
2895 2872
2896static int __init setup_xmon_sysrq(void) 2873static int __init setup_xmon_sysrq(void)
2897{ 2874{
2898#ifdef CONFIG_PPC_ISERIES
2899 if (firmware_has_feature(FW_FEATURE_ISERIES))
2900 return 0;
2901#endif
2902 register_sysrq_key('x', &sysrq_xmon_op); 2875 register_sysrq_key('x', &sysrq_xmon_op);
2903 return 0; 2876 return 0;
2904} 2877}
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 60e4f77ca662..3ec3896c83a6 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -123,36 +123,6 @@ void driver_remove_file(struct device_driver *drv,
123} 123}
124EXPORT_SYMBOL_GPL(driver_remove_file); 124EXPORT_SYMBOL_GPL(driver_remove_file);
125 125
126/**
127 * driver_add_kobj - add a kobject below the specified driver
128 * @drv: requesting device driver
129 * @kobj: kobject to add below this driver
130 * @fmt: format string that names the kobject
131 *
132 * You really don't want to do this, this is only here due to one looney
133 * iseries driver, go poke those developers if you are annoyed about
134 * this...
135 */
136int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
137 const char *fmt, ...)
138{
139 va_list args;
140 char *name;
141 int ret;
142
143 va_start(args, fmt);
144 name = kvasprintf(GFP_KERNEL, fmt, args);
145 va_end(args);
146
147 if (!name)
148 return -ENOMEM;
149
150 ret = kobject_add(kobj, &drv->p->kobj, "%s", name);
151 kfree(name);
152 return ret;
153}
154EXPORT_SYMBOL_GPL(driver_add_kobj);
155
156static int driver_add_groups(struct device_driver *drv, 126static int driver_add_groups(struct device_driver *drv,
157 const struct attribute_group **groups) 127 const struct attribute_group **groups)
158{ 128{
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
deleted file mode 100644
index 9a5b2a2d616d..000000000000
--- a/drivers/block/viodasd.c
+++ /dev/null
@@ -1,809 +0,0 @@
1/* -*- linux-c -*-
2 * viodasd.c
3 * Authors: Dave Boutcher <boutcher@us.ibm.com>
4 * Ryan Arnold <ryanarn@us.ibm.com>
5 * Colin Devilbiss <devilbis@us.ibm.com>
6 * Stephen Rothwell
7 *
8 * (C) Copyright 2000-2004 IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * This routine provides access to disk space (termed "DASD" in historical
25 * IBM terms) owned and managed by an OS/400 partition running on the
26 * same box as this Linux partition.
27 *
28 * All disk operations are performed by sending messages back and forth to
29 * the OS/400 partition.
30 */
31
32#define pr_fmt(fmt) "viod: " fmt
33
34#include <linux/major.h>
35#include <linux/fs.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/blkdev.h>
39#include <linux/genhd.h>
40#include <linux/hdreg.h>
41#include <linux/errno.h>
42#include <linux/init.h>
43#include <linux/string.h>
44#include <linux/mutex.h>
45#include <linux/dma-mapping.h>
46#include <linux/completion.h>
47#include <linux/device.h>
48#include <linux/scatterlist.h>
49
50#include <asm/uaccess.h>
51#include <asm/vio.h>
52#include <asm/iseries/hv_types.h>
53#include <asm/iseries/hv_lp_event.h>
54#include <asm/iseries/hv_lp_config.h>
55#include <asm/iseries/vio.h>
56#include <asm/firmware.h>
57
58MODULE_DESCRIPTION("iSeries Virtual DASD");
59MODULE_AUTHOR("Dave Boutcher");
60MODULE_LICENSE("GPL");
61
62/*
63 * We only support 7 partitions per physical disk....so with minor
64 * numbers 0-255 we get a maximum of 32 disks.
65 */
66#define VIOD_GENHD_NAME "iseries/vd"
67
68#define VIOD_VERS "1.64"
69
70enum {
71 PARTITION_SHIFT = 3,
72 MAX_DISKNO = HVMAXARCHITECTEDVIRTUALDISKS,
73 MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
74};
75
76static DEFINE_MUTEX(viodasd_mutex);
77static DEFINE_SPINLOCK(viodasd_spinlock);
78
79#define VIOMAXREQ 16
80
81#define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0])
82
83struct viodasd_waitevent {
84 struct completion com;
85 int rc;
86 u16 sub_result;
87 int max_disk; /* open */
88};
89
90static const struct vio_error_entry viodasd_err_table[] = {
91 { 0x0201, EINVAL, "Invalid Range" },
92 { 0x0202, EINVAL, "Invalid Token" },
93 { 0x0203, EIO, "DMA Error" },
94 { 0x0204, EIO, "Use Error" },
95 { 0x0205, EIO, "Release Error" },
96 { 0x0206, EINVAL, "Invalid Disk" },
97 { 0x0207, EBUSY, "Can't Lock" },
98 { 0x0208, EIO, "Already Locked" },
99 { 0x0209, EIO, "Already Unlocked" },
100 { 0x020A, EIO, "Invalid Arg" },
101 { 0x020B, EIO, "Bad IFS File" },
102 { 0x020C, EROFS, "Read Only Device" },
103 { 0x02FF, EIO, "Internal Error" },
104 { 0x0000, 0, NULL },
105};
106
107/*
108 * Figure out the biggest I/O request (in sectors) we can accept
109 */
110#define VIODASD_MAXSECTORS (4096 / 512 * VIOMAXBLOCKDMA)
111
112/*
113 * Number of disk I/O requests we've sent to OS/400
114 */
115static int num_req_outstanding;
116
117/*
118 * This is our internal structure for keeping track of disk devices
119 */
120struct viodasd_device {
121 u16 cylinders;
122 u16 tracks;
123 u16 sectors;
124 u16 bytes_per_sector;
125 u64 size;
126 int read_only;
127 spinlock_t q_lock;
128 struct gendisk *disk;
129 struct device *dev;
130} viodasd_devices[MAX_DISKNO];
131
132/*
133 * External open entry point.
134 */
135static int viodasd_open(struct block_device *bdev, fmode_t mode)
136{
137 struct viodasd_device *d = bdev->bd_disk->private_data;
138 HvLpEvent_Rc hvrc;
139 struct viodasd_waitevent we;
140 u16 flags = 0;
141
142 if (d->read_only) {
143 if (mode & FMODE_WRITE)
144 return -EROFS;
145 flags = vioblockflags_ro;
146 }
147
148 init_completion(&we.com);
149
150 /* Send the open event to OS/400 */
151 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
152 HvLpEvent_Type_VirtualIo,
153 viomajorsubtype_blockio | vioblockopen,
154 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
155 viopath_sourceinst(viopath_hostLp),
156 viopath_targetinst(viopath_hostLp),
157 (u64)(unsigned long)&we, VIOVERSION << 16,
158 ((u64)DEVICE_NO(d) << 48) | ((u64)flags << 32),
159 0, 0, 0);
160 if (hvrc != 0) {
161 pr_warning("HV open failed %d\n", (int)hvrc);
162 return -EIO;
163 }
164
165 wait_for_completion(&we.com);
166
167 /* Check the return code */
168 if (we.rc != 0) {
169 const struct vio_error_entry *err =
170 vio_lookup_rc(viodasd_err_table, we.sub_result);
171
172 pr_warning("bad rc opening disk: %d:0x%04x (%s)\n",
173 (int)we.rc, we.sub_result, err->msg);
174 return -EIO;
175 }
176
177 return 0;
178}
179
180static int viodasd_unlocked_open(struct block_device *bdev, fmode_t mode)
181{
182 int ret;
183
184 mutex_lock(&viodasd_mutex);
185 ret = viodasd_open(bdev, mode);
186 mutex_unlock(&viodasd_mutex);
187
188 return ret;
189}
190
191
192/*
193 * External release entry point.
194 */
195static int viodasd_release(struct gendisk *disk, fmode_t mode)
196{
197 struct viodasd_device *d = disk->private_data;
198 HvLpEvent_Rc hvrc;
199
200 mutex_lock(&viodasd_mutex);
201 /* Send the event to OS/400. We DON'T expect a response */
202 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
203 HvLpEvent_Type_VirtualIo,
204 viomajorsubtype_blockio | vioblockclose,
205 HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
206 viopath_sourceinst(viopath_hostLp),
207 viopath_targetinst(viopath_hostLp),
208 0, VIOVERSION << 16,
209 ((u64)DEVICE_NO(d) << 48) /* | ((u64)flags << 32) */,
210 0, 0, 0);
211 if (hvrc != 0)
212 pr_warning("HV close call failed %d\n", (int)hvrc);
213
214 mutex_unlock(&viodasd_mutex);
215
216 return 0;
217}
218
219
220/* External ioctl entry point.
221 */
222static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
223{
224 struct gendisk *disk = bdev->bd_disk;
225 struct viodasd_device *d = disk->private_data;
226
227 geo->sectors = d->sectors ? d->sectors : 32;
228 geo->heads = d->tracks ? d->tracks : 64;
229 geo->cylinders = d->cylinders ? d->cylinders :
230 get_capacity(disk) / (geo->sectors * geo->heads);
231
232 return 0;
233}
234
235/*
236 * Our file operations table
237 */
238static const struct block_device_operations viodasd_fops = {
239 .owner = THIS_MODULE,
240 .open = viodasd_unlocked_open,
241 .release = viodasd_release,
242 .getgeo = viodasd_getgeo,
243};
244
245/*
246 * End a request
247 */
248static void viodasd_end_request(struct request *req, int error,
249 int num_sectors)
250{
251 __blk_end_request(req, error, num_sectors << 9);
252}
253
254/*
255 * Send an actual I/O request to OS/400
256 */
257static int send_request(struct request *req)
258{
259 u64 start;
260 int direction;
261 int nsg;
262 u16 viocmd;
263 HvLpEvent_Rc hvrc;
264 struct vioblocklpevent *bevent;
265 struct HvLpEvent *hev;
266 struct scatterlist sg[VIOMAXBLOCKDMA];
267 int sgindex;
268 struct viodasd_device *d;
269 unsigned long flags;
270
271 start = (u64)blk_rq_pos(req) << 9;
272
273 if (rq_data_dir(req) == READ) {
274 direction = DMA_FROM_DEVICE;
275 viocmd = viomajorsubtype_blockio | vioblockread;
276 } else {
277 direction = DMA_TO_DEVICE;
278 viocmd = viomajorsubtype_blockio | vioblockwrite;
279 }
280
281 d = req->rq_disk->private_data;
282
283 /* Now build the scatter-gather list */
284 sg_init_table(sg, VIOMAXBLOCKDMA);
285 nsg = blk_rq_map_sg(req->q, req, sg);
286 nsg = dma_map_sg(d->dev, sg, nsg, direction);
287
288 spin_lock_irqsave(&viodasd_spinlock, flags);
289 num_req_outstanding++;
290
291 /* This optimization handles a single DMA block */
292 if (nsg == 1)
293 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
294 HvLpEvent_Type_VirtualIo, viocmd,
295 HvLpEvent_AckInd_DoAck,
296 HvLpEvent_AckType_ImmediateAck,
297 viopath_sourceinst(viopath_hostLp),
298 viopath_targetinst(viopath_hostLp),
299 (u64)(unsigned long)req, VIOVERSION << 16,
300 ((u64)DEVICE_NO(d) << 48), start,
301 ((u64)sg_dma_address(&sg[0])) << 32,
302 sg_dma_len(&sg[0]));
303 else {
304 bevent = (struct vioblocklpevent *)
305 vio_get_event_buffer(viomajorsubtype_blockio);
306 if (bevent == NULL) {
307 pr_warning("error allocating disk event buffer\n");
308 goto error_ret;
309 }
310
311 /*
312 * Now build up the actual request. Note that we store
313 * the pointer to the request in the correlation
314 * token so we can match the response up later
315 */
316 memset(bevent, 0, sizeof(struct vioblocklpevent));
317 hev = &bevent->event;
318 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK |
319 HV_LP_EVENT_INT;
320 hev->xType = HvLpEvent_Type_VirtualIo;
321 hev->xSubtype = viocmd;
322 hev->xSourceLp = HvLpConfig_getLpIndex();
323 hev->xTargetLp = viopath_hostLp;
324 hev->xSizeMinus1 =
325 offsetof(struct vioblocklpevent, u.rw_data.dma_info) +
326 (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1;
327 hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp);
328 hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp);
329 hev->xCorrelationToken = (u64)req;
330 bevent->version = VIOVERSION;
331 bevent->disk = DEVICE_NO(d);
332 bevent->u.rw_data.offset = start;
333
334 /*
335 * Copy just the dma information from the sg list
336 * into the request
337 */
338 for (sgindex = 0; sgindex < nsg; sgindex++) {
339 bevent->u.rw_data.dma_info[sgindex].token =
340 sg_dma_address(&sg[sgindex]);
341 bevent->u.rw_data.dma_info[sgindex].len =
342 sg_dma_len(&sg[sgindex]);
343 }
344
345 /* Send the request */
346 hvrc = HvCallEvent_signalLpEvent(&bevent->event);
347 vio_free_event_buffer(viomajorsubtype_blockio, bevent);
348 }
349
350 if (hvrc != HvLpEvent_Rc_Good) {
351 pr_warning("error sending disk event to OS/400 (rc %d)\n",
352 (int)hvrc);
353 goto error_ret;
354 }
355 spin_unlock_irqrestore(&viodasd_spinlock, flags);
356 return 0;
357
358error_ret:
359 num_req_outstanding--;
360 spin_unlock_irqrestore(&viodasd_spinlock, flags);
361 dma_unmap_sg(d->dev, sg, nsg, direction);
362 return -1;
363}
364
365/*
366 * This is the external request processing routine
367 */
368static void do_viodasd_request(struct request_queue *q)
369{
370 struct request *req;
371
372 /*
373 * If we already have the maximum number of requests
374 * outstanding to OS/400 just bail out. We'll come
375 * back later.
376 */
377 while (num_req_outstanding < VIOMAXREQ) {
378 req = blk_fetch_request(q);
379 if (req == NULL)
380 return;
381 /* check that request contains a valid command */
382 if (req->cmd_type != REQ_TYPE_FS) {
383 viodasd_end_request(req, -EIO, blk_rq_sectors(req));
384 continue;
385 }
386 /* Try sending the request */
387 if (send_request(req) != 0)
388 viodasd_end_request(req, -EIO, blk_rq_sectors(req));
389 }
390}
391
392/*
393 * Probe a single disk and fill in the viodasd_device structure
394 * for it.
395 */
396static int probe_disk(struct viodasd_device *d)
397{
398 HvLpEvent_Rc hvrc;
399 struct viodasd_waitevent we;
400 int dev_no = DEVICE_NO(d);
401 struct gendisk *g;
402 struct request_queue *q;
403 u16 flags = 0;
404
405retry:
406 init_completion(&we.com);
407
408 /* Send the open event to OS/400 */
409 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
410 HvLpEvent_Type_VirtualIo,
411 viomajorsubtype_blockio | vioblockopen,
412 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
413 viopath_sourceinst(viopath_hostLp),
414 viopath_targetinst(viopath_hostLp),
415 (u64)(unsigned long)&we, VIOVERSION << 16,
416 ((u64)dev_no << 48) | ((u64)flags<< 32),
417 0, 0, 0);
418 if (hvrc != 0) {
419 pr_warning("bad rc on HV open %d\n", (int)hvrc);
420 return 0;
421 }
422
423 wait_for_completion(&we.com);
424
425 if (we.rc != 0) {
426 if (flags != 0)
427 return 0;
428 /* try again with read only flag set */
429 flags = vioblockflags_ro;
430 goto retry;
431 }
432 if (we.max_disk > (MAX_DISKNO - 1)) {
433 printk_once(KERN_INFO pr_fmt("Only examining the first %d of %d disks connected\n"),
434 MAX_DISKNO, we.max_disk + 1);
435 }
436
437 /* Send the close event to OS/400. We DON'T expect a response */
438 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
439 HvLpEvent_Type_VirtualIo,
440 viomajorsubtype_blockio | vioblockclose,
441 HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
442 viopath_sourceinst(viopath_hostLp),
443 viopath_targetinst(viopath_hostLp),
444 0, VIOVERSION << 16,
445 ((u64)dev_no << 48) | ((u64)flags << 32),
446 0, 0, 0);
447 if (hvrc != 0) {
448 pr_warning("bad rc sending event to OS/400 %d\n", (int)hvrc);
449 return 0;
450 }
451
452 if (d->dev == NULL) {
453 /* this is when we reprobe for new disks */
454 if (vio_create_viodasd(dev_no) == NULL) {
455 pr_warning("cannot allocate virtual device for disk %d\n",
456 dev_no);
457 return 0;
458 }
459 /*
460 * The vio_create_viodasd will have recursed into this
461 * routine with d->dev set to the new vio device and
462 * will finish the setup of the disk below.
463 */
464 return 1;
465 }
466
467 /* create the request queue for the disk */
468 spin_lock_init(&d->q_lock);
469 q = blk_init_queue(do_viodasd_request, &d->q_lock);
470 if (q == NULL) {
471 pr_warning("cannot allocate queue for disk %d\n", dev_no);
472 return 0;
473 }
474 g = alloc_disk(1 << PARTITION_SHIFT);
475 if (g == NULL) {
476 pr_warning("cannot allocate disk structure for disk %d\n",
477 dev_no);
478 blk_cleanup_queue(q);
479 return 0;
480 }
481
482 d->disk = g;
483 blk_queue_max_segments(q, VIOMAXBLOCKDMA);
484 blk_queue_max_hw_sectors(q, VIODASD_MAXSECTORS);
485 g->major = VIODASD_MAJOR;
486 g->first_minor = dev_no << PARTITION_SHIFT;
487 if (dev_no >= 26)
488 snprintf(g->disk_name, sizeof(g->disk_name),
489 VIOD_GENHD_NAME "%c%c",
490 'a' + (dev_no / 26) - 1, 'a' + (dev_no % 26));
491 else
492 snprintf(g->disk_name, sizeof(g->disk_name),
493 VIOD_GENHD_NAME "%c", 'a' + (dev_no % 26));
494 g->fops = &viodasd_fops;
495 g->queue = q;
496 g->private_data = d;
497 g->driverfs_dev = d->dev;
498 set_capacity(g, d->size >> 9);
499
500 pr_info("disk %d: %lu sectors (%lu MB) CHS=%d/%d/%d sector size %d%s\n",
501 dev_no, (unsigned long)(d->size >> 9),
502 (unsigned long)(d->size >> 20),
503 (int)d->cylinders, (int)d->tracks,
504 (int)d->sectors, (int)d->bytes_per_sector,
505 d->read_only ? " (RO)" : "");
506
507 /* register us in the global list */
508 add_disk(g);
509 return 1;
510}
511
512/* returns the total number of scatterlist elements converted */
513static int block_event_to_scatterlist(const struct vioblocklpevent *bevent,
514 struct scatterlist *sg, int *total_len)
515{
516 int i, numsg;
517 const struct rw_data *rw_data = &bevent->u.rw_data;
518 static const int offset =
519 offsetof(struct vioblocklpevent, u.rw_data.dma_info);
520 static const int element_size = sizeof(rw_data->dma_info[0]);
521
522 numsg = ((bevent->event.xSizeMinus1 + 1) - offset) / element_size;
523 if (numsg > VIOMAXBLOCKDMA)
524 numsg = VIOMAXBLOCKDMA;
525
526 *total_len = 0;
527 sg_init_table(sg, VIOMAXBLOCKDMA);
528 for (i = 0; (i < numsg) && (rw_data->dma_info[i].len > 0); ++i) {
529 sg_dma_address(&sg[i]) = rw_data->dma_info[i].token;
530 sg_dma_len(&sg[i]) = rw_data->dma_info[i].len;
531 *total_len += rw_data->dma_info[i].len;
532 }
533 return i;
534}
535
536/*
537 * Restart all queues, starting with the one _after_ the disk given,
538 * thus reducing the chance of starvation of higher numbered disks.
539 */
540static void viodasd_restart_all_queues_starting_from(int first_index)
541{
542 int i;
543
544 for (i = first_index + 1; i < MAX_DISKNO; ++i)
545 if (viodasd_devices[i].disk)
546 blk_run_queue(viodasd_devices[i].disk->queue);
547 for (i = 0; i <= first_index; ++i)
548 if (viodasd_devices[i].disk)
549 blk_run_queue(viodasd_devices[i].disk->queue);
550}
551
552/*
553 * For read and write requests, decrement the number of outstanding requests,
554 * Free the DMA buffers we allocated.
555 */
556static int viodasd_handle_read_write(struct vioblocklpevent *bevent)
557{
558 int num_sg, num_sect, pci_direction, total_len;
559 struct request *req;
560 struct scatterlist sg[VIOMAXBLOCKDMA];
561 struct HvLpEvent *event = &bevent->event;
562 unsigned long irq_flags;
563 struct viodasd_device *d;
564 int error;
565 spinlock_t *qlock;
566
567 num_sg = block_event_to_scatterlist(bevent, sg, &total_len);
568 num_sect = total_len >> 9;
569 if (event->xSubtype == (viomajorsubtype_blockio | vioblockread))
570 pci_direction = DMA_FROM_DEVICE;
571 else
572 pci_direction = DMA_TO_DEVICE;
573 req = (struct request *)bevent->event.xCorrelationToken;
574 d = req->rq_disk->private_data;
575
576 dma_unmap_sg(d->dev, sg, num_sg, pci_direction);
577
578 /*
579 * Since this is running in interrupt mode, we need to make sure
580 * we're not stepping on any global I/O operations
581 */
582 spin_lock_irqsave(&viodasd_spinlock, irq_flags);
583 num_req_outstanding--;
584 spin_unlock_irqrestore(&viodasd_spinlock, irq_flags);
585
586 error = (event->xRc == HvLpEvent_Rc_Good) ? 0 : -EIO;
587 if (error) {
588 const struct vio_error_entry *err;
589 err = vio_lookup_rc(viodasd_err_table, bevent->sub_result);
590 pr_warning("read/write error %d:0x%04x (%s)\n",
591 event->xRc, bevent->sub_result, err->msg);
592 num_sect = blk_rq_sectors(req);
593 }
594 qlock = req->q->queue_lock;
595 spin_lock_irqsave(qlock, irq_flags);
596 viodasd_end_request(req, error, num_sect);
597 spin_unlock_irqrestore(qlock, irq_flags);
598
599 /* Finally, try to get more requests off of this device's queue */
600 viodasd_restart_all_queues_starting_from(DEVICE_NO(d));
601
602 return 0;
603}
604
605/* This routine handles incoming block LP events */
606static void handle_block_event(struct HvLpEvent *event)
607{
608 struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
609 struct viodasd_waitevent *pwe;
610
611 if (event == NULL)
612 /* Notification that a partition went away! */
613 return;
614 /* First, we should NEVER get an int here...only acks */
615 if (hvlpevent_is_int(event)) {
616 pr_warning("Yikes! got an int in viodasd event handler!\n");
617 if (hvlpevent_need_ack(event)) {
618 event->xRc = HvLpEvent_Rc_InvalidSubtype;
619 HvCallEvent_ackLpEvent(event);
620 }
621 }
622
623 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
624 case vioblockopen:
625 /*
626 * Handle a response to an open request. We get all the
627 * disk information in the response, so update it. The
628 * correlation token contains a pointer to a waitevent
629 * structure that has a completion in it. update the
630 * return code in the waitevent structure and post the
631 * completion to wake up the guy who sent the request
632 */
633 pwe = (struct viodasd_waitevent *)event->xCorrelationToken;
634 pwe->rc = event->xRc;
635 pwe->sub_result = bevent->sub_result;
636 if (event->xRc == HvLpEvent_Rc_Good) {
637 const struct open_data *data = &bevent->u.open_data;
638 struct viodasd_device *device =
639 &viodasd_devices[bevent->disk];
640 device->read_only =
641 bevent->flags & vioblockflags_ro;
642 device->size = data->disk_size;
643 device->cylinders = data->cylinders;
644 device->tracks = data->tracks;
645 device->sectors = data->sectors;
646 device->bytes_per_sector = data->bytes_per_sector;
647 pwe->max_disk = data->max_disk;
648 }
649 complete(&pwe->com);
650 break;
651 case vioblockclose:
652 break;
653 case vioblockread:
654 case vioblockwrite:
655 viodasd_handle_read_write(bevent);
656 break;
657
658 default:
659 pr_warning("invalid subtype!");
660 if (hvlpevent_need_ack(event)) {
661 event->xRc = HvLpEvent_Rc_InvalidSubtype;
662 HvCallEvent_ackLpEvent(event);
663 }
664 }
665}
666
667/*
668 * Get the driver to reprobe for more disks.
669 */
670static ssize_t probe_disks(struct device_driver *drv, const char *buf,
671 size_t count)
672{
673 struct viodasd_device *d;
674
675 for (d = viodasd_devices; d < &viodasd_devices[MAX_DISKNO]; d++) {
676 if (d->disk == NULL)
677 probe_disk(d);
678 }
679 return count;
680}
681static DRIVER_ATTR(probe, S_IWUSR, NULL, probe_disks);
682
683static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
684{
685 struct viodasd_device *d = &viodasd_devices[vdev->unit_address];
686
687 d->dev = &vdev->dev;
688 if (!probe_disk(d))
689 return -ENODEV;
690 return 0;
691}
692
693static int viodasd_remove(struct vio_dev *vdev)
694{
695 struct viodasd_device *d;
696
697 d = &viodasd_devices[vdev->unit_address];
698 if (d->disk) {
699 del_gendisk(d->disk);
700 blk_cleanup_queue(d->disk->queue);
701 put_disk(d->disk);
702 d->disk = NULL;
703 }
704 d->dev = NULL;
705 return 0;
706}
707
708/**
709 * viodasd_device_table: Used by vio.c to match devices that we
710 * support.
711 */
712static struct vio_device_id viodasd_device_table[] __devinitdata = {
713 { "block", "IBM,iSeries-viodasd" },
714 { "", "" }
715};
716MODULE_DEVICE_TABLE(vio, viodasd_device_table);
717
718static struct vio_driver viodasd_driver = {
719 .id_table = viodasd_device_table,
720 .probe = viodasd_probe,
721 .remove = viodasd_remove,
722 .driver = {
723 .name = "viodasd",
724 .owner = THIS_MODULE,
725 }
726};
727
728static int need_delete_probe;
729
730/*
731 * Initialize the whole device driver. Handle module and non-module
732 * versions
733 */
734static int __init viodasd_init(void)
735{
736 int rc;
737
738 if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
739 rc = -ENODEV;
740 goto early_fail;
741 }
742
743 /* Try to open to our host lp */
744 if (viopath_hostLp == HvLpIndexInvalid)
745 vio_set_hostlp();
746
747 if (viopath_hostLp == HvLpIndexInvalid) {
748 pr_warning("invalid hosting partition\n");
749 rc = -EIO;
750 goto early_fail;
751 }
752
753 pr_info("vers " VIOD_VERS ", hosting partition %d\n", viopath_hostLp);
754
755 /* register the block device */
756 rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
757 if (rc) {
758 pr_warning("Unable to get major number %d for %s\n",
759 VIODASD_MAJOR, VIOD_GENHD_NAME);
760 goto early_fail;
761 }
762 /* Actually open the path to the hosting partition */
763 rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio,
764 VIOMAXREQ + 2);
765 if (rc) {
766 pr_warning("error opening path to host partition %d\n",
767 viopath_hostLp);
768 goto unregister_blk;
769 }
770
771 /* Initialize our request handler */
772 vio_setHandler(viomajorsubtype_blockio, handle_block_event);
773
774 rc = vio_register_driver(&viodasd_driver);
775 if (rc) {
776 pr_warning("vio_register_driver failed\n");
777 goto unset_handler;
778 }
779
780 /*
781 * If this call fails, it just means that we cannot dynamically
782 * add virtual disks, but the driver will still work fine for
783 * all existing disk, so ignore the failure.
784 */
785 if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe))
786 need_delete_probe = 1;
787
788 return 0;
789
790unset_handler:
791 vio_clearHandler(viomajorsubtype_blockio);
792 viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
793unregister_blk:
794 unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
795early_fail:
796 return rc;
797}
798module_init(viodasd_init);
799
800void __exit viodasd_exit(void)
801{
802 if (need_delete_probe)
803 driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
804 vio_unregister_driver(&viodasd_driver);
805 vio_clearHandler(viomajorsubtype_blockio);
806 viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
807 unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
808}
809module_exit(viodasd_exit);
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
deleted file mode 100644
index 7878da89d29e..000000000000
--- a/drivers/cdrom/viocd.c
+++ /dev/null
@@ -1,739 +0,0 @@
1/* -*- linux-c -*-
2 * drivers/cdrom/viocd.c
3 *
4 * iSeries Virtual CD Rom
5 *
6 * Authors: Dave Boutcher <boutcher@us.ibm.com>
7 * Ryan Arnold <ryanarn@us.ibm.com>
8 * Colin Devilbiss <devilbis@us.ibm.com>
9 * Stephen Rothwell
10 *
11 * (C) Copyright 2000-2004 IBM Corporation
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) anyu later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * This routine provides access to CD ROM drives owned and managed by an
28 * OS/400 partition running on the same box as this Linux partition.
29 *
30 * All operations are performed by sending messages back and forth to
31 * the OS/400 partition.
32 */
33
34#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
35
36#include <linux/major.h>
37#include <linux/blkdev.h>
38#include <linux/cdrom.h>
39#include <linux/errno.h>
40#include <linux/init.h>
41#include <linux/dma-mapping.h>
42#include <linux/module.h>
43#include <linux/completion.h>
44#include <linux/proc_fs.h>
45#include <linux/mutex.h>
46#include <linux/seq_file.h>
47#include <linux/scatterlist.h>
48
49#include <asm/vio.h>
50#include <asm/iseries/hv_types.h>
51#include <asm/iseries/hv_lp_event.h>
52#include <asm/iseries/vio.h>
53#include <asm/firmware.h>
54
55#define VIOCD_DEVICE "iseries/vcd"
56
57#define VIOCD_VERS "1.06"
58
59/*
60 * Should probably make this a module parameter....sigh
61 */
62#define VIOCD_MAX_CD HVMAXARCHITECTEDVIRTUALCDROMS
63
64static DEFINE_MUTEX(viocd_mutex);
65static const struct vio_error_entry viocd_err_table[] = {
66 {0x0201, EINVAL, "Invalid Range"},
67 {0x0202, EINVAL, "Invalid Token"},
68 {0x0203, EIO, "DMA Error"},
69 {0x0204, EIO, "Use Error"},
70 {0x0205, EIO, "Release Error"},
71 {0x0206, EINVAL, "Invalid CD"},
72 {0x020C, EROFS, "Read Only Device"},
73 {0x020D, ENOMEDIUM, "Changed or Missing Volume (or Varied Off?)"},
74 {0x020E, EIO, "Optical System Error (Varied Off?)"},
75 {0x02FF, EIO, "Internal Error"},
76 {0x3010, EIO, "Changed Volume"},
77 {0xC100, EIO, "Optical System Error"},
78 {0x0000, 0, NULL},
79};
80
81/*
82 * This is the structure we use to exchange info between driver and interrupt
83 * handler
84 */
85struct viocd_waitevent {
86 struct completion com;
87 int rc;
88 u16 sub_result;
89 int changed;
90};
91
92/* this is a lookup table for the true capabilities of a device */
93struct capability_entry {
94 char *type;
95 int capability;
96};
97
98static struct capability_entry capability_table[] __initdata = {
99 { "6330", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
100 { "6331", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
101 { "6333", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
102 { "632A", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
103 { "6321", CDC_LOCK },
104 { "632B", 0 },
105 { NULL , CDC_LOCK },
106};
107
108/* These are our internal structures for keeping track of devices */
109static int viocd_numdev;
110
111struct disk_info {
112 struct gendisk *viocd_disk;
113 struct cdrom_device_info viocd_info;
114 struct device *dev;
115 const char *rsrcname;
116 const char *type;
117 const char *model;
118};
119static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
120
121#define DEVICE_NR(di) ((di) - &viocd_diskinfo[0])
122
123static spinlock_t viocd_reqlock;
124
125#define MAX_CD_REQ 1
126
127/* procfs support */
128static int proc_viocd_show(struct seq_file *m, void *v)
129{
130 int i;
131
132 for (i = 0; i < viocd_numdev; i++) {
133 seq_printf(m, "viocd device %d is iSeries resource %10.10s"
134 "type %4.4s, model %3.3s\n",
135 i, viocd_diskinfo[i].rsrcname,
136 viocd_diskinfo[i].type,
137 viocd_diskinfo[i].model);
138 }
139 return 0;
140}
141
142static int proc_viocd_open(struct inode *inode, struct file *file)
143{
144 return single_open(file, proc_viocd_show, NULL);
145}
146
147static const struct file_operations proc_viocd_operations = {
148 .owner = THIS_MODULE,
149 .open = proc_viocd_open,
150 .read = seq_read,
151 .llseek = seq_lseek,
152 .release = single_release,
153};
154
155static int viocd_blk_open(struct block_device *bdev, fmode_t mode)
156{
157 struct disk_info *di = bdev->bd_disk->private_data;
158 int ret;
159
160 mutex_lock(&viocd_mutex);
161 ret = cdrom_open(&di->viocd_info, bdev, mode);
162 mutex_unlock(&viocd_mutex);
163
164 return ret;
165}
166
167static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
168{
169 struct disk_info *di = disk->private_data;
170 mutex_lock(&viocd_mutex);
171 cdrom_release(&di->viocd_info, mode);
172 mutex_unlock(&viocd_mutex);
173 return 0;
174}
175
176static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode,
177 unsigned cmd, unsigned long arg)
178{
179 struct disk_info *di = bdev->bd_disk->private_data;
180 int ret;
181
182 mutex_lock(&viocd_mutex);
183 ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
184 mutex_unlock(&viocd_mutex);
185
186 return ret;
187}
188
189static unsigned int viocd_blk_check_events(struct gendisk *disk,
190 unsigned int clearing)
191{
192 struct disk_info *di = disk->private_data;
193 return cdrom_check_events(&di->viocd_info, clearing);
194}
195
196static const struct block_device_operations viocd_fops = {
197 .owner = THIS_MODULE,
198 .open = viocd_blk_open,
199 .release = viocd_blk_release,
200 .ioctl = viocd_blk_ioctl,
201 .check_events = viocd_blk_check_events,
202};
203
204static int viocd_open(struct cdrom_device_info *cdi, int purpose)
205{
206 struct disk_info *diskinfo = cdi->handle;
207 int device_no = DEVICE_NR(diskinfo);
208 HvLpEvent_Rc hvrc;
209 struct viocd_waitevent we;
210
211 init_completion(&we.com);
212 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
213 HvLpEvent_Type_VirtualIo,
214 viomajorsubtype_cdio | viocdopen,
215 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
216 viopath_sourceinst(viopath_hostLp),
217 viopath_targetinst(viopath_hostLp),
218 (u64)&we, VIOVERSION << 16, ((u64)device_no << 48),
219 0, 0, 0);
220 if (hvrc != 0) {
221 pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
222 (int)hvrc);
223 return -EIO;
224 }
225
226 wait_for_completion(&we.com);
227
228 if (we.rc) {
229 const struct vio_error_entry *err =
230 vio_lookup_rc(viocd_err_table, we.sub_result);
231 pr_warning("bad rc %d:0x%04X on open: %s\n",
232 we.rc, we.sub_result, err->msg);
233 return -err->errno;
234 }
235
236 return 0;
237}
238
239static void viocd_release(struct cdrom_device_info *cdi)
240{
241 int device_no = DEVICE_NR((struct disk_info *)cdi->handle);
242 HvLpEvent_Rc hvrc;
243
244 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
245 HvLpEvent_Type_VirtualIo,
246 viomajorsubtype_cdio | viocdclose,
247 HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
248 viopath_sourceinst(viopath_hostLp),
249 viopath_targetinst(viopath_hostLp), 0,
250 VIOVERSION << 16, ((u64)device_no << 48), 0, 0, 0);
251 if (hvrc != 0)
252 pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
253 (int)hvrc);
254}
255
256/* Send a read or write request to OS/400 */
257static int send_request(struct request *req)
258{
259 HvLpEvent_Rc hvrc;
260 struct disk_info *diskinfo = req->rq_disk->private_data;
261 u64 len;
262 dma_addr_t dmaaddr;
263 int direction;
264 u16 cmd;
265 struct scatterlist sg;
266
267 BUG_ON(req->nr_phys_segments > 1);
268
269 if (rq_data_dir(req) == READ) {
270 direction = DMA_FROM_DEVICE;
271 cmd = viomajorsubtype_cdio | viocdread;
272 } else {
273 direction = DMA_TO_DEVICE;
274 cmd = viomajorsubtype_cdio | viocdwrite;
275 }
276
277 sg_init_table(&sg, 1);
278 if (blk_rq_map_sg(req->q, req, &sg) == 0) {
279 pr_warning("error setting up scatter/gather list\n");
280 return -1;
281 }
282
283 if (dma_map_sg(diskinfo->dev, &sg, 1, direction) == 0) {
284 pr_warning("error allocating sg tce\n");
285 return -1;
286 }
287 dmaaddr = sg_dma_address(&sg);
288 len = sg_dma_len(&sg);
289
290 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
291 HvLpEvent_Type_VirtualIo, cmd,
292 HvLpEvent_AckInd_DoAck,
293 HvLpEvent_AckType_ImmediateAck,
294 viopath_sourceinst(viopath_hostLp),
295 viopath_targetinst(viopath_hostLp),
296 (u64)req, VIOVERSION << 16,
297 ((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr,
298 (u64)blk_rq_pos(req) * 512, len, 0);
299 if (hvrc != HvLpEvent_Rc_Good) {
300 pr_warning("hv error on op %d\n", (int)hvrc);
301 return -1;
302 }
303
304 return 0;
305}
306
307static int rwreq;
308
309static void do_viocd_request(struct request_queue *q)
310{
311 struct request *req;
312
313 while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) {
314 if (req->cmd_type != REQ_TYPE_FS)
315 __blk_end_request_all(req, -EIO);
316 else if (send_request(req) < 0) {
317 pr_warning("unable to send message to OS/400!\n");
318 __blk_end_request_all(req, -EIO);
319 } else
320 rwreq++;
321 }
322}
323
324static unsigned int viocd_check_events(struct cdrom_device_info *cdi,
325 unsigned int clearing, int disc_nr)
326{
327 struct viocd_waitevent we;
328 HvLpEvent_Rc hvrc;
329 int device_no = DEVICE_NR((struct disk_info *)cdi->handle);
330
331 init_completion(&we.com);
332
333 /* Send the open event to OS/400 */
334 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
335 HvLpEvent_Type_VirtualIo,
336 viomajorsubtype_cdio | viocdcheck,
337 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
338 viopath_sourceinst(viopath_hostLp),
339 viopath_targetinst(viopath_hostLp),
340 (u64)&we, VIOVERSION << 16, ((u64)device_no << 48),
341 0, 0, 0);
342 if (hvrc != 0) {
343 pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
344 (int)hvrc);
345 return 0;
346 }
347
348 wait_for_completion(&we.com);
349
350 /* Check the return code. If bad, assume no change */
351 if (we.rc) {
352 const struct vio_error_entry *err =
353 vio_lookup_rc(viocd_err_table, we.sub_result);
354 pr_warning("bad rc %d:0x%04X on check_change: %s; Assuming no change\n",
355 we.rc, we.sub_result, err->msg);
356 return 0;
357 }
358
359 return we.changed ? DISK_EVENT_MEDIA_CHANGE : 0;
360}
361
362static int viocd_lock_door(struct cdrom_device_info *cdi, int locking)
363{
364 HvLpEvent_Rc hvrc;
365 u64 device_no = DEVICE_NR((struct disk_info *)cdi->handle);
366 /* NOTE: flags is 1 or 0 so it won't overwrite the device_no */
367 u64 flags = !!locking;
368 struct viocd_waitevent we;
369
370 init_completion(&we.com);
371
372 /* Send the lockdoor event to OS/400 */
373 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
374 HvLpEvent_Type_VirtualIo,
375 viomajorsubtype_cdio | viocdlockdoor,
376 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
377 viopath_sourceinst(viopath_hostLp),
378 viopath_targetinst(viopath_hostLp),
379 (u64)&we, VIOVERSION << 16,
380 (device_no << 48) | (flags << 32), 0, 0, 0);
381 if (hvrc != 0) {
382 pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
383 (int)hvrc);
384 return -EIO;
385 }
386
387 wait_for_completion(&we.com);
388
389 if (we.rc != 0)
390 return -EIO;
391 return 0;
392}
393
394static int viocd_packet(struct cdrom_device_info *cdi,
395 struct packet_command *cgc)
396{
397 unsigned int buflen = cgc->buflen;
398 int ret = -EIO;
399
400 switch (cgc->cmd[0]) {
401 case GPCMD_READ_DISC_INFO:
402 {
403 disc_information *di = (disc_information *)cgc->buffer;
404
405 if (buflen >= 2) {
406 di->disc_information_length = cpu_to_be16(1);
407 ret = 0;
408 }
409 if (buflen >= 3)
410 di->erasable =
411 (cdi->ops->capability & ~cdi->mask
412 & (CDC_DVD_RAM | CDC_RAM)) != 0;
413 }
414 break;
415 case GPCMD_GET_CONFIGURATION:
416 if (cgc->cmd[3] == CDF_RWRT) {
417 struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header));
418
419 if ((buflen >=
420 (sizeof(struct feature_header) + sizeof(*rfd))) &&
421 (cdi->ops->capability & ~cdi->mask
422 & (CDC_DVD_RAM | CDC_RAM))) {
423 rfd->feature_code = cpu_to_be16(CDF_RWRT);
424 rfd->curr = 1;
425 ret = 0;
426 }
427 }
428 break;
429 default:
430 if (cgc->sense) {
431 /* indicate Unknown code */
432 cgc->sense->sense_key = 0x05;
433 cgc->sense->asc = 0x20;
434 cgc->sense->ascq = 0x00;
435 }
436 break;
437 }
438
439 cgc->stat = ret;
440 return ret;
441}
442
443static void restart_all_queues(int first_index)
444{
445 int i;
446
447 for (i = first_index + 1; i < viocd_numdev; i++)
448 if (viocd_diskinfo[i].viocd_disk)
449 blk_run_queue(viocd_diskinfo[i].viocd_disk->queue);
450 for (i = 0; i <= first_index; i++)
451 if (viocd_diskinfo[i].viocd_disk)
452 blk_run_queue(viocd_diskinfo[i].viocd_disk->queue);
453}
454
455/* This routine handles incoming CD LP events */
456static void vio_handle_cd_event(struct HvLpEvent *event)
457{
458 struct viocdlpevent *bevent;
459 struct viocd_waitevent *pwe;
460 struct disk_info *di;
461 unsigned long flags;
462 struct request *req;
463
464
465 if (event == NULL)
466 /* Notification that a partition went away! */
467 return;
468 /* First, we should NEVER get an int here...only acks */
469 if (hvlpevent_is_int(event)) {
470 pr_warning("Yikes! got an int in viocd event handler!\n");
471 if (hvlpevent_need_ack(event)) {
472 event->xRc = HvLpEvent_Rc_InvalidSubtype;
473 HvCallEvent_ackLpEvent(event);
474 }
475 }
476
477 bevent = (struct viocdlpevent *)event;
478
479 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
480 case viocdopen:
481 if (event->xRc == 0) {
482 di = &viocd_diskinfo[bevent->disk];
483 blk_queue_logical_block_size(di->viocd_disk->queue,
484 bevent->block_size);
485 set_capacity(di->viocd_disk,
486 bevent->media_size *
487 bevent->block_size / 512);
488 }
489 /* FALLTHROUGH !! */
490 case viocdlockdoor:
491 pwe = (struct viocd_waitevent *)event->xCorrelationToken;
492return_complete:
493 pwe->rc = event->xRc;
494 pwe->sub_result = bevent->sub_result;
495 complete(&pwe->com);
496 break;
497
498 case viocdcheck:
499 pwe = (struct viocd_waitevent *)event->xCorrelationToken;
500 pwe->changed = bevent->flags;
501 goto return_complete;
502
503 case viocdclose:
504 break;
505
506 case viocdwrite:
507 case viocdread:
508 /*
509 * Since this is running in interrupt mode, we need to
510 * make sure we're not stepping on any global I/O operations
511 */
512 di = &viocd_diskinfo[bevent->disk];
513 spin_lock_irqsave(&viocd_reqlock, flags);
514 dma_unmap_single(di->dev, bevent->token, bevent->len,
515 ((event->xSubtype & VIOMINOR_SUBTYPE_MASK) == viocdread)
516 ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
517 req = (struct request *)bevent->event.xCorrelationToken;
518 rwreq--;
519
520 if (event->xRc != HvLpEvent_Rc_Good) {
521 const struct vio_error_entry *err =
522 vio_lookup_rc(viocd_err_table,
523 bevent->sub_result);
524 pr_warning("request %p failed with rc %d:0x%04X: %s\n",
525 req, event->xRc,
526 bevent->sub_result, err->msg);
527 __blk_end_request_all(req, -EIO);
528 } else
529 __blk_end_request_all(req, 0);
530
531 /* restart handling of incoming requests */
532 spin_unlock_irqrestore(&viocd_reqlock, flags);
533 restart_all_queues(bevent->disk);
534 break;
535
536 default:
537 pr_warning("message with invalid subtype %0x04X!\n",
538 event->xSubtype & VIOMINOR_SUBTYPE_MASK);
539 if (hvlpevent_need_ack(event)) {
540 event->xRc = HvLpEvent_Rc_InvalidSubtype;
541 HvCallEvent_ackLpEvent(event);
542 }
543 }
544}
545
546static int viocd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
547 void *arg)
548{
549 return -EINVAL;
550}
551
552static struct cdrom_device_ops viocd_dops = {
553 .open = viocd_open,
554 .release = viocd_release,
555 .check_events = viocd_check_events,
556 .lock_door = viocd_lock_door,
557 .generic_packet = viocd_packet,
558 .audio_ioctl = viocd_audio_ioctl,
559 .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM
560};
561
562static int find_capability(const char *type)
563{
564 struct capability_entry *entry;
565
566 for(entry = capability_table; entry->type; ++entry)
567 if(!strncmp(entry->type, type, 4))
568 break;
569 return entry->capability;
570}
571
572static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
573{
574 struct gendisk *gendisk;
575 int deviceno;
576 struct disk_info *d;
577 struct cdrom_device_info *c;
578 struct request_queue *q;
579 struct device_node *node = vdev->dev.of_node;
580
581 deviceno = vdev->unit_address;
582 if (deviceno >= VIOCD_MAX_CD)
583 return -ENODEV;
584 if (!node)
585 return -ENODEV;
586
587 if (deviceno >= viocd_numdev)
588 viocd_numdev = deviceno + 1;
589
590 d = &viocd_diskinfo[deviceno];
591 d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
592 d->type = of_get_property(node, "linux,vio_type", NULL);
593 d->model = of_get_property(node, "linux,vio_model", NULL);
594
595 c = &d->viocd_info;
596
597 c->ops = &viocd_dops;
598 c->speed = 4;
599 c->capacity = 1;
600 c->handle = d;
601 c->mask = ~find_capability(d->type);
602 sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
603
604 if (register_cdrom(c) != 0) {
605 pr_warning("Cannot register viocd CD-ROM %s!\n", c->name);
606 goto out;
607 }
608 pr_info("cd %s is iSeries resource %10.10s type %4.4s, model %3.3s\n",
609 c->name, d->rsrcname, d->type, d->model);
610 q = blk_init_queue(do_viocd_request, &viocd_reqlock);
611 if (q == NULL) {
612 pr_warning("Cannot allocate queue for %s!\n", c->name);
613 goto out_unregister_cdrom;
614 }
615 gendisk = alloc_disk(1);
616 if (gendisk == NULL) {
617 pr_warning("Cannot create gendisk for %s!\n", c->name);
618 goto out_cleanup_queue;
619 }
620 gendisk->major = VIOCD_MAJOR;
621 gendisk->first_minor = deviceno;
622 strncpy(gendisk->disk_name, c->name,
623 sizeof(gendisk->disk_name));
624 blk_queue_max_segments(q, 1);
625 blk_queue_max_hw_sectors(q, 4096 / 512);
626 gendisk->queue = q;
627 gendisk->fops = &viocd_fops;
628 gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
629 GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
630 set_capacity(gendisk, 0);
631 gendisk->private_data = d;
632 d->viocd_disk = gendisk;
633 d->dev = &vdev->dev;
634 gendisk->driverfs_dev = d->dev;
635 add_disk(gendisk);
636 return 0;
637
638out_cleanup_queue:
639 blk_cleanup_queue(q);
640out_unregister_cdrom:
641 unregister_cdrom(c);
642out:
643 return -ENODEV;
644}
645
646static int viocd_remove(struct vio_dev *vdev)
647{
648 struct disk_info *d = &viocd_diskinfo[vdev->unit_address];
649
650 unregister_cdrom(&d->viocd_info);
651 del_gendisk(d->viocd_disk);
652 blk_cleanup_queue(d->viocd_disk->queue);
653 put_disk(d->viocd_disk);
654 return 0;
655}
656
657/**
658 * viocd_device_table: Used by vio.c to match devices that we
659 * support.
660 */
661static struct vio_device_id viocd_device_table[] __devinitdata = {
662 { "block", "IBM,iSeries-viocd" },
663 { "", "" }
664};
665MODULE_DEVICE_TABLE(vio, viocd_device_table);
666
667static struct vio_driver viocd_driver = {
668 .id_table = viocd_device_table,
669 .probe = viocd_probe,
670 .remove = viocd_remove,
671 .driver = {
672 .name = "viocd",
673 .owner = THIS_MODULE,
674 }
675};
676
677static int __init viocd_init(void)
678{
679 int ret = 0;
680
681 if (!firmware_has_feature(FW_FEATURE_ISERIES))
682 return -ENODEV;
683
684 if (viopath_hostLp == HvLpIndexInvalid) {
685 vio_set_hostlp();
686 /* If we don't have a host, bail out */
687 if (viopath_hostLp == HvLpIndexInvalid)
688 return -ENODEV;
689 }
690
691 pr_info("vers " VIOCD_VERS ", hosting partition %d\n", viopath_hostLp);
692
693 if (register_blkdev(VIOCD_MAJOR, VIOCD_DEVICE) != 0) {
694 pr_warning("Unable to get major %d for %s\n",
695 VIOCD_MAJOR, VIOCD_DEVICE);
696 return -EIO;
697 }
698
699 ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio,
700 MAX_CD_REQ + 2);
701 if (ret) {
702 pr_warning("error opening path to host partition %d\n",
703 viopath_hostLp);
704 goto out_unregister;
705 }
706
707 /* Initialize our request handler */
708 vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
709
710 spin_lock_init(&viocd_reqlock);
711
712 ret = vio_register_driver(&viocd_driver);
713 if (ret)
714 goto out_free_info;
715
716 proc_create("iSeries/viocd", S_IFREG|S_IRUGO, NULL,
717 &proc_viocd_operations);
718 return 0;
719
720out_free_info:
721 vio_clearHandler(viomajorsubtype_cdio);
722 viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
723out_unregister:
724 unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
725 return ret;
726}
727
728static void __exit viocd_exit(void)
729{
730 remove_proc_entry("iSeries/viocd", NULL);
731 vio_unregister_driver(&viocd_driver);
732 viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
733 vio_clearHandler(viomajorsubtype_cdio);
734 unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
735}
736
737module_init(viocd_init);
738module_exit(viocd_exit);
739MODULE_LICENSE("GPL");
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
deleted file mode 100644
index 8b34c65511eb..000000000000
--- a/drivers/char/viotape.c
+++ /dev/null
@@ -1,1041 +0,0 @@
1/* -*- linux-c -*-
2 * drivers/char/viotape.c
3 *
4 * iSeries Virtual Tape
5 *
6 * Authors: Dave Boutcher <boutcher@us.ibm.com>
7 * Ryan Arnold <ryanarn@us.ibm.com>
8 * Colin Devilbiss <devilbis@us.ibm.com>
9 * Stephen Rothwell
10 *
11 * (C) Copyright 2000-2004 IBM Corporation
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) anyu later version.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software Foundation,
25 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * This routine provides access to tape drives owned and managed by an OS/400
28 * partition running on the same box as this Linux partition.
29 *
30 * All tape operations are performed by sending messages back and forth to
31 * the OS/400 partition. The format of the messages is defined in
32 * iseries/vio.h
33 */
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/errno.h>
37#include <linux/init.h>
38#include <linux/wait.h>
39#include <linux/spinlock.h>
40#include <linux/mtio.h>
41#include <linux/device.h>
42#include <linux/dma-mapping.h>
43#include <linux/fs.h>
44#include <linux/cdev.h>
45#include <linux/major.h>
46#include <linux/completion.h>
47#include <linux/proc_fs.h>
48#include <linux/seq_file.h>
49#include <linux/mutex.h>
50#include <linux/slab.h>
51
52#include <asm/uaccess.h>
53#include <asm/ioctls.h>
54#include <asm/firmware.h>
55#include <asm/vio.h>
56#include <asm/iseries/vio.h>
57#include <asm/iseries/hv_lp_event.h>
58#include <asm/iseries/hv_call_event.h>
59#include <asm/iseries/hv_lp_config.h>
60
61#define VIOTAPE_VERSION "1.2"
62#define VIOTAPE_MAXREQ 1
63
64#define VIOTAPE_KERN_WARN KERN_WARNING "viotape: "
65#define VIOTAPE_KERN_INFO KERN_INFO "viotape: "
66
67static DEFINE_MUTEX(proc_viotape_mutex);
68static int viotape_numdev;
69
70/*
71 * The minor number follows the conventions of the SCSI tape drives. The
72 * rewind and mode are encoded in the minor #. We use this struct to break
73 * them out
74 */
75struct viot_devinfo_struct {
76 int devno;
77 int mode;
78 int rewind;
79};
80
81#define VIOTAPOP_RESET 0
82#define VIOTAPOP_FSF 1
83#define VIOTAPOP_BSF 2
84#define VIOTAPOP_FSR 3
85#define VIOTAPOP_BSR 4
86#define VIOTAPOP_WEOF 5
87#define VIOTAPOP_REW 6
88#define VIOTAPOP_NOP 7
89#define VIOTAPOP_EOM 8
90#define VIOTAPOP_ERASE 9
91#define VIOTAPOP_SETBLK 10
92#define VIOTAPOP_SETDENSITY 11
93#define VIOTAPOP_SETPOS 12
94#define VIOTAPOP_GETPOS 13
95#define VIOTAPOP_SETPART 14
96#define VIOTAPOP_UNLOAD 15
97
98enum viotaperc {
99 viotape_InvalidRange = 0x0601,
100 viotape_InvalidToken = 0x0602,
101 viotape_DMAError = 0x0603,
102 viotape_UseError = 0x0604,
103 viotape_ReleaseError = 0x0605,
104 viotape_InvalidTape = 0x0606,
105 viotape_InvalidOp = 0x0607,
106 viotape_TapeErr = 0x0608,
107
108 viotape_AllocTimedOut = 0x0640,
109 viotape_BOTEnc = 0x0641,
110 viotape_BlankTape = 0x0642,
111 viotape_BufferEmpty = 0x0643,
112 viotape_CleanCartFound = 0x0644,
113 viotape_CmdNotAllowed = 0x0645,
114 viotape_CmdNotSupported = 0x0646,
115 viotape_DataCheck = 0x0647,
116 viotape_DecompressErr = 0x0648,
117 viotape_DeviceTimeout = 0x0649,
118 viotape_DeviceUnavail = 0x064a,
119 viotape_DeviceBusy = 0x064b,
120 viotape_EndOfMedia = 0x064c,
121 viotape_EndOfTape = 0x064d,
122 viotape_EquipCheck = 0x064e,
123 viotape_InsufficientRs = 0x064f,
124 viotape_InvalidLogBlk = 0x0650,
125 viotape_LengthError = 0x0651,
126 viotape_LibDoorOpen = 0x0652,
127 viotape_LoadFailure = 0x0653,
128 viotape_NotCapable = 0x0654,
129 viotape_NotOperational = 0x0655,
130 viotape_NotReady = 0x0656,
131 viotape_OpCancelled = 0x0657,
132 viotape_PhyLinkErr = 0x0658,
133 viotape_RdyNotBOT = 0x0659,
134 viotape_TapeMark = 0x065a,
135 viotape_WriteProt = 0x065b
136};
137
138static const struct vio_error_entry viotape_err_table[] = {
139 { viotape_InvalidRange, EIO, "Internal error" },
140 { viotape_InvalidToken, EIO, "Internal error" },
141 { viotape_DMAError, EIO, "DMA error" },
142 { viotape_UseError, EIO, "Internal error" },
143 { viotape_ReleaseError, EIO, "Internal error" },
144 { viotape_InvalidTape, EIO, "Invalid tape device" },
145 { viotape_InvalidOp, EIO, "Invalid operation" },
146 { viotape_TapeErr, EIO, "Tape error" },
147 { viotape_AllocTimedOut, EBUSY, "Allocate timed out" },
148 { viotape_BOTEnc, EIO, "Beginning of tape encountered" },
149 { viotape_BlankTape, EIO, "Blank tape" },
150 { viotape_BufferEmpty, EIO, "Buffer empty" },
151 { viotape_CleanCartFound, ENOMEDIUM, "Cleaning cartridge found" },
152 { viotape_CmdNotAllowed, EIO, "Command not allowed" },
153 { viotape_CmdNotSupported, EIO, "Command not supported" },
154 { viotape_DataCheck, EIO, "Data check" },
155 { viotape_DecompressErr, EIO, "Decompression error" },
156 { viotape_DeviceTimeout, EBUSY, "Device timeout" },
157 { viotape_DeviceUnavail, EIO, "Device unavailable" },
158 { viotape_DeviceBusy, EBUSY, "Device busy" },
159 { viotape_EndOfMedia, ENOSPC, "End of media" },
160 { viotape_EndOfTape, ENOSPC, "End of tape" },
161 { viotape_EquipCheck, EIO, "Equipment check" },
162 { viotape_InsufficientRs, EOVERFLOW, "Insufficient tape resources" },
163 { viotape_InvalidLogBlk, EIO, "Invalid logical block location" },
164 { viotape_LengthError, EOVERFLOW, "Length error" },
165 { viotape_LibDoorOpen, EBUSY, "Door open" },
166 { viotape_LoadFailure, ENOMEDIUM, "Load failure" },
167 { viotape_NotCapable, EIO, "Not capable" },
168 { viotape_NotOperational, EIO, "Not operational" },
169 { viotape_NotReady, EIO, "Not ready" },
170 { viotape_OpCancelled, EIO, "Operation cancelled" },
171 { viotape_PhyLinkErr, EIO, "Physical link error" },
172 { viotape_RdyNotBOT, EIO, "Ready but not beginning of tape" },
173 { viotape_TapeMark, EIO, "Tape mark" },
174 { viotape_WriteProt, EROFS, "Write protection error" },
175 { 0, 0, NULL },
176};
177
178/* Maximum number of tapes we support */
179#define VIOTAPE_MAX_TAPE HVMAXARCHITECTEDVIRTUALTAPES
180#define MAX_PARTITIONS 4
181
182/* defines for current tape state */
183#define VIOT_IDLE 0
184#define VIOT_READING 1
185#define VIOT_WRITING 2
186
187/* Our info on the tapes */
188static struct {
189 const char *rsrcname;
190 const char *type;
191 const char *model;
192} viotape_unitinfo[VIOTAPE_MAX_TAPE];
193
194static struct mtget viomtget[VIOTAPE_MAX_TAPE];
195
196static struct class *tape_class;
197
198static struct device *tape_device[VIOTAPE_MAX_TAPE];
199
200/*
201 * maintain the current state of each tape (and partition)
202 * so that we know when to write EOF marks.
203 */
204static struct {
205 unsigned char cur_part;
206 unsigned char part_stat_rwi[MAX_PARTITIONS];
207} state[VIOTAPE_MAX_TAPE];
208
209/* We single-thread */
210static struct semaphore reqSem;
211
212/*
213 * When we send a request, we use this struct to get the response back
214 * from the interrupt handler
215 */
216struct op_struct {
217 void *buffer;
218 dma_addr_t dmaaddr;
219 size_t count;
220 int rc;
221 int non_blocking;
222 struct completion com;
223 struct device *dev;
224 struct op_struct *next;
225};
226
227static spinlock_t op_struct_list_lock;
228static struct op_struct *op_struct_list;
229
230/* forward declaration to resolve interdependence */
231static int chg_state(int index, unsigned char new_state, struct file *file);
232
233/* procfs support */
234static int proc_viotape_show(struct seq_file *m, void *v)
235{
236 int i;
237
238 seq_printf(m, "viotape driver version " VIOTAPE_VERSION "\n");
239 for (i = 0; i < viotape_numdev; i++) {
240 seq_printf(m, "viotape device %d is iSeries resource %10.10s"
241 "type %4.4s, model %3.3s\n",
242 i, viotape_unitinfo[i].rsrcname,
243 viotape_unitinfo[i].type,
244 viotape_unitinfo[i].model);
245 }
246 return 0;
247}
248
249static int proc_viotape_open(struct inode *inode, struct file *file)
250{
251 return single_open(file, proc_viotape_show, NULL);
252}
253
254static const struct file_operations proc_viotape_operations = {
255 .owner = THIS_MODULE,
256 .open = proc_viotape_open,
257 .read = seq_read,
258 .llseek = seq_lseek,
259 .release = single_release,
260};
261
262/* Decode the device minor number into its parts */
263void get_dev_info(struct inode *ino, struct viot_devinfo_struct *devi)
264{
265 devi->devno = iminor(ino) & 0x1F;
266 devi->mode = (iminor(ino) & 0x60) >> 5;
267 /* if bit is set in the minor, do _not_ rewind automatically */
268 devi->rewind = (iminor(ino) & 0x80) == 0;
269}
270
271/* This is called only from the exit and init paths, so no need for locking */
272static void clear_op_struct_pool(void)
273{
274 while (op_struct_list) {
275 struct op_struct *toFree = op_struct_list;
276 op_struct_list = op_struct_list->next;
277 kfree(toFree);
278 }
279}
280
281/* Likewise, this is only called from the init path */
282static int add_op_structs(int structs)
283{
284 int i;
285
286 for (i = 0; i < structs; ++i) {
287 struct op_struct *new_struct =
288 kmalloc(sizeof(*new_struct), GFP_KERNEL);
289 if (!new_struct) {
290 clear_op_struct_pool();
291 return -ENOMEM;
292 }
293 new_struct->next = op_struct_list;
294 op_struct_list = new_struct;
295 }
296 return 0;
297}
298
299/* Allocate an op structure from our pool */
300static struct op_struct *get_op_struct(void)
301{
302 struct op_struct *retval;
303 unsigned long flags;
304
305 spin_lock_irqsave(&op_struct_list_lock, flags);
306 retval = op_struct_list;
307 if (retval)
308 op_struct_list = retval->next;
309 spin_unlock_irqrestore(&op_struct_list_lock, flags);
310 if (retval) {
311 memset(retval, 0, sizeof(*retval));
312 init_completion(&retval->com);
313 }
314
315 return retval;
316}
317
318/* Return an op structure to our pool */
319static void free_op_struct(struct op_struct *op_struct)
320{
321 unsigned long flags;
322
323 spin_lock_irqsave(&op_struct_list_lock, flags);
324 op_struct->next = op_struct_list;
325 op_struct_list = op_struct;
326 spin_unlock_irqrestore(&op_struct_list_lock, flags);
327}
328
329/* Map our tape return codes to errno values */
330int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
331{
332 const struct vio_error_entry *err;
333
334 if (tape_rc == 0)
335 return 0;
336
337 err = vio_lookup_rc(viotape_err_table, tape_rc);
338 printk(VIOTAPE_KERN_WARN "error(%s) 0x%04x on Device %d (%-10s): %s\n",
339 operation, tape_rc, tapeno,
340 viotape_unitinfo[tapeno].rsrcname, err->msg);
341 return -err->errno;
342}
343
344/* Write */
345static ssize_t viotap_write(struct file *file, const char *buf,
346 size_t count, loff_t * ppos)
347{
348 HvLpEvent_Rc hvrc;
349 unsigned short flags = file->f_flags;
350 int noblock = ((flags & O_NONBLOCK) != 0);
351 ssize_t ret;
352 struct viot_devinfo_struct devi;
353 struct op_struct *op = get_op_struct();
354
355 if (op == NULL)
356 return -ENOMEM;
357
358 get_dev_info(file->f_path.dentry->d_inode, &devi);
359
360 /*
361 * We need to make sure we can send a request. We use
362 * a semaphore to keep track of # requests in use. If
363 * we are non-blocking, make sure we don't block on the
364 * semaphore
365 */
366 if (noblock) {
367 if (down_trylock(&reqSem)) {
368 ret = -EWOULDBLOCK;
369 goto free_op;
370 }
371 } else
372 down(&reqSem);
373
374 /* Allocate a DMA buffer */
375 op->dev = tape_device[devi.devno];
376 op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
377 GFP_ATOMIC);
378
379 if (op->buffer == NULL) {
380 printk(VIOTAPE_KERN_WARN
381 "error allocating dma buffer for len %ld\n",
382 count);
383 ret = -EFAULT;
384 goto up_sem;
385 }
386
387 /* Copy the data into the buffer */
388 if (copy_from_user(op->buffer, buf, count)) {
389 printk(VIOTAPE_KERN_WARN "tape: error on copy from user\n");
390 ret = -EFAULT;
391 goto free_dma;
392 }
393
394 op->non_blocking = noblock;
395 init_completion(&op->com);
396 op->count = count;
397
398 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
399 HvLpEvent_Type_VirtualIo,
400 viomajorsubtype_tape | viotapewrite,
401 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
402 viopath_sourceinst(viopath_hostLp),
403 viopath_targetinst(viopath_hostLp),
404 (u64)(unsigned long)op, VIOVERSION << 16,
405 ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
406 if (hvrc != HvLpEvent_Rc_Good) {
407 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
408 (int)hvrc);
409 ret = -EIO;
410 goto free_dma;
411 }
412
413 if (noblock)
414 return count;
415
416 wait_for_completion(&op->com);
417
418 if (op->rc)
419 ret = tape_rc_to_errno(op->rc, "write", devi.devno);
420 else {
421 chg_state(devi.devno, VIOT_WRITING, file);
422 ret = op->count;
423 }
424
425free_dma:
426 dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
427up_sem:
428 up(&reqSem);
429free_op:
430 free_op_struct(op);
431 return ret;
432}
433
434/* read */
435static ssize_t viotap_read(struct file *file, char *buf, size_t count,
436 loff_t *ptr)
437{
438 HvLpEvent_Rc hvrc;
439 unsigned short flags = file->f_flags;
440 struct op_struct *op = get_op_struct();
441 int noblock = ((flags & O_NONBLOCK) != 0);
442 ssize_t ret;
443 struct viot_devinfo_struct devi;
444
445 if (op == NULL)
446 return -ENOMEM;
447
448 get_dev_info(file->f_path.dentry->d_inode, &devi);
449
450 /*
451 * We need to make sure we can send a request. We use
452 * a semaphore to keep track of # requests in use. If
453 * we are non-blocking, make sure we don't block on the
454 * semaphore
455 */
456 if (noblock) {
457 if (down_trylock(&reqSem)) {
458 ret = -EWOULDBLOCK;
459 goto free_op;
460 }
461 } else
462 down(&reqSem);
463
464 chg_state(devi.devno, VIOT_READING, file);
465
466 /* Allocate a DMA buffer */
467 op->dev = tape_device[devi.devno];
468 op->buffer = dma_alloc_coherent(op->dev, count, &op->dmaaddr,
469 GFP_ATOMIC);
470 if (op->buffer == NULL) {
471 ret = -EFAULT;
472 goto up_sem;
473 }
474
475 op->count = count;
476 init_completion(&op->com);
477
478 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
479 HvLpEvent_Type_VirtualIo,
480 viomajorsubtype_tape | viotaperead,
481 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
482 viopath_sourceinst(viopath_hostLp),
483 viopath_targetinst(viopath_hostLp),
484 (u64)(unsigned long)op, VIOVERSION << 16,
485 ((u64)devi.devno << 48) | op->dmaaddr, count, 0, 0);
486 if (hvrc != HvLpEvent_Rc_Good) {
487 printk(VIOTAPE_KERN_WARN "tape hv error on op %d\n",
488 (int)hvrc);
489 ret = -EIO;
490 goto free_dma;
491 }
492
493 wait_for_completion(&op->com);
494
495 if (op->rc)
496 ret = tape_rc_to_errno(op->rc, "read", devi.devno);
497 else {
498 ret = op->count;
499 if (ret && copy_to_user(buf, op->buffer, ret)) {
500 printk(VIOTAPE_KERN_WARN "error on copy_to_user\n");
501 ret = -EFAULT;
502 }
503 }
504
505free_dma:
506 dma_free_coherent(op->dev, count, op->buffer, op->dmaaddr);
507up_sem:
508 up(&reqSem);
509free_op:
510 free_op_struct(op);
511 return ret;
512}
513
514/* ioctl */
515static int viotap_ioctl(struct inode *inode, struct file *file,
516 unsigned int cmd, unsigned long arg)
517{
518 HvLpEvent_Rc hvrc;
519 int ret;
520 struct viot_devinfo_struct devi;
521 struct mtop mtc;
522 u32 myOp;
523 struct op_struct *op = get_op_struct();
524
525 if (op == NULL)
526 return -ENOMEM;
527
528 get_dev_info(file->f_path.dentry->d_inode, &devi);
529
530 down(&reqSem);
531
532 ret = -EINVAL;
533
534 switch (cmd) {
535 case MTIOCTOP:
536 ret = -EFAULT;
537 /*
538 * inode is null if and only if we (the kernel)
539 * made the request
540 */
541 if (inode == NULL)
542 memcpy(&mtc, (void *) arg, sizeof(struct mtop));
543 else if (copy_from_user((char *)&mtc, (char *)arg,
544 sizeof(struct mtop)))
545 goto free_op;
546
547 ret = -EIO;
548 switch (mtc.mt_op) {
549 case MTRESET:
550 myOp = VIOTAPOP_RESET;
551 break;
552 case MTFSF:
553 myOp = VIOTAPOP_FSF;
554 break;
555 case MTBSF:
556 myOp = VIOTAPOP_BSF;
557 break;
558 case MTFSR:
559 myOp = VIOTAPOP_FSR;
560 break;
561 case MTBSR:
562 myOp = VIOTAPOP_BSR;
563 break;
564 case MTWEOF:
565 myOp = VIOTAPOP_WEOF;
566 break;
567 case MTREW:
568 myOp = VIOTAPOP_REW;
569 break;
570 case MTNOP:
571 myOp = VIOTAPOP_NOP;
572 break;
573 case MTEOM:
574 myOp = VIOTAPOP_EOM;
575 break;
576 case MTERASE:
577 myOp = VIOTAPOP_ERASE;
578 break;
579 case MTSETBLK:
580 myOp = VIOTAPOP_SETBLK;
581 break;
582 case MTSETDENSITY:
583 myOp = VIOTAPOP_SETDENSITY;
584 break;
585 case MTTELL:
586 myOp = VIOTAPOP_GETPOS;
587 break;
588 case MTSEEK:
589 myOp = VIOTAPOP_SETPOS;
590 break;
591 case MTSETPART:
592 myOp = VIOTAPOP_SETPART;
593 break;
594 case MTOFFL:
595 myOp = VIOTAPOP_UNLOAD;
596 break;
597 default:
598 printk(VIOTAPE_KERN_WARN "MTIOCTOP called "
599 "with invalid op 0x%x\n", mtc.mt_op);
600 goto free_op;
601 }
602
603 /*
604 * if we moved the head, we are no longer
605 * reading or writing
606 */
607 switch (mtc.mt_op) {
608 case MTFSF:
609 case MTBSF:
610 case MTFSR:
611 case MTBSR:
612 case MTTELL:
613 case MTSEEK:
614 case MTREW:
615 chg_state(devi.devno, VIOT_IDLE, file);
616 }
617
618 init_completion(&op->com);
619 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
620 HvLpEvent_Type_VirtualIo,
621 viomajorsubtype_tape | viotapeop,
622 HvLpEvent_AckInd_DoAck,
623 HvLpEvent_AckType_ImmediateAck,
624 viopath_sourceinst(viopath_hostLp),
625 viopath_targetinst(viopath_hostLp),
626 (u64)(unsigned long)op,
627 VIOVERSION << 16,
628 ((u64)devi.devno << 48), 0,
629 (((u64)myOp) << 32) | mtc.mt_count, 0);
630 if (hvrc != HvLpEvent_Rc_Good) {
631 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
632 (int)hvrc);
633 goto free_op;
634 }
635 wait_for_completion(&op->com);
636 ret = tape_rc_to_errno(op->rc, "tape operation", devi.devno);
637 goto free_op;
638
639 case MTIOCGET:
640 ret = -EIO;
641 init_completion(&op->com);
642 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
643 HvLpEvent_Type_VirtualIo,
644 viomajorsubtype_tape | viotapegetstatus,
645 HvLpEvent_AckInd_DoAck,
646 HvLpEvent_AckType_ImmediateAck,
647 viopath_sourceinst(viopath_hostLp),
648 viopath_targetinst(viopath_hostLp),
649 (u64)(unsigned long)op, VIOVERSION << 16,
650 ((u64)devi.devno << 48), 0, 0, 0);
651 if (hvrc != HvLpEvent_Rc_Good) {
652 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
653 (int)hvrc);
654 goto free_op;
655 }
656 wait_for_completion(&op->com);
657
658 /* Operation is complete - grab the error code */
659 ret = tape_rc_to_errno(op->rc, "get status", devi.devno);
660 free_op_struct(op);
661 up(&reqSem);
662
663 if ((ret == 0) && copy_to_user((void *)arg,
664 &viomtget[devi.devno],
665 sizeof(viomtget[0])))
666 ret = -EFAULT;
667 return ret;
668 case MTIOCPOS:
669 printk(VIOTAPE_KERN_WARN "Got an (unsupported) MTIOCPOS\n");
670 break;
671 default:
672 printk(VIOTAPE_KERN_WARN "got an unsupported ioctl 0x%0x\n",
673 cmd);
674 break;
675 }
676
677free_op:
678 free_op_struct(op);
679 up(&reqSem);
680 return ret;
681}
682
683static long viotap_unlocked_ioctl(struct file *file,
684 unsigned int cmd, unsigned long arg)
685{
686 long rc;
687
688 mutex_lock(&proc_viotape_mutex);
689 rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
690 mutex_unlock(&proc_viotape_mutex);
691 return rc;
692}
693
694static int viotap_open(struct inode *inode, struct file *file)
695{
696 HvLpEvent_Rc hvrc;
697 struct viot_devinfo_struct devi;
698 int ret;
699 struct op_struct *op = get_op_struct();
700
701 if (op == NULL)
702 return -ENOMEM;
703
704 mutex_lock(&proc_viotape_mutex);
705 get_dev_info(file->f_path.dentry->d_inode, &devi);
706
707 /* Note: We currently only support one mode! */
708 if ((devi.devno >= viotape_numdev) || (devi.mode)) {
709 ret = -ENODEV;
710 goto free_op;
711 }
712
713 init_completion(&op->com);
714
715 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
716 HvLpEvent_Type_VirtualIo,
717 viomajorsubtype_tape | viotapeopen,
718 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
719 viopath_sourceinst(viopath_hostLp),
720 viopath_targetinst(viopath_hostLp),
721 (u64)(unsigned long)op, VIOVERSION << 16,
722 ((u64)devi.devno << 48), 0, 0, 0);
723 if (hvrc != 0) {
724 printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
725 (int) hvrc);
726 ret = -EIO;
727 goto free_op;
728 }
729
730 wait_for_completion(&op->com);
731 ret = tape_rc_to_errno(op->rc, "open", devi.devno);
732
733free_op:
734 free_op_struct(op);
735 mutex_unlock(&proc_viotape_mutex);
736 return ret;
737}
738
739
740static int viotap_release(struct inode *inode, struct file *file)
741{
742 HvLpEvent_Rc hvrc;
743 struct viot_devinfo_struct devi;
744 int ret = 0;
745 struct op_struct *op = get_op_struct();
746
747 if (op == NULL)
748 return -ENOMEM;
749 init_completion(&op->com);
750
751 get_dev_info(file->f_path.dentry->d_inode, &devi);
752
753 if (devi.devno >= viotape_numdev) {
754 ret = -ENODEV;
755 goto free_op;
756 }
757
758 chg_state(devi.devno, VIOT_IDLE, file);
759
760 if (devi.rewind) {
761 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
762 HvLpEvent_Type_VirtualIo,
763 viomajorsubtype_tape | viotapeop,
764 HvLpEvent_AckInd_DoAck,
765 HvLpEvent_AckType_ImmediateAck,
766 viopath_sourceinst(viopath_hostLp),
767 viopath_targetinst(viopath_hostLp),
768 (u64)(unsigned long)op, VIOVERSION << 16,
769 ((u64)devi.devno << 48), 0,
770 ((u64)VIOTAPOP_REW) << 32, 0);
771 wait_for_completion(&op->com);
772
773 tape_rc_to_errno(op->rc, "rewind", devi.devno);
774 }
775
776 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
777 HvLpEvent_Type_VirtualIo,
778 viomajorsubtype_tape | viotapeclose,
779 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
780 viopath_sourceinst(viopath_hostLp),
781 viopath_targetinst(viopath_hostLp),
782 (u64)(unsigned long)op, VIOVERSION << 16,
783 ((u64)devi.devno << 48), 0, 0, 0);
784 if (hvrc != 0) {
785 printk(VIOTAPE_KERN_WARN "bad rc on signalLpEvent %d\n",
786 (int) hvrc);
787 ret = -EIO;
788 goto free_op;
789 }
790
791 wait_for_completion(&op->com);
792
793 if (op->rc)
794 printk(VIOTAPE_KERN_WARN "close failed\n");
795
796free_op:
797 free_op_struct(op);
798 return ret;
799}
800
801const struct file_operations viotap_fops = {
802 .owner = THIS_MODULE,
803 .read = viotap_read,
804 .write = viotap_write,
805 .unlocked_ioctl = viotap_unlocked_ioctl,
806 .open = viotap_open,
807 .release = viotap_release,
808 .llseek = noop_llseek,
809};
810
811/* Handle interrupt events for tape */
812static void vioHandleTapeEvent(struct HvLpEvent *event)
813{
814 int tapeminor;
815 struct op_struct *op;
816 struct viotapelpevent *tevent = (struct viotapelpevent *)event;
817
818 if (event == NULL) {
819 /* Notification that a partition went away! */
820 if (!viopath_isactive(viopath_hostLp)) {
821 /* TODO! Clean up */
822 }
823 return;
824 }
825
826 tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
827 op = (struct op_struct *)event->xCorrelationToken;
828 switch (tapeminor) {
829 case viotapeopen:
830 case viotapeclose:
831 op->rc = tevent->sub_type_result;
832 complete(&op->com);
833 break;
834 case viotaperead:
835 op->rc = tevent->sub_type_result;
836 op->count = tevent->len;
837 complete(&op->com);
838 break;
839 case viotapewrite:
840 if (op->non_blocking) {
841 dma_free_coherent(op->dev, op->count,
842 op->buffer, op->dmaaddr);
843 free_op_struct(op);
844 up(&reqSem);
845 } else {
846 op->rc = tevent->sub_type_result;
847 op->count = tevent->len;
848 complete(&op->com);
849 }
850 break;
851 case viotapeop:
852 case viotapegetpos:
853 case viotapesetpos:
854 case viotapegetstatus:
855 if (op) {
856 op->count = tevent->u.op.count;
857 op->rc = tevent->sub_type_result;
858 if (!op->non_blocking)
859 complete(&op->com);
860 }
861 break;
862 default:
863 printk(VIOTAPE_KERN_WARN "weird ack\n");
864 }
865}
866
867static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
868{
869 int i = vdev->unit_address;
870 int j;
871 struct device_node *node = vdev->dev.of_node;
872
873 if (i >= VIOTAPE_MAX_TAPE)
874 return -ENODEV;
875 if (!node)
876 return -ENODEV;
877
878 if (i >= viotape_numdev)
879 viotape_numdev = i + 1;
880
881 tape_device[i] = &vdev->dev;
882 viotape_unitinfo[i].rsrcname = of_get_property(node,
883 "linux,vio_rsrcname", NULL);
884 viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
885 NULL);
886 viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
887 NULL);
888
889 state[i].cur_part = 0;
890 for (j = 0; j < MAX_PARTITIONS; ++j)
891 state[i].part_stat_rwi[j] = VIOT_IDLE;
892 device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), NULL,
893 "iseries!vt%d", i);
894 device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL,
895 "iseries!nvt%d", i);
896 printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
897 "resource %10.10s type %4.4s, model %3.3s\n",
898 i, viotape_unitinfo[i].rsrcname,
899 viotape_unitinfo[i].type, viotape_unitinfo[i].model);
900 return 0;
901}
902
903static int viotape_remove(struct vio_dev *vdev)
904{
905 int i = vdev->unit_address;
906
907 device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
908 device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
909 return 0;
910}
911
912/**
913 * viotape_device_table: Used by vio.c to match devices that we
914 * support.
915 */
916static struct vio_device_id viotape_device_table[] __devinitdata = {
917 { "byte", "IBM,iSeries-viotape" },
918 { "", "" }
919};
920MODULE_DEVICE_TABLE(vio, viotape_device_table);
921
922static struct vio_driver viotape_driver = {
923 .id_table = viotape_device_table,
924 .probe = viotape_probe,
925 .remove = viotape_remove,
926 .driver = {
927 .name = "viotape",
928 .owner = THIS_MODULE,
929 }
930};
931
932
933int __init viotap_init(void)
934{
935 int ret;
936
937 if (!firmware_has_feature(FW_FEATURE_ISERIES))
938 return -ENODEV;
939
940 op_struct_list = NULL;
941 if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) {
942 printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n");
943 return ret;
944 }
945 spin_lock_init(&op_struct_list_lock);
946
947 sema_init(&reqSem, VIOTAPE_MAXREQ);
948
949 if (viopath_hostLp == HvLpIndexInvalid) {
950 vio_set_hostlp();
951 if (viopath_hostLp == HvLpIndexInvalid) {
952 ret = -ENODEV;
953 goto clear_op;
954 }
955 }
956
957 ret = viopath_open(viopath_hostLp, viomajorsubtype_tape,
958 VIOTAPE_MAXREQ + 2);
959 if (ret) {
960 printk(VIOTAPE_KERN_WARN
961 "error on viopath_open to hostlp %d\n", ret);
962 ret = -EIO;
963 goto clear_op;
964 }
965
966 printk(VIOTAPE_KERN_INFO "vers " VIOTAPE_VERSION
967 ", hosting partition %d\n", viopath_hostLp);
968
969 vio_setHandler(viomajorsubtype_tape, vioHandleTapeEvent);
970
971 ret = register_chrdev(VIOTAPE_MAJOR, "viotape", &viotap_fops);
972 if (ret < 0) {
973 printk(VIOTAPE_KERN_WARN "Error registering viotape device\n");
974 goto clear_handler;
975 }
976
977 tape_class = class_create(THIS_MODULE, "tape");
978 if (IS_ERR(tape_class)) {
979 printk(VIOTAPE_KERN_WARN "Unable to allocate class\n");
980 ret = PTR_ERR(tape_class);
981 goto unreg_chrdev;
982 }
983
984 ret = vio_register_driver(&viotape_driver);
985 if (ret)
986 goto unreg_class;
987
988 proc_create("iSeries/viotape", S_IFREG|S_IRUGO, NULL,
989 &proc_viotape_operations);
990
991 return 0;
992
993unreg_class:
994 class_destroy(tape_class);
995unreg_chrdev:
996 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
997clear_handler:
998 vio_clearHandler(viomajorsubtype_tape);
999 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1000clear_op:
1001 clear_op_struct_pool();
1002 return ret;
1003}
1004
1005/* Give a new state to the tape object */
1006static int chg_state(int index, unsigned char new_state, struct file *file)
1007{
1008 unsigned char *cur_state =
1009 &state[index].part_stat_rwi[state[index].cur_part];
1010 int rc = 0;
1011
1012 /* if the same state, don't bother */
1013 if (*cur_state == new_state)
1014 return 0;
1015
1016 /* write an EOF if changing from writing to some other state */
1017 if (*cur_state == VIOT_WRITING) {
1018 struct mtop write_eof = { MTWEOF, 1 };
1019
1020 rc = viotap_ioctl(NULL, file, MTIOCTOP,
1021 (unsigned long)&write_eof);
1022 }
1023 *cur_state = new_state;
1024 return rc;
1025}
1026
1027/* Cleanup */
1028static void __exit viotap_exit(void)
1029{
1030 remove_proc_entry("iSeries/viotape", NULL);
1031 vio_unregister_driver(&viotape_driver);
1032 class_destroy(tape_class);
1033 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1034 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1035 vio_clearHandler(viomajorsubtype_tape);
1036 clear_op_struct_pool();
1037}
1038
1039MODULE_LICENSE("GPL");
1040module_init(viotap_init);
1041module_exit(viotap_exit);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d0c41188d4e5..0409cf35adda 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -190,6 +190,17 @@ config GPIO_VX855
190 additional drivers must be enabled in order to use the 190 additional drivers must be enabled in order to use the
191 functionality of the device. 191 functionality of the device.
192 192
193config GPIO_GE_FPGA
194 bool "GE FPGA based GPIO"
195 depends on GE_FPGA
196 help
197 Support for common GPIO functionality provided on some GE Single Board
198 Computers.
199
200 This driver provides basic support (configure as input or output, read
201 and write pin state) for GPIO implemented in a number of GE single
202 board computers.
203
193comment "I2C GPIO expanders:" 204comment "I2C GPIO expanders:"
194 205
195config GPIO_MAX7300 206config GPIO_MAX7300
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fa10df604c01..9a8fb54ae462 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o 16obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
17obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o 17obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
18obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o 18obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
19obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
19obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o 20obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
20obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o 21obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
21obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o 22obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/drivers/gpio/gpio-ge.c
index 2a703365e664..7b95a4a8318c 100644
--- a/arch/powerpc/platforms/86xx/gef_gpio.c
+++ b/drivers/gpio/gpio-ge.c
@@ -14,7 +14,7 @@
14 * 14 *
15 * Configuration of output modes (totem-pole/open-drain) 15 * Configuration of output modes (totem-pole/open-drain)
16 * Interrupt configuration - interrupts are always generated the FPGA relies on 16 * Interrupt configuration - interrupts are always generated the FPGA relies on
17 * the I/O interrupt controllers mask to stop them propergating 17 * the I/O interrupt controllers mask to stop them propergating
18 */ 18 */
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
@@ -162,6 +162,34 @@ static int __init gef_gpio_init(void)
162 } 162 }
163 } 163 }
164 164
165 for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
166
167 pr_debug("%s: Initialising GE GPIO\n", np->full_name);
168
169 /* Allocate chip structure */
170 gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
171 if (!gef_gpio_chip) {
172 pr_err("%s: Unable to allocate structure\n",
173 np->full_name);
174 continue;
175 }
176
177 /* Setup pointers to chip functions */
178 gef_gpio_chip->gc.of_gpio_n_cells = 2;
179 gef_gpio_chip->gc.ngpio = 16;
180 gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
181 gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
182 gef_gpio_chip->gc.get = gef_gpio_get;
183 gef_gpio_chip->gc.set = gef_gpio_set;
184
185 /* This function adds a memory mapped GPIO chip */
186 retval = of_mm_gpiochip_add(np, gef_gpio_chip);
187 if (retval) {
188 kfree(gef_gpio_chip);
189 pr_err("%s: Unable to add GPIO\n", np->full_name);
190 }
191 }
192
165 return 0; 193 return 0;
166}; 194};
167arch_initcall(gef_gpio_init); 195arch_initcall(gef_gpio_init);
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 366bc156e34d..8c279da07410 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -560,6 +560,9 @@ static void data_enable_interrupts(struct fpga_device *priv)
560 560
561 /* flush the writes */ 561 /* flush the writes */
562 fpga_read_reg(priv, 0, MMAP_REG_STATUS); 562 fpga_read_reg(priv, 0, MMAP_REG_STATUS);
563 fpga_read_reg(priv, 1, MMAP_REG_STATUS);
564 fpga_read_reg(priv, 2, MMAP_REG_STATUS);
565 fpga_read_reg(priv, 3, MMAP_REG_STATUS);
563 566
564 /* switch back to the external interrupt source */ 567 /* switch back to the external interrupt source */
565 iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL); 568 iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL);
@@ -591,8 +594,12 @@ static void data_dma_cb(void *data)
591 list_move_tail(&priv->inflight->entry, &priv->used); 594 list_move_tail(&priv->inflight->entry, &priv->used);
592 priv->inflight = NULL; 595 priv->inflight = NULL;
593 596
594 /* clear the FPGA status and re-enable interrupts */ 597 /*
595 data_enable_interrupts(priv); 598 * If data dumping is still enabled, then clear the FPGA
599 * status registers and re-enable FPGA interrupts
600 */
601 if (priv->enabled)
602 data_enable_interrupts(priv);
596 603
597 spin_unlock_irqrestore(&priv->lock, flags); 604 spin_unlock_irqrestore(&priv->lock, flags);
598 605
@@ -708,6 +715,15 @@ static irqreturn_t data_irq(int irq, void *dev_id)
708 715
709 spin_lock(&priv->lock); 716 spin_lock(&priv->lock);
710 717
718 /*
719 * This is an error case that should never happen.
720 *
721 * If this driver has a bug and manages to re-enable interrupts while
722 * a DMA is in progress, then we will hit this statement and should
723 * start paying attention immediately.
724 */
725 BUG_ON(priv->inflight != NULL);
726
711 /* hide the interrupt by switching the IRQ driver to GPIO */ 727 /* hide the interrupt by switching the IRQ driver to GPIO */
712 data_disable_interrupts(priv); 728 data_disable_interrupts(priv);
713 729
@@ -762,11 +778,15 @@ out:
762 */ 778 */
763static int data_device_enable(struct fpga_device *priv) 779static int data_device_enable(struct fpga_device *priv)
764{ 780{
781 bool enabled;
765 u32 val; 782 u32 val;
766 int ret; 783 int ret;
767 784
768 /* multiple enables are safe: they do nothing */ 785 /* multiple enables are safe: they do nothing */
769 if (priv->enabled) 786 spin_lock_irq(&priv->lock);
787 enabled = priv->enabled;
788 spin_unlock_irq(&priv->lock);
789 if (enabled)
770 return 0; 790 return 0;
771 791
772 /* check that the FPGAs are programmed */ 792 /* check that the FPGAs are programmed */
@@ -797,6 +817,9 @@ static int data_device_enable(struct fpga_device *priv)
797 goto out_error; 817 goto out_error;
798 } 818 }
799 819
820 /* prevent the FPGAs from generating interrupts */
821 data_disable_interrupts(priv);
822
800 /* hookup the irq handler */ 823 /* hookup the irq handler */
801 ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv); 824 ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv);
802 if (ret) { 825 if (ret) {
@@ -804,11 +827,13 @@ static int data_device_enable(struct fpga_device *priv)
804 goto out_error; 827 goto out_error;
805 } 828 }
806 829
807 /* switch to the external FPGA IRQ line */ 830 /* allow the DMA callback to re-enable FPGA interrupts */
808 data_enable_interrupts(priv); 831 spin_lock_irq(&priv->lock);
809
810 /* success, we're enabled */
811 priv->enabled = true; 832 priv->enabled = true;
833 spin_unlock_irq(&priv->lock);
834
835 /* allow the FPGAs to generate interrupts */
836 data_enable_interrupts(priv);
812 return 0; 837 return 0;
813 838
814out_error: 839out_error:
@@ -834,41 +859,40 @@ out_error:
834 */ 859 */
835static int data_device_disable(struct fpga_device *priv) 860static int data_device_disable(struct fpga_device *priv)
836{ 861{
837 int ret; 862 spin_lock_irq(&priv->lock);
838 863
839 /* allow multiple disable */ 864 /* allow multiple disable */
840 if (!priv->enabled) 865 if (!priv->enabled) {
866 spin_unlock_irq(&priv->lock);
841 return 0; 867 return 0;
868 }
869
870 /*
871 * Mark the device disabled
872 *
873 * This stops DMA callbacks from re-enabling interrupts
874 */
875 priv->enabled = false;
842 876
843 /* switch to the internal GPIO IRQ line */ 877 /* prevent the FPGAs from generating interrupts */
844 data_disable_interrupts(priv); 878 data_disable_interrupts(priv);
845 879
880 /* wait until all ongoing DMA has finished */
881 while (priv->inflight != NULL) {
882 spin_unlock_irq(&priv->lock);
883 wait_event(priv->wait, priv->inflight == NULL);
884 spin_lock_irq(&priv->lock);
885 }
886
887 spin_unlock_irq(&priv->lock);
888
846 /* unhook the irq handler */ 889 /* unhook the irq handler */
847 free_irq(priv->irq, priv); 890 free_irq(priv->irq, priv);
848 891
849 /*
850 * wait for all outstanding DMA to complete
851 *
852 * Device interrupts are disabled, therefore another buffer cannot
853 * be marked inflight.
854 */
855 ret = wait_event_interruptible(priv->wait, priv->inflight == NULL);
856 if (ret)
857 return ret;
858
859 /* free the correlation table */ 892 /* free the correlation table */
860 sg_free_table(&priv->corl_table); 893 sg_free_table(&priv->corl_table);
861 priv->corl_nents = 0; 894 priv->corl_nents = 0;
862 895
863 /*
864 * We are taking the spinlock not to protect priv->enabled, but instead
865 * to make sure that there are no readers in the process of altering
866 * the free or used lists while we are setting this flag.
867 */
868 spin_lock_irq(&priv->lock);
869 priv->enabled = false;
870 spin_unlock_irq(&priv->lock);
871
872 /* free all buffers: the free and used lists are not being changed */ 896 /* free all buffers: the free and used lists are not being changed */
873 data_free_buffers(priv); 897 data_free_buffers(priv);
874 return 0; 898 return 0;
@@ -896,15 +920,6 @@ static unsigned int list_num_entries(struct list_head *list)
896static int data_debug_show(struct seq_file *f, void *offset) 920static int data_debug_show(struct seq_file *f, void *offset)
897{ 921{
898 struct fpga_device *priv = f->private; 922 struct fpga_device *priv = f->private;
899 int ret;
900
901 /*
902 * Lock the mutex first, so that we get an accurate value for enable
903 * Lock the spinlock next, to get accurate list counts
904 */
905 ret = mutex_lock_interruptible(&priv->mutex);
906 if (ret)
907 return ret;
908 923
909 spin_lock_irq(&priv->lock); 924 spin_lock_irq(&priv->lock);
910 925
@@ -917,7 +932,6 @@ static int data_debug_show(struct seq_file *f, void *offset)
917 seq_printf(f, "num_dropped: %d\n", priv->num_dropped); 932 seq_printf(f, "num_dropped: %d\n", priv->num_dropped);
918 933
919 spin_unlock_irq(&priv->lock); 934 spin_unlock_irq(&priv->lock);
920 mutex_unlock(&priv->mutex);
921 return 0; 935 return 0;
922} 936}
923 937
@@ -970,7 +984,13 @@ static ssize_t data_en_show(struct device *dev, struct device_attribute *attr,
970 char *buf) 984 char *buf)
971{ 985{
972 struct fpga_device *priv = dev_get_drvdata(dev); 986 struct fpga_device *priv = dev_get_drvdata(dev);
973 return snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled); 987 int ret;
988
989 spin_lock_irq(&priv->lock);
990 ret = snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
991 spin_unlock_irq(&priv->lock);
992
993 return ret;
974} 994}
975 995
976static ssize_t data_en_set(struct device *dev, struct device_attribute *attr, 996static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
@@ -986,6 +1006,7 @@ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
986 return -EINVAL; 1006 return -EINVAL;
987 } 1007 }
988 1008
1009 /* protect against concurrent enable/disable */
989 ret = mutex_lock_interruptible(&priv->mutex); 1010 ret = mutex_lock_interruptible(&priv->mutex);
990 if (ret) 1011 if (ret)
991 return ret; 1012 return ret;
@@ -1079,6 +1100,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
1079 struct fpga_reader *reader = filp->private_data; 1100 struct fpga_reader *reader = filp->private_data;
1080 struct fpga_device *priv = reader->priv; 1101 struct fpga_device *priv = reader->priv;
1081 struct list_head *used = &priv->used; 1102 struct list_head *used = &priv->used;
1103 bool drop_buffer = false;
1082 struct data_buf *dbuf; 1104 struct data_buf *dbuf;
1083 size_t avail; 1105 size_t avail;
1084 void *data; 1106 void *data;
@@ -1166,10 +1188,12 @@ have_buffer:
1166 * One of two things has happened, the device is disabled, or the 1188 * One of two things has happened, the device is disabled, or the
1167 * device has been reconfigured underneath us. In either case, we 1189 * device has been reconfigured underneath us. In either case, we
1168 * should just throw away the buffer. 1190 * should just throw away the buffer.
1191 *
1192 * Lockdep complains if this is done under the spinlock, so we
1193 * handle it during the unlock path.
1169 */ 1194 */
1170 if (!priv->enabled || dbuf->size != priv->bufsize) { 1195 if (!priv->enabled || dbuf->size != priv->bufsize) {
1171 videobuf_dma_unmap(priv->dev, &dbuf->vb); 1196 drop_buffer = true;
1172 data_free_buffer(dbuf);
1173 goto out_unlock; 1197 goto out_unlock;
1174 } 1198 }
1175 1199
@@ -1178,6 +1202,12 @@ have_buffer:
1178 1202
1179out_unlock: 1203out_unlock:
1180 spin_unlock_irq(&priv->lock); 1204 spin_unlock_irq(&priv->lock);
1205
1206 if (drop_buffer) {
1207 videobuf_dma_unmap(priv->dev, &dbuf->vb);
1208 data_free_buffer(dbuf);
1209 }
1210
1181 return count; 1211 return count;
1182} 1212}
1183 1213
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 31b034b7eba3..3b1d6da874e0 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -462,6 +462,16 @@ config MTD_NAND_FSL_ELBC
462 Enabling this option will enable you to use this to control 462 Enabling this option will enable you to use this to control
463 external NAND devices. 463 external NAND devices.
464 464
465config MTD_NAND_FSL_IFC
466 tristate "NAND support for Freescale IFC controller"
467 depends on MTD_NAND && FSL_SOC
468 select FSL_IFC
469 help
470 Various Freescale chips e.g P1010, include a NAND Flash machine
471 with built-in hardware ECC capabilities.
472 Enabling this option will enable you to use this to control
473 external NAND devices.
474
465config MTD_NAND_FSL_UPM 475config MTD_NAND_FSL_UPM
466 tristate "Support for NAND on Freescale UPM" 476 tristate "Support for NAND on Freescale UPM"
467 depends on PPC_83xx || PPC_85xx 477 depends on PPC_83xx || PPC_85xx
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 618f4ba23699..19bc8cb1d187 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MTD_ALAUDA) += alauda.o
37obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o 37obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
38obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o 38obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
39obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o 39obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
40obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o
40obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o 41obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
41obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o 42obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o
42obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o 43obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
new file mode 100644
index 000000000000..c30ac7b83d28
--- /dev/null
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -0,0 +1,1072 @@
1/*
2 * Freescale Integrated Flash Controller NAND driver
3 *
4 * Copyright 2011-2012 Freescale Semiconductor, Inc
5 *
6 * Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/module.h>
24#include <linux/types.h>
25#include <linux/init.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/mtd/mtd.h>
29#include <linux/mtd/nand.h>
30#include <linux/mtd/partitions.h>
31#include <linux/mtd/nand_ecc.h>
32#include <asm/fsl_ifc.h>
33
34#define ERR_BYTE 0xFF /* Value returned for read
35 bytes when read failed */
36#define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait
37 for IFC NAND Machine */
38
39struct fsl_ifc_ctrl;
40
41/* mtd information per set */
42struct fsl_ifc_mtd {
43 struct mtd_info mtd;
44 struct nand_chip chip;
45 struct fsl_ifc_ctrl *ctrl;
46
47 struct device *dev;
48 int bank; /* Chip select bank number */
49 unsigned int bufnum_mask; /* bufnum = page & bufnum_mask */
50 u8 __iomem *vbase; /* Chip select base virtual address */
51};
52
53/* overview of the fsl ifc controller */
54struct fsl_ifc_nand_ctrl {
55 struct nand_hw_control controller;
56 struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT];
57
58 u8 __iomem *addr; /* Address of assigned IFC buffer */
59 unsigned int page; /* Last page written to / read from */
60 unsigned int read_bytes;/* Number of bytes read during command */
61 unsigned int column; /* Saved column from SEQIN */
62 unsigned int index; /* Pointer to next byte to 'read' */
63 unsigned int oob; /* Non zero if operating on OOB data */
64 unsigned int eccread; /* Non zero for a full-page ECC read */
65 unsigned int counter; /* counter for the initializations */
66};
67
68static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl;
69
70/* 512-byte page with 4-bit ECC, 8-bit */
71static struct nand_ecclayout oob_512_8bit_ecc4 = {
72 .eccbytes = 8,
73 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
74 .oobfree = { {0, 5}, {6, 2} },
75};
76
77/* 512-byte page with 4-bit ECC, 16-bit */
78static struct nand_ecclayout oob_512_16bit_ecc4 = {
79 .eccbytes = 8,
80 .eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
81 .oobfree = { {2, 6}, },
82};
83
84/* 2048-byte page size with 4-bit ECC */
85static struct nand_ecclayout oob_2048_ecc4 = {
86 .eccbytes = 32,
87 .eccpos = {
88 8, 9, 10, 11, 12, 13, 14, 15,
89 16, 17, 18, 19, 20, 21, 22, 23,
90 24, 25, 26, 27, 28, 29, 30, 31,
91 32, 33, 34, 35, 36, 37, 38, 39,
92 },
93 .oobfree = { {2, 6}, {40, 24} },
94};
95
96/* 4096-byte page size with 4-bit ECC */
97static struct nand_ecclayout oob_4096_ecc4 = {
98 .eccbytes = 64,
99 .eccpos = {
100 8, 9, 10, 11, 12, 13, 14, 15,
101 16, 17, 18, 19, 20, 21, 22, 23,
102 24, 25, 26, 27, 28, 29, 30, 31,
103 32, 33, 34, 35, 36, 37, 38, 39,
104 40, 41, 42, 43, 44, 45, 46, 47,
105 48, 49, 50, 51, 52, 53, 54, 55,
106 56, 57, 58, 59, 60, 61, 62, 63,
107 64, 65, 66, 67, 68, 69, 70, 71,
108 },
109 .oobfree = { {2, 6}, {72, 56} },
110};
111
112/* 4096-byte page size with 8-bit ECC -- requires 218-byte OOB */
113static struct nand_ecclayout oob_4096_ecc8 = {
114 .eccbytes = 128,
115 .eccpos = {
116 8, 9, 10, 11, 12, 13, 14, 15,
117 16, 17, 18, 19, 20, 21, 22, 23,
118 24, 25, 26, 27, 28, 29, 30, 31,
119 32, 33, 34, 35, 36, 37, 38, 39,
120 40, 41, 42, 43, 44, 45, 46, 47,
121 48, 49, 50, 51, 52, 53, 54, 55,
122 56, 57, 58, 59, 60, 61, 62, 63,
123 64, 65, 66, 67, 68, 69, 70, 71,
124 72, 73, 74, 75, 76, 77, 78, 79,
125 80, 81, 82, 83, 84, 85, 86, 87,
126 88, 89, 90, 91, 92, 93, 94, 95,
127 96, 97, 98, 99, 100, 101, 102, 103,
128 104, 105, 106, 107, 108, 109, 110, 111,
129 112, 113, 114, 115, 116, 117, 118, 119,
130 120, 121, 122, 123, 124, 125, 126, 127,
131 128, 129, 130, 131, 132, 133, 134, 135,
132 },
133 .oobfree = { {2, 6}, {136, 82} },
134};
135
136
137/*
138 * Generic flash bbt descriptors
139 */
140static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
141static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
142
143static struct nand_bbt_descr bbt_main_descr = {
144 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
145 NAND_BBT_2BIT | NAND_BBT_VERSION,
146 .offs = 2, /* 0 on 8-bit small page */
147 .len = 4,
148 .veroffs = 6,
149 .maxblocks = 4,
150 .pattern = bbt_pattern,
151};
152
153static struct nand_bbt_descr bbt_mirror_descr = {
154 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
155 NAND_BBT_2BIT | NAND_BBT_VERSION,
156 .offs = 2, /* 0 on 8-bit small page */
157 .len = 4,
158 .veroffs = 6,
159 .maxblocks = 4,
160 .pattern = mirror_pattern,
161};
162
163/*
164 * Set up the IFC hardware block and page address fields, and the ifc nand
165 * structure addr field to point to the correct IFC buffer in memory
166 */
167static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
168{
169 struct nand_chip *chip = mtd->priv;
170 struct fsl_ifc_mtd *priv = chip->priv;
171 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
172 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
173 int buf_num;
174
175 ifc_nand_ctrl->page = page_addr;
176 /* Program ROW0/COL0 */
177 out_be32(&ifc->ifc_nand.row0, page_addr);
178 out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column);
179
180 buf_num = page_addr & priv->bufnum_mask;
181
182 ifc_nand_ctrl->addr = priv->vbase + buf_num * (mtd->writesize * 2);
183 ifc_nand_ctrl->index = column;
184
185 /* for OOB data point to the second half of the buffer */
186 if (oob)
187 ifc_nand_ctrl->index += mtd->writesize;
188}
189
190static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
191{
192 struct nand_chip *chip = mtd->priv;
193 struct fsl_ifc_mtd *priv = chip->priv;
194 u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
195 u32 __iomem *mainarea = (u32 *)addr;
196 u8 __iomem *oob = addr + mtd->writesize;
197 int i;
198
199 for (i = 0; i < mtd->writesize / 4; i++) {
200 if (__raw_readl(&mainarea[i]) != 0xffffffff)
201 return 0;
202 }
203
204 for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
205 int pos = chip->ecc.layout->eccpos[i];
206
207 if (__raw_readb(&oob[pos]) != 0xff)
208 return 0;
209 }
210
211 return 1;
212}
213
214/* returns nonzero if entire page is blank */
215static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
216 u32 *eccstat, unsigned int bufnum)
217{
218 u32 reg = eccstat[bufnum / 4];
219 int errors;
220
221 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
222
223 return errors;
224}
225
226/*
227 * execute IFC NAND command and wait for it to complete
228 */
229static void fsl_ifc_run_command(struct mtd_info *mtd)
230{
231 struct nand_chip *chip = mtd->priv;
232 struct fsl_ifc_mtd *priv = chip->priv;
233 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
234 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
235 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
236 u32 eccstat[4];
237 int i;
238
239 /* set the chip select for NAND Transaction */
240 out_be32(&ifc->ifc_nand.nand_csel, priv->bank << IFC_NAND_CSEL_SHIFT);
241
242 dev_vdbg(priv->dev,
243 "%s: fir0=%08x fcr0=%08x\n",
244 __func__,
245 in_be32(&ifc->ifc_nand.nand_fir0),
246 in_be32(&ifc->ifc_nand.nand_fcr0));
247
248 ctrl->nand_stat = 0;
249
250 /* start read/write seq */
251 out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
252
253 /* wait for command complete flag or timeout */
254 wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
255 IFC_TIMEOUT_MSECS * HZ/1000);
256
257 /* ctrl->nand_stat will be updated from IRQ context */
258 if (!ctrl->nand_stat)
259 dev_err(priv->dev, "Controller is not responding\n");
260 if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_FTOER)
261 dev_err(priv->dev, "NAND Flash Timeout Error\n");
262 if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER)
263 dev_err(priv->dev, "NAND Flash Write Protect Error\n");
264
265 if (nctrl->eccread) {
266 int errors;
267 int bufnum = nctrl->page & priv->bufnum_mask;
268 int sector = bufnum * chip->ecc.steps;
269 int sector_end = sector + chip->ecc.steps - 1;
270
271 for (i = sector / 4; i <= sector_end / 4; i++)
272 eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]);
273
274 for (i = sector; i <= sector_end; i++) {
275 errors = check_read_ecc(mtd, ctrl, eccstat, i);
276
277 if (errors == 15) {
278 /*
279 * Uncorrectable error.
280 * OK only if the whole page is blank.
281 *
282 * We disable ECCER reporting due to...
283 * erratum IFC-A002770 -- so report it now if we
284 * see an uncorrectable error in ECCSTAT.
285 */
286 if (!is_blank(mtd, bufnum))
287 ctrl->nand_stat |=
288 IFC_NAND_EVTER_STAT_ECCER;
289 break;
290 }
291
292 mtd->ecc_stats.corrected += errors;
293 }
294
295 nctrl->eccread = 0;
296 }
297}
298
299static void fsl_ifc_do_read(struct nand_chip *chip,
300 int oob,
301 struct mtd_info *mtd)
302{
303 struct fsl_ifc_mtd *priv = chip->priv;
304 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
305 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
306
307 /* Program FIR/IFC_NAND_FCR0 for Small/Large page */
308 if (mtd->writesize > 512) {
309 out_be32(&ifc->ifc_nand.nand_fir0,
310 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
311 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
312 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
313 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) |
314 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT));
315 out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
316
317 out_be32(&ifc->ifc_nand.nand_fcr0,
318 (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) |
319 (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT));
320 } else {
321 out_be32(&ifc->ifc_nand.nand_fir0,
322 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
323 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
324 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
325 (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT));
326 out_be32(&ifc->ifc_nand.nand_fir1, 0x0);
327
328 if (oob)
329 out_be32(&ifc->ifc_nand.nand_fcr0,
330 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT);
331 else
332 out_be32(&ifc->ifc_nand.nand_fcr0,
333 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT);
334 }
335}
336
337/* cmdfunc send commands to the IFC NAND Machine */
338static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
339 int column, int page_addr) {
340 struct nand_chip *chip = mtd->priv;
341 struct fsl_ifc_mtd *priv = chip->priv;
342 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
343 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
344
345 /* clear the read buffer */
346 ifc_nand_ctrl->read_bytes = 0;
347 if (command != NAND_CMD_PAGEPROG)
348 ifc_nand_ctrl->index = 0;
349
350 switch (command) {
351 /* READ0 read the entire buffer to use hardware ECC. */
352 case NAND_CMD_READ0:
353 out_be32(&ifc->ifc_nand.nand_fbcr, 0);
354 set_addr(mtd, 0, page_addr, 0);
355
356 ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
357 ifc_nand_ctrl->index += column;
358
359 if (chip->ecc.mode == NAND_ECC_HW)
360 ifc_nand_ctrl->eccread = 1;
361
362 fsl_ifc_do_read(chip, 0, mtd);
363 fsl_ifc_run_command(mtd);
364 return;
365
366 /* READOOB reads only the OOB because no ECC is performed. */
367 case NAND_CMD_READOOB:
368 out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column);
369 set_addr(mtd, column, page_addr, 1);
370
371 ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
372
373 fsl_ifc_do_read(chip, 1, mtd);
374 fsl_ifc_run_command(mtd);
375
376 return;
377
378 /* READID must read all 8 possible bytes */
379 case NAND_CMD_READID:
380 out_be32(&ifc->ifc_nand.nand_fir0,
381 (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
382 (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
383 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
384 out_be32(&ifc->ifc_nand.nand_fcr0,
385 NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
386 /* 8 bytes for manuf, device and exts */
387 out_be32(&ifc->ifc_nand.nand_fbcr, 8);
388 ifc_nand_ctrl->read_bytes = 8;
389
390 set_addr(mtd, 0, 0, 0);
391 fsl_ifc_run_command(mtd);
392 return;
393
394 /* ERASE1 stores the block and page address */
395 case NAND_CMD_ERASE1:
396 set_addr(mtd, 0, page_addr, 0);
397 return;
398
399 /* ERASE2 uses the block and page address from ERASE1 */
400 case NAND_CMD_ERASE2:
401 out_be32(&ifc->ifc_nand.nand_fir0,
402 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
403 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) |
404 (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT));
405
406 out_be32(&ifc->ifc_nand.nand_fcr0,
407 (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) |
408 (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT));
409
410 out_be32(&ifc->ifc_nand.nand_fbcr, 0);
411 ifc_nand_ctrl->read_bytes = 0;
412 fsl_ifc_run_command(mtd);
413 return;
414
415 /* SEQIN sets up the addr buffer and all registers except the length */
416 case NAND_CMD_SEQIN: {
417 u32 nand_fcr0;
418 ifc_nand_ctrl->column = column;
419 ifc_nand_ctrl->oob = 0;
420
421 if (mtd->writesize > 512) {
422 nand_fcr0 =
423 (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
424 (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
425
426 out_be32(&ifc->ifc_nand.nand_fir0,
427 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
428 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
429 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
430 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
431 (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT));
432 } else {
433 nand_fcr0 = ((NAND_CMD_PAGEPROG <<
434 IFC_NAND_FCR0_CMD1_SHIFT) |
435 (NAND_CMD_SEQIN <<
436 IFC_NAND_FCR0_CMD2_SHIFT));
437
438 out_be32(&ifc->ifc_nand.nand_fir0,
439 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
440 (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) |
441 (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) |
442 (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
443 (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT));
444 out_be32(&ifc->ifc_nand.nand_fir1,
445 (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT));
446
447 if (column >= mtd->writesize)
448 nand_fcr0 |=
449 NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT;
450 else
451 nand_fcr0 |=
452 NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT;
453 }
454
455 if (column >= mtd->writesize) {
456 /* OOB area --> READOOB */
457 column -= mtd->writesize;
458 ifc_nand_ctrl->oob = 1;
459 }
460 out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0);
461 set_addr(mtd, column, page_addr, ifc_nand_ctrl->oob);
462 return;
463 }
464
465 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
466 case NAND_CMD_PAGEPROG: {
467 if (ifc_nand_ctrl->oob) {
468 out_be32(&ifc->ifc_nand.nand_fbcr,
469 ifc_nand_ctrl->index - ifc_nand_ctrl->column);
470 } else {
471 out_be32(&ifc->ifc_nand.nand_fbcr, 0);
472 }
473
474 fsl_ifc_run_command(mtd);
475 return;
476 }
477
478 case NAND_CMD_STATUS:
479 out_be32(&ifc->ifc_nand.nand_fir0,
480 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
481 (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT));
482 out_be32(&ifc->ifc_nand.nand_fcr0,
483 NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT);
484 out_be32(&ifc->ifc_nand.nand_fbcr, 1);
485 set_addr(mtd, 0, 0, 0);
486 ifc_nand_ctrl->read_bytes = 1;
487
488 fsl_ifc_run_command(mtd);
489
490 /*
491 * The chip always seems to report that it is
492 * write-protected, even when it is not.
493 */
494 setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP);
495 return;
496
497 case NAND_CMD_RESET:
498 out_be32(&ifc->ifc_nand.nand_fir0,
499 IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT);
500 out_be32(&ifc->ifc_nand.nand_fcr0,
501 NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT);
502 fsl_ifc_run_command(mtd);
503 return;
504
505 default:
506 dev_err(priv->dev, "%s: error, unsupported command 0x%x.\n",
507 __func__, command);
508 }
509}
510
511static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
512{
513 /* The hardware does not seem to support multiple
514 * chips per bank.
515 */
516}
517
518/*
519 * Write buf to the IFC NAND Controller Data Buffer
520 */
521static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
522{
523 struct nand_chip *chip = mtd->priv;
524 struct fsl_ifc_mtd *priv = chip->priv;
525 unsigned int bufsize = mtd->writesize + mtd->oobsize;
526
527 if (len <= 0) {
528 dev_err(priv->dev, "%s: len %d bytes", __func__, len);
529 return;
530 }
531
532 if ((unsigned int)len > bufsize - ifc_nand_ctrl->index) {
533 dev_err(priv->dev,
534 "%s: beyond end of buffer (%d requested, %u available)\n",
535 __func__, len, bufsize - ifc_nand_ctrl->index);
536 len = bufsize - ifc_nand_ctrl->index;
537 }
538
539 memcpy_toio(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index], buf, len);
540 ifc_nand_ctrl->index += len;
541}
542
543/*
544 * Read a byte from either the IFC hardware buffer
545 * read function for 8-bit buswidth
546 */
547static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
548{
549 struct nand_chip *chip = mtd->priv;
550 struct fsl_ifc_mtd *priv = chip->priv;
551
552 /*
553 * If there are still bytes in the IFC buffer, then use the
554 * next byte.
555 */
556 if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes)
557 return in_8(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index++]);
558
559 dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
560 return ERR_BYTE;
561}
562
563/*
564 * Read two bytes from the IFC hardware buffer
565 * read function for 16-bit buswith
566 */
567static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
568{
569 struct nand_chip *chip = mtd->priv;
570 struct fsl_ifc_mtd *priv = chip->priv;
571 uint16_t data;
572
573 /*
574 * If there are still bytes in the IFC buffer, then use the
575 * next byte.
576 */
577 if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) {
578 data = in_be16((uint16_t *)&ifc_nand_ctrl->
579 addr[ifc_nand_ctrl->index]);
580 ifc_nand_ctrl->index += 2;
581 return (uint8_t) data;
582 }
583
584 dev_err(priv->dev, "%s: beyond end of buffer\n", __func__);
585 return ERR_BYTE;
586}
587
588/*
589 * Read from the IFC Controller Data Buffer
590 */
591static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
592{
593 struct nand_chip *chip = mtd->priv;
594 struct fsl_ifc_mtd *priv = chip->priv;
595 int avail;
596
597 if (len < 0) {
598 dev_err(priv->dev, "%s: len %d bytes", __func__, len);
599 return;
600 }
601
602 avail = min((unsigned int)len,
603 ifc_nand_ctrl->read_bytes - ifc_nand_ctrl->index);
604 memcpy_fromio(buf, &ifc_nand_ctrl->addr[ifc_nand_ctrl->index], avail);
605 ifc_nand_ctrl->index += avail;
606
607 if (len > avail)
608 dev_err(priv->dev,
609 "%s: beyond end of buffer (%d requested, %d available)\n",
610 __func__, len, avail);
611}
612
613/*
614 * Verify buffer against the IFC Controller Data Buffer
615 */
616static int fsl_ifc_verify_buf(struct mtd_info *mtd,
617 const u_char *buf, int len)
618{
619 struct nand_chip *chip = mtd->priv;
620 struct fsl_ifc_mtd *priv = chip->priv;
621 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
622 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
623 int i;
624
625 if (len < 0) {
626 dev_err(priv->dev, "%s: write_buf of %d bytes", __func__, len);
627 return -EINVAL;
628 }
629
630 if ((unsigned int)len > nctrl->read_bytes - nctrl->index) {
631 dev_err(priv->dev,
632 "%s: beyond end of buffer (%d requested, %u available)\n",
633 __func__, len, nctrl->read_bytes - nctrl->index);
634
635 nctrl->index = nctrl->read_bytes;
636 return -EINVAL;
637 }
638
639 for (i = 0; i < len; i++)
640 if (in_8(&nctrl->addr[nctrl->index + i]) != buf[i])
641 break;
642
643 nctrl->index += len;
644
645 if (i != len)
646 return -EIO;
647 if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
648 return -EIO;
649
650 return 0;
651}
652
653/*
654 * This function is called after Program and Erase Operations to
655 * check for success or failure.
656 */
657static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
658{
659 struct fsl_ifc_mtd *priv = chip->priv;
660 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
661 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
662 u32 nand_fsr;
663
664 /* Use READ_STATUS command, but wait for the device to be ready */
665 out_be32(&ifc->ifc_nand.nand_fir0,
666 (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
667 (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT));
668 out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS <<
669 IFC_NAND_FCR0_CMD0_SHIFT);
670 out_be32(&ifc->ifc_nand.nand_fbcr, 1);
671 set_addr(mtd, 0, 0, 0);
672 ifc_nand_ctrl->read_bytes = 1;
673
674 fsl_ifc_run_command(mtd);
675
676 nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr);
677
678 /*
679 * The chip always seems to report that it is
680 * write-protected, even when it is not.
681 */
682 return nand_fsr | NAND_STATUS_WP;
683}
684
685static int fsl_ifc_read_page(struct mtd_info *mtd,
686 struct nand_chip *chip,
687 uint8_t *buf, int page)
688{
689 struct fsl_ifc_mtd *priv = chip->priv;
690 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
691
692 fsl_ifc_read_buf(mtd, buf, mtd->writesize);
693 fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
694
695 if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER)
696 dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n");
697
698 if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
699 mtd->ecc_stats.failed++;
700
701 return 0;
702}
703
704/* ECC will be calculated automatically, and errors will be detected in
705 * waitfunc.
706 */
707static void fsl_ifc_write_page(struct mtd_info *mtd,
708 struct nand_chip *chip,
709 const uint8_t *buf)
710{
711 fsl_ifc_write_buf(mtd, buf, mtd->writesize);
712 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
713}
714
715static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
716{
717 struct nand_chip *chip = mtd->priv;
718 struct fsl_ifc_mtd *priv = chip->priv;
719
720 dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
721 chip->numchips);
722 dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__,
723 chip->chipsize);
724 dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__,
725 chip->pagemask);
726 dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__,
727 chip->chip_delay);
728 dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__,
729 chip->badblockpos);
730 dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__,
731 chip->chip_shift);
732 dev_dbg(priv->dev, "%s: nand->page_shift = %d\n", __func__,
733 chip->page_shift);
734 dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
735 chip->phys_erase_shift);
736 dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
737 chip->ecclayout);
738 dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
739 chip->ecc.mode);
740 dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
741 chip->ecc.steps);
742 dev_dbg(priv->dev, "%s: nand->ecc.bytes = %d\n", __func__,
743 chip->ecc.bytes);
744 dev_dbg(priv->dev, "%s: nand->ecc.total = %d\n", __func__,
745 chip->ecc.total);
746 dev_dbg(priv->dev, "%s: nand->ecc.layout = %p\n", __func__,
747 chip->ecc.layout);
748 dev_dbg(priv->dev, "%s: mtd->flags = %08x\n", __func__, mtd->flags);
749 dev_dbg(priv->dev, "%s: mtd->size = %lld\n", __func__, mtd->size);
750 dev_dbg(priv->dev, "%s: mtd->erasesize = %d\n", __func__,
751 mtd->erasesize);
752 dev_dbg(priv->dev, "%s: mtd->writesize = %d\n", __func__,
753 mtd->writesize);
754 dev_dbg(priv->dev, "%s: mtd->oobsize = %d\n", __func__,
755 mtd->oobsize);
756
757 return 0;
758}
759
760static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
761{
762 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
763 struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
764 struct nand_chip *chip = &priv->chip;
765 struct nand_ecclayout *layout;
766 u32 csor;
767
768 /* Fill in fsl_ifc_mtd structure */
769 priv->mtd.priv = chip;
770 priv->mtd.owner = THIS_MODULE;
771
772 /* fill in nand_chip structure */
773 /* set up function call table */
774 if ((in_be32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16)
775 chip->read_byte = fsl_ifc_read_byte16;
776 else
777 chip->read_byte = fsl_ifc_read_byte;
778
779 chip->write_buf = fsl_ifc_write_buf;
780 chip->read_buf = fsl_ifc_read_buf;
781 chip->verify_buf = fsl_ifc_verify_buf;
782 chip->select_chip = fsl_ifc_select_chip;
783 chip->cmdfunc = fsl_ifc_cmdfunc;
784 chip->waitfunc = fsl_ifc_wait;
785
786 chip->bbt_td = &bbt_main_descr;
787 chip->bbt_md = &bbt_mirror_descr;
788
789 out_be32(&ifc->ifc_nand.ncfgr, 0x0);
790
791 /* set up nand options */
792 chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR;
793 chip->bbt_options = NAND_BBT_USE_FLASH;
794
795
796 if (in_be32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) {
797 chip->read_byte = fsl_ifc_read_byte16;
798 chip->options |= NAND_BUSWIDTH_16;
799 } else {
800 chip->read_byte = fsl_ifc_read_byte;
801 }
802
803 chip->controller = &ifc_nand_ctrl->controller;
804 chip->priv = priv;
805
806 chip->ecc.read_page = fsl_ifc_read_page;
807 chip->ecc.write_page = fsl_ifc_write_page;
808
809 csor = in_be32(&ifc->csor_cs[priv->bank].csor);
810
811 /* Hardware generates ECC per 512 Bytes */
812 chip->ecc.size = 512;
813 chip->ecc.bytes = 8;
814
815 switch (csor & CSOR_NAND_PGS_MASK) {
816 case CSOR_NAND_PGS_512:
817 if (chip->options & NAND_BUSWIDTH_16) {
818 layout = &oob_512_16bit_ecc4;
819 } else {
820 layout = &oob_512_8bit_ecc4;
821
822 /* Avoid conflict with bad block marker */
823 bbt_main_descr.offs = 0;
824 bbt_mirror_descr.offs = 0;
825 }
826
827 priv->bufnum_mask = 15;
828 break;
829
830 case CSOR_NAND_PGS_2K:
831 layout = &oob_2048_ecc4;
832 priv->bufnum_mask = 3;
833 break;
834
835 case CSOR_NAND_PGS_4K:
836 if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
837 CSOR_NAND_ECC_MODE_4) {
838 layout = &oob_4096_ecc4;
839 } else {
840 layout = &oob_4096_ecc8;
841 chip->ecc.bytes = 16;
842 }
843
844 priv->bufnum_mask = 1;
845 break;
846
847 default:
848 dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
849 return -ENODEV;
850 }
851
852 /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */
853 if (csor & CSOR_NAND_ECC_DEC_EN) {
854 chip->ecc.mode = NAND_ECC_HW;
855 chip->ecc.layout = layout;
856 } else {
857 chip->ecc.mode = NAND_ECC_SOFT;
858 }
859
860 return 0;
861}
862
863static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
864{
865 nand_release(&priv->mtd);
866
867 kfree(priv->mtd.name);
868
869 if (priv->vbase)
870 iounmap(priv->vbase);
871
872 ifc_nand_ctrl->chips[priv->bank] = NULL;
873 dev_set_drvdata(priv->dev, NULL);
874 kfree(priv);
875
876 return 0;
877}
878
879static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank,
880 phys_addr_t addr)
881{
882 u32 cspr = in_be32(&ifc->cspr_cs[bank].cspr);
883
884 if (!(cspr & CSPR_V))
885 return 0;
886 if ((cspr & CSPR_MSEL) != CSPR_MSEL_NAND)
887 return 0;
888
889 return (cspr & CSPR_BA) == convert_ifc_address(addr);
890}
891
892static DEFINE_MUTEX(fsl_ifc_nand_mutex);
893
894static int __devinit fsl_ifc_nand_probe(struct platform_device *dev)
895{
896 struct fsl_ifc_regs __iomem *ifc;
897 struct fsl_ifc_mtd *priv;
898 struct resource res;
899 static const char *part_probe_types[]
900 = { "cmdlinepart", "RedBoot", "ofpart", NULL };
901 int ret;
902 int bank;
903 struct device_node *node = dev->dev.of_node;
904 struct mtd_part_parser_data ppdata;
905
906 ppdata.of_node = dev->dev.of_node;
907 if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
908 return -ENODEV;
909 ifc = fsl_ifc_ctrl_dev->regs;
910
911 /* get, allocate and map the memory resource */
912 ret = of_address_to_resource(node, 0, &res);
913 if (ret) {
914 dev_err(&dev->dev, "%s: failed to get resource\n", __func__);
915 return ret;
916 }
917
918 /* find which chip select it is connected to */
919 for (bank = 0; bank < FSL_IFC_BANK_COUNT; bank++) {
920 if (match_bank(ifc, bank, res.start))
921 break;
922 }
923
924 if (bank >= FSL_IFC_BANK_COUNT) {
925 dev_err(&dev->dev, "%s: address did not match any chip selects\n",
926 __func__);
927 return -ENODEV;
928 }
929
930 priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
931 if (!priv)
932 return -ENOMEM;
933
934 mutex_lock(&fsl_ifc_nand_mutex);
935 if (!fsl_ifc_ctrl_dev->nand) {
936 ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL);
937 if (!ifc_nand_ctrl) {
938 dev_err(&dev->dev, "failed to allocate memory\n");
939 mutex_unlock(&fsl_ifc_nand_mutex);
940 return -ENOMEM;
941 }
942
943 ifc_nand_ctrl->read_bytes = 0;
944 ifc_nand_ctrl->index = 0;
945 ifc_nand_ctrl->addr = NULL;
946 fsl_ifc_ctrl_dev->nand = ifc_nand_ctrl;
947
948 spin_lock_init(&ifc_nand_ctrl->controller.lock);
949 init_waitqueue_head(&ifc_nand_ctrl->controller.wq);
950 } else {
951 ifc_nand_ctrl = fsl_ifc_ctrl_dev->nand;
952 }
953 mutex_unlock(&fsl_ifc_nand_mutex);
954
955 ifc_nand_ctrl->chips[bank] = priv;
956 priv->bank = bank;
957 priv->ctrl = fsl_ifc_ctrl_dev;
958 priv->dev = &dev->dev;
959
960 priv->vbase = ioremap(res.start, resource_size(&res));
961 if (!priv->vbase) {
962 dev_err(priv->dev, "%s: failed to map chip region\n", __func__);
963 ret = -ENOMEM;
964 goto err;
965 }
966
967 dev_set_drvdata(priv->dev, priv);
968
969 out_be32(&ifc->ifc_nand.nand_evter_en,
970 IFC_NAND_EVTER_EN_OPC_EN |
971 IFC_NAND_EVTER_EN_FTOER_EN |
972 IFC_NAND_EVTER_EN_WPER_EN);
973
974 /* enable NAND Machine Interrupts */
975 out_be32(&ifc->ifc_nand.nand_evter_intr_en,
976 IFC_NAND_EVTER_INTR_OPCIR_EN |
977 IFC_NAND_EVTER_INTR_FTOERIR_EN |
978 IFC_NAND_EVTER_INTR_WPERIR_EN);
979
980 priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
981 if (!priv->mtd.name) {
982 ret = -ENOMEM;
983 goto err;
984 }
985
986 ret = fsl_ifc_chip_init(priv);
987 if (ret)
988 goto err;
989
990 ret = nand_scan_ident(&priv->mtd, 1, NULL);
991 if (ret)
992 goto err;
993
994 ret = fsl_ifc_chip_init_tail(&priv->mtd);
995 if (ret)
996 goto err;
997
998 ret = nand_scan_tail(&priv->mtd);
999 if (ret)
1000 goto err;
1001
1002 /* First look for RedBoot table or partitions on the command
1003 * line, these take precedence over device tree information */
1004 mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
1005 NULL, 0);
1006
1007 dev_info(priv->dev, "IFC NAND device at 0x%llx, bank %d\n",
1008 (unsigned long long)res.start, priv->bank);
1009 return 0;
1010
1011err:
1012 fsl_ifc_chip_remove(priv);
1013 return ret;
1014}
1015
1016static int fsl_ifc_nand_remove(struct platform_device *dev)
1017{
1018 struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev);
1019
1020 fsl_ifc_chip_remove(priv);
1021
1022 mutex_lock(&fsl_ifc_nand_mutex);
1023 ifc_nand_ctrl->counter--;
1024 if (!ifc_nand_ctrl->counter) {
1025 fsl_ifc_ctrl_dev->nand = NULL;
1026 kfree(ifc_nand_ctrl);
1027 }
1028 mutex_unlock(&fsl_ifc_nand_mutex);
1029
1030 return 0;
1031}
1032
1033static const struct of_device_id fsl_ifc_nand_match[] = {
1034 {
1035 .compatible = "fsl,ifc-nand",
1036 },
1037 {}
1038};
1039
1040static struct platform_driver fsl_ifc_nand_driver = {
1041 .driver = {
1042 .name = "fsl,ifc-nand",
1043 .owner = THIS_MODULE,
1044 .of_match_table = fsl_ifc_nand_match,
1045 },
1046 .probe = fsl_ifc_nand_probe,
1047 .remove = fsl_ifc_nand_remove,
1048};
1049
1050static int __init fsl_ifc_nand_init(void)
1051{
1052 int ret;
1053
1054 ret = platform_driver_register(&fsl_ifc_nand_driver);
1055 if (ret)
1056 printk(KERN_ERR "fsl-ifc: Failed to register platform"
1057 "driver\n");
1058
1059 return ret;
1060}
1061
1062static void __exit fsl_ifc_nand_exit(void)
1063{
1064 platform_driver_unregister(&fsl_ifc_nand_driver);
1065}
1066
1067module_init(fsl_ifc_nand_init);
1068module_exit(fsl_ifc_nand_exit);
1069
1070MODULE_LICENSE("GPL");
1071MODULE_AUTHOR("Freescale");
1072MODULE_DESCRIPTION("Freescale Integrated Flash Controller MTD NAND driver");
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index d3d18e89cb57..4e89103204dc 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -974,9 +974,8 @@ config SCSI_IPS
974 974
975config SCSI_IBMVSCSI 975config SCSI_IBMVSCSI
976 tristate "IBM Virtual SCSI support" 976 tristate "IBM Virtual SCSI support"
977 depends on PPC_PSERIES || PPC_ISERIES 977 depends on PPC_PSERIES
978 select SCSI_SRP_ATTRS 978 select SCSI_SRP_ATTRS
979 select VIOPATH if PPC_ISERIES
980 help 979 help
981 This is the IBM POWER Virtual SCSI Client 980 This is the IBM POWER Virtual SCSI Client
982 981
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
index a423d9633625..ff5b5c5538ee 100644
--- a/drivers/scsi/ibmvscsi/Makefile
+++ b/drivers/scsi/ibmvscsi/Makefile
@@ -1,7 +1,6 @@
1obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o 1obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o
2 2
3ibmvscsic-y += ibmvscsi.o 3ibmvscsic-y += ibmvscsi.o
4ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o
5ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o 4ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o
6 5
7obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o 6obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 3d391dc3f11f..e984951baeb6 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -55,13 +55,7 @@
55 * and sends a CRQ message back to inform the client that the request has 55 * and sends a CRQ message back to inform the client that the request has
56 * completed. 56 * completed.
57 * 57 *
58 * Note that some of the underlying infrastructure is different between 58 * TODO: This is currently pretty tied to the IBM pSeries hypervisor
59 * machines conforming to the "RS/6000 Platform Architecture" (RPA) and
60 * the older iSeries hypervisor models. To support both, some low level
61 * routines have been broken out into rpa_vscsi.c and iseries_vscsi.c.
62 * The Makefile should pick one, not two, not zero, of these.
63 *
64 * TODO: This is currently pretty tied to the IBM i/pSeries hypervisor
65 * interfaces. It would be really nice to abstract this above an RDMA 59 * interfaces. It would be really nice to abstract this above an RDMA
66 * layer. 60 * layer.
67 */ 61 */
@@ -2085,9 +2079,7 @@ int __init ibmvscsi_module_init(void)
2085 driver_template.can_queue = max_requests; 2079 driver_template.can_queue = max_requests;
2086 max_events = max_requests + 2; 2080 max_events = max_requests + 2;
2087 2081
2088 if (firmware_has_feature(FW_FEATURE_ISERIES)) 2082 if (firmware_has_feature(FW_FEATURE_VIO))
2089 ibmvscsi_ops = &iseriesvscsi_ops;
2090 else if (firmware_has_feature(FW_FEATURE_VIO))
2091 ibmvscsi_ops = &rpavscsi_ops; 2083 ibmvscsi_ops = &rpavscsi_ops;
2092 else 2084 else
2093 return -ENODEV; 2085 return -ENODEV;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 02197a2b22b9..c503e1776014 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -127,7 +127,6 @@ struct ibmvscsi_ops {
127 int (*resume) (struct ibmvscsi_host_data *hostdata); 127 int (*resume) (struct ibmvscsi_host_data *hostdata);
128}; 128};
129 129
130extern struct ibmvscsi_ops iseriesvscsi_ops;
131extern struct ibmvscsi_ops rpavscsi_ops; 130extern struct ibmvscsi_ops rpavscsi_ops;
132 131
133#endif /* IBMVSCSI_H */ 132#endif /* IBMVSCSI_H */
diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
deleted file mode 100644
index f4776451a754..000000000000
--- a/drivers/scsi/ibmvscsi/iseries_vscsi.c
+++ /dev/null
@@ -1,173 +0,0 @@
1/* ------------------------------------------------------------
2 * iSeries_vscsi.c
3 * (C) Copyright IBM Corporation 1994, 2003
4 * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
5 * Santiago Leon (santil@us.ibm.com)
6 * Dave Boutcher (sleddog@us.ibm.com)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 * ------------------------------------------------------------
24 * iSeries-specific functions of the SCSI host adapter for Virtual I/O devices
25 *
26 * This driver allows the Linux SCSI peripheral drivers to directly
27 * access devices in the hosting partition, either on an iSeries
28 * hypervisor system or a converged hypervisor system.
29 */
30
31#include <asm/iseries/vio.h>
32#include <asm/iseries/hv_lp_event.h>
33#include <asm/iseries/hv_types.h>
34#include <asm/iseries/hv_lp_config.h>
35#include <asm/vio.h>
36#include <linux/device.h>
37#include "ibmvscsi.h"
38
39/* global variables */
40static struct ibmvscsi_host_data *single_host_data;
41
42/* ------------------------------------------------------------
43 * Routines for direct interpartition interaction
44 */
45struct srp_lp_event {
46 struct HvLpEvent lpevt; /* 0x00-0x17 */
47 u32 reserved1; /* 0x18-0x1B; unused */
48 u16 version; /* 0x1C-0x1D; unused */
49 u16 subtype_rc; /* 0x1E-0x1F; unused */
50 struct viosrp_crq crq; /* 0x20-0x3F */
51};
52
53/**
54 * standard interface for handling logical partition events.
55 */
56static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt)
57{
58 struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
59
60 if (!evt) {
61 printk(KERN_ERR "ibmvscsi: received null event\n");
62 return;
63 }
64
65 if (single_host_data == NULL) {
66 printk(KERN_ERR
67 "ibmvscsi: received event, no adapter present\n");
68 return;
69 }
70
71 ibmvscsi_handle_crq(&evt->crq, single_host_data);
72}
73
74/* ------------------------------------------------------------
75 * Routines for driver initialization
76 */
77static int iseriesvscsi_init_crq_queue(struct crq_queue *queue,
78 struct ibmvscsi_host_data *hostdata,
79 int max_requests)
80{
81 int rc;
82
83 single_host_data = hostdata;
84 rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, max_requests);
85 if (rc < 0) {
86 printk("viopath_open failed with rc %d in open_event_path\n",
87 rc);
88 goto viopath_open_failed;
89 }
90
91 rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event);
92 if (rc < 0) {
93 printk("vio_setHandler failed with rc %d in open_event_path\n",
94 rc);
95 goto vio_setHandler_failed;
96 }
97 return 0;
98
99 vio_setHandler_failed:
100 viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
101 viopath_open_failed:
102 return -1;
103}
104
105static void iseriesvscsi_release_crq_queue(struct crq_queue *queue,
106 struct ibmvscsi_host_data *hostdata,
107 int max_requests)
108{
109 vio_clearHandler(viomajorsubtype_scsi);
110 viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
111}
112
113/**
114 * reset_crq_queue: - resets a crq after a failure
115 * @queue: crq_queue to initialize and register
116 * @hostdata: ibmvscsi_host_data of host
117 *
118 * no-op for iSeries
119 */
120static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue,
121 struct ibmvscsi_host_data *hostdata)
122{
123 return 0;
124}
125
126/**
127 * reenable_crq_queue: - reenables a crq after a failure
128 * @queue: crq_queue to initialize and register
129 * @hostdata: ibmvscsi_host_data of host
130 *
131 * no-op for iSeries
132 */
133static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue,
134 struct ibmvscsi_host_data *hostdata)
135{
136 return 0;
137}
138
139/**
140 * iseriesvscsi_send_crq: - Send a CRQ
141 * @hostdata: the adapter
142 * @word1: the first 64 bits of the data
143 * @word2: the second 64 bits of the data
144 */
145static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
146 u64 word1, u64 word2)
147{
148 single_host_data = hostdata;
149 return HvCallEvent_signalLpEventFast(viopath_hostLp,
150 HvLpEvent_Type_VirtualIo,
151 viomajorsubtype_scsi,
152 HvLpEvent_AckInd_NoAck,
153 HvLpEvent_AckType_ImmediateAck,
154 viopath_sourceinst(viopath_hostLp),
155 viopath_targetinst(viopath_hostLp),
156 0,
157 VIOVERSION << 16, word1, word2, 0,
158 0);
159}
160
161static int iseriesvscsi_resume(struct ibmvscsi_host_data *hostdata)
162{
163 return 0;
164}
165
166struct ibmvscsi_ops iseriesvscsi_ops = {
167 .init_crq_queue = iseriesvscsi_init_crq_queue,
168 .release_crq_queue = iseriesvscsi_release_crq_queue,
169 .reset_crq_queue = iseriesvscsi_reset_crq_queue,
170 .reenable_crq_queue = iseriesvscsi_reenable_crq_queue,
171 .send_crq = iseriesvscsi_send_crq,
172 .resume = iseriesvscsi_resume,
173};
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 4222035acfb7..48cb8d3d1758 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -24,16 +24,6 @@ config HVC_OLD_HVSI
24 depends on HVC_CONSOLE 24 depends on HVC_CONSOLE
25 default n 25 default n
26 26
27config HVC_ISERIES
28 bool "iSeries Hypervisor Virtual Console support"
29 depends on PPC_ISERIES
30 default y
31 select HVC_DRIVER
32 select HVC_IRQ
33 select VIOPATH
34 help
35 iSeries machines support a hypervisor virtual console.
36
37config HVC_OPAL 27config HVC_OPAL
38 bool "OPAL Console support" 28 bool "OPAL Console support"
39 depends on PPC_POWERNV 29 depends on PPC_POWERNV
@@ -81,6 +71,10 @@ config HVC_UDBG
81 depends on PPC && EXPERIMENTAL 71 depends on PPC && EXPERIMENTAL
82 select HVC_DRIVER 72 select HVC_DRIVER
83 default n 73 default n
74 help
75 This is meant to be used during HW bring up or debugging when
76 no other console mechanism exist but udbg, to get you a quick
77 console for userspace. Do NOT enable in production kernels.
84 78
85config HVC_DCC 79config HVC_DCC
86 bool "ARM JTAG DCC console" 80 bool "ARM JTAG DCC console"
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 89abf40bc73d..4ca3723b0a3a 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -1,7 +1,6 @@
1obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi_lib.o 1obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi_lib.o
2obj-$(CONFIG_HVC_OPAL) += hvc_opal.o hvsi_lib.o 2obj-$(CONFIG_HVC_OPAL) += hvc_opal.o hvsi_lib.o
3obj-$(CONFIG_HVC_OLD_HVSI) += hvsi.o 3obj-$(CONFIG_HVC_OLD_HVSI) += hvsi.o
4obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
5obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o 4obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o
6obj-$(CONFIG_HVC_TILE) += hvc_tile.o 5obj-$(CONFIG_HVC_TILE) += hvc_tile.o
7obj-$(CONFIG_HVC_DCC) += hvc_dcc.o 6obj-$(CONFIG_HVC_DCC) += hvc_dcc.o
diff --git a/drivers/tty/hvc/hvc_iseries.c b/drivers/tty/hvc/hvc_iseries.c
deleted file mode 100644
index 3f4a897bf4d7..000000000000
--- a/drivers/tty/hvc/hvc_iseries.c
+++ /dev/null
@@ -1,599 +0,0 @@
1/*
2 * iSeries vio driver interface to hvc_console.c
3 *
4 * This code is based heavily on hvc_vio.c and viocons.c
5 *
6 * Copyright (C) 2006 Stephen Rothwell, IBM Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <stdarg.h>
23#include <linux/types.h>
24#include <linux/init.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/spinlock.h>
28#include <linux/console.h>
29
30#include <asm/hvconsole.h>
31#include <asm/vio.h>
32#include <asm/prom.h>
33#include <asm/firmware.h>
34#include <asm/iseries/vio.h>
35#include <asm/iseries/hv_call.h>
36#include <asm/iseries/hv_lp_config.h>
37#include <asm/iseries/hv_lp_event.h>
38
39#include "hvc_console.h"
40
41#define VTTY_PORTS 10
42
43static DEFINE_SPINLOCK(consolelock);
44static DEFINE_SPINLOCK(consoleloglock);
45
46static const char hvc_driver_name[] = "hvc_console";
47
48#define IN_BUF_SIZE 200
49
50/*
51 * Our port information.
52 */
53static struct port_info {
54 HvLpIndex lp;
55 u64 seq; /* sequence number of last HV send */
56 u64 ack; /* last ack from HV */
57 struct hvc_struct *hp;
58 int in_start;
59 int in_end;
60 unsigned char in_buf[IN_BUF_SIZE];
61} port_info[VTTY_PORTS] = {
62 [ 0 ... VTTY_PORTS - 1 ] = {
63 .lp = HvLpIndexInvalid
64 }
65};
66
67#define viochar_is_console(pi) ((pi) == &port_info[0])
68
69static struct vio_device_id hvc_driver_table[] __devinitdata = {
70 {"serial", "IBM,iSeries-vty"},
71 { "", "" }
72};
73MODULE_DEVICE_TABLE(vio, hvc_driver_table);
74
75static void hvlog(char *fmt, ...)
76{
77 int i;
78 unsigned long flags;
79 va_list args;
80 static char buf[256];
81
82 spin_lock_irqsave(&consoleloglock, flags);
83 va_start(args, fmt);
84 i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
85 va_end(args);
86 buf[i++] = '\r';
87 HvCall_writeLogBuffer(buf, i);
88 spin_unlock_irqrestore(&consoleloglock, flags);
89}
90
91/*
92 * Initialize the common fields in a charLpEvent
93 */
94static void init_data_event(struct viocharlpevent *viochar, HvLpIndex lp)
95{
96 struct HvLpEvent *hev = &viochar->event;
97
98 memset(viochar, 0, sizeof(struct viocharlpevent));
99
100 hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
101 HV_LP_EVENT_INT;
102 hev->xType = HvLpEvent_Type_VirtualIo;
103 hev->xSubtype = viomajorsubtype_chario | viochardata;
104 hev->xSourceLp = HvLpConfig_getLpIndex();
105 hev->xTargetLp = lp;
106 hev->xSizeMinus1 = sizeof(struct viocharlpevent);
107 hev->xSourceInstanceId = viopath_sourceinst(lp);
108 hev->xTargetInstanceId = viopath_targetinst(lp);
109}
110
111static int get_chars(uint32_t vtermno, char *buf, int count)
112{
113 struct port_info *pi;
114 int n = 0;
115 unsigned long flags;
116
117 if (vtermno >= VTTY_PORTS)
118 return -EINVAL;
119 if (count == 0)
120 return 0;
121
122 pi = &port_info[vtermno];
123 spin_lock_irqsave(&consolelock, flags);
124
125 if (pi->in_end == 0)
126 goto done;
127
128 n = pi->in_end - pi->in_start;
129 if (n > count)
130 n = count;
131 memcpy(buf, &pi->in_buf[pi->in_start], n);
132 pi->in_start += n;
133 if (pi->in_start == pi->in_end) {
134 pi->in_start = 0;
135 pi->in_end = 0;
136 }
137done:
138 spin_unlock_irqrestore(&consolelock, flags);
139 return n;
140}
141
142static int put_chars(uint32_t vtermno, const char *buf, int count)
143{
144 struct viocharlpevent *viochar;
145 struct port_info *pi;
146 HvLpEvent_Rc hvrc;
147 unsigned long flags;
148 int sent = 0;
149
150 if (vtermno >= VTTY_PORTS)
151 return -EINVAL;
152
153 pi = &port_info[vtermno];
154
155 spin_lock_irqsave(&consolelock, flags);
156
157 if (viochar_is_console(pi) && !viopath_isactive(pi->lp)) {
158 HvCall_writeLogBuffer(buf, count);
159 sent = count;
160 goto done;
161 }
162
163 viochar = vio_get_event_buffer(viomajorsubtype_chario);
164 if (viochar == NULL) {
165 hvlog("\n\rviocons: Can't get viochar buffer.");
166 goto done;
167 }
168
169 while ((count > 0) && ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
170 int len;
171
172 len = (count > VIOCHAR_MAX_DATA) ? VIOCHAR_MAX_DATA : count;
173
174 if (viochar_is_console(pi))
175 HvCall_writeLogBuffer(buf, len);
176
177 init_data_event(viochar, pi->lp);
178
179 viochar->len = len;
180 viochar->event.xCorrelationToken = pi->seq++;
181 viochar->event.xSizeMinus1 =
182 offsetof(struct viocharlpevent, data) + len;
183
184 memcpy(viochar->data, buf, len);
185
186 hvrc = HvCallEvent_signalLpEvent(&viochar->event);
187 if (hvrc)
188 hvlog("\n\rerror sending event! return code %d\n\r",
189 (int)hvrc);
190 sent += len;
191 count -= len;
192 buf += len;
193 }
194
195 vio_free_event_buffer(viomajorsubtype_chario, viochar);
196done:
197 spin_unlock_irqrestore(&consolelock, flags);
198 return sent;
199}
200
201static const struct hv_ops hvc_get_put_ops = {
202 .get_chars = get_chars,
203 .put_chars = put_chars,
204 .notifier_add = notifier_add_irq,
205 .notifier_del = notifier_del_irq,
206 .notifier_hangup = notifier_hangup_irq,
207};
208
209static int __devinit hvc_vio_probe(struct vio_dev *vdev,
210 const struct vio_device_id *id)
211{
212 struct hvc_struct *hp;
213 struct port_info *pi;
214
215 /* probed with invalid parameters. */
216 if (!vdev || !id)
217 return -EPERM;
218
219 if (vdev->unit_address >= VTTY_PORTS)
220 return -ENODEV;
221
222 pi = &port_info[vdev->unit_address];
223
224 hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
225 VIOCHAR_MAX_DATA);
226 if (IS_ERR(hp))
227 return PTR_ERR(hp);
228 pi->hp = hp;
229 dev_set_drvdata(&vdev->dev, pi);
230
231 return 0;
232}
233
234static int __devexit hvc_vio_remove(struct vio_dev *vdev)
235{
236 struct port_info *pi = dev_get_drvdata(&vdev->dev);
237 struct hvc_struct *hp = pi->hp;
238
239 return hvc_remove(hp);
240}
241
242static struct vio_driver hvc_vio_driver = {
243 .id_table = hvc_driver_table,
244 .probe = hvc_vio_probe,
245 .remove = __devexit_p(hvc_vio_remove),
246 .driver = {
247 .name = hvc_driver_name,
248 .owner = THIS_MODULE,
249 }
250};
251
252static void hvc_open_event(struct HvLpEvent *event)
253{
254 unsigned long flags;
255 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
256 u8 port = cevent->virtual_device;
257 struct port_info *pi;
258 int reject = 0;
259
260 if (hvlpevent_is_ack(event)) {
261 if (port >= VTTY_PORTS)
262 return;
263
264 spin_lock_irqsave(&consolelock, flags);
265
266 pi = &port_info[port];
267 if (event->xRc == HvLpEvent_Rc_Good) {
268 pi->seq = pi->ack = 0;
269 /*
270 * This line allows connections from the primary
271 * partition but once one is connected from the
272 * primary partition nothing short of a reboot
273 * of linux will allow access from the hosting
274 * partition again without a required iSeries fix.
275 */
276 pi->lp = event->xTargetLp;
277 }
278
279 spin_unlock_irqrestore(&consolelock, flags);
280 if (event->xRc != HvLpEvent_Rc_Good)
281 printk(KERN_WARNING
282 "hvc: handle_open_event: event->xRc == (%d).\n",
283 event->xRc);
284
285 if (event->xCorrelationToken != 0) {
286 atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
287 atomic_set(aptr, 1);
288 } else
289 printk(KERN_WARNING
290 "hvc: weird...got open ack without atomic\n");
291 return;
292 }
293
294 /* This had better require an ack, otherwise complain */
295 if (!hvlpevent_need_ack(event)) {
296 printk(KERN_WARNING "hvc: viocharopen without ack bit!\n");
297 return;
298 }
299
300 spin_lock_irqsave(&consolelock, flags);
301
302 /* Make sure this is a good virtual tty */
303 if (port >= VTTY_PORTS) {
304 event->xRc = HvLpEvent_Rc_SubtypeError;
305 cevent->subtype_result_code = viorc_openRejected;
306 /*
307 * Flag state here since we can't printk while holding
308 * the consolelock spinlock.
309 */
310 reject = 1;
311 } else {
312 pi = &port_info[port];
313 if ((pi->lp != HvLpIndexInvalid) &&
314 (pi->lp != event->xSourceLp)) {
315 /*
316 * If this is tty is already connected to a different
317 * partition, fail.
318 */
319 event->xRc = HvLpEvent_Rc_SubtypeError;
320 cevent->subtype_result_code = viorc_openRejected;
321 reject = 2;
322 } else {
323 pi->lp = event->xSourceLp;
324 event->xRc = HvLpEvent_Rc_Good;
325 cevent->subtype_result_code = viorc_good;
326 pi->seq = pi->ack = 0;
327 }
328 }
329
330 spin_unlock_irqrestore(&consolelock, flags);
331
332 if (reject == 1)
333 printk(KERN_WARNING "hvc: open rejected: bad virtual tty.\n");
334 else if (reject == 2)
335 printk(KERN_WARNING "hvc: open rejected: console in exclusive "
336 "use by another partition.\n");
337
338 /* Return the acknowledgement */
339 HvCallEvent_ackLpEvent(event);
340}
341
342/*
343 * Handle a close charLpEvent. This should ONLY be an Interrupt because the
344 * virtual console should never actually issue a close event to the hypervisor
345 * because the virtual console never goes away. A close event coming from the
346 * hypervisor simply means that there are no client consoles connected to the
347 * virtual console.
348 */
349static void hvc_close_event(struct HvLpEvent *event)
350{
351 unsigned long flags;
352 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
353 u8 port = cevent->virtual_device;
354
355 if (!hvlpevent_is_int(event)) {
356 printk(KERN_WARNING
357 "hvc: got unexpected close acknowledgement\n");
358 return;
359 }
360
361 if (port >= VTTY_PORTS) {
362 printk(KERN_WARNING
363 "hvc: close message from invalid virtual device.\n");
364 return;
365 }
366
367 /* For closes, just mark the console partition invalid */
368 spin_lock_irqsave(&consolelock, flags);
369
370 if (port_info[port].lp == event->xSourceLp)
371 port_info[port].lp = HvLpIndexInvalid;
372
373 spin_unlock_irqrestore(&consolelock, flags);
374}
375
376static void hvc_data_event(struct HvLpEvent *event)
377{
378 unsigned long flags;
379 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
380 struct port_info *pi;
381 int n;
382 u8 port = cevent->virtual_device;
383
384 if (port >= VTTY_PORTS) {
385 printk(KERN_WARNING "hvc: data on invalid virtual device %d\n",
386 port);
387 return;
388 }
389 if (cevent->len == 0)
390 return;
391
392 /*
393 * Change 05/01/2003 - Ryan Arnold: If a partition other than
394 * the current exclusive partition tries to send us data
395 * events then just drop them on the floor because we don't
396 * want his stinking data. He isn't authorized to receive
397 * data because he wasn't the first one to get the console,
398 * therefore he shouldn't be allowed to send data either.
399 * This will work without an iSeries fix.
400 */
401 pi = &port_info[port];
402 if (pi->lp != event->xSourceLp)
403 return;
404
405 spin_lock_irqsave(&consolelock, flags);
406
407 n = IN_BUF_SIZE - pi->in_end;
408 if (n > cevent->len)
409 n = cevent->len;
410 if (n > 0) {
411 memcpy(&pi->in_buf[pi->in_end], cevent->data, n);
412 pi->in_end += n;
413 }
414 spin_unlock_irqrestore(&consolelock, flags);
415 if (n == 0)
416 printk(KERN_WARNING "hvc: input buffer overflow\n");
417}
418
419static void hvc_ack_event(struct HvLpEvent *event)
420{
421 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
422 unsigned long flags;
423 u8 port = cevent->virtual_device;
424
425 if (port >= VTTY_PORTS) {
426 printk(KERN_WARNING "hvc: data on invalid virtual device\n");
427 return;
428 }
429
430 spin_lock_irqsave(&consolelock, flags);
431 port_info[port].ack = event->xCorrelationToken;
432 spin_unlock_irqrestore(&consolelock, flags);
433}
434
435static void hvc_config_event(struct HvLpEvent *event)
436{
437 struct viocharlpevent *cevent = (struct viocharlpevent *)event;
438
439 if (cevent->data[0] == 0x01)
440 printk(KERN_INFO "hvc: window resized to %d: %d: %d: %d\n",
441 cevent->data[1], cevent->data[2],
442 cevent->data[3], cevent->data[4]);
443 else
444 printk(KERN_WARNING "hvc: unknown config event\n");
445}
446
447static void hvc_handle_event(struct HvLpEvent *event)
448{
449 int charminor;
450
451 if (event == NULL)
452 return;
453
454 charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
455 switch (charminor) {
456 case viocharopen:
457 hvc_open_event(event);
458 break;
459 case viocharclose:
460 hvc_close_event(event);
461 break;
462 case viochardata:
463 hvc_data_event(event);
464 break;
465 case viocharack:
466 hvc_ack_event(event);
467 break;
468 case viocharconfig:
469 hvc_config_event(event);
470 break;
471 default:
472 if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
473 event->xRc = HvLpEvent_Rc_InvalidSubtype;
474 HvCallEvent_ackLpEvent(event);
475 }
476 }
477}
478
479static int __init send_open(HvLpIndex remoteLp, void *sem)
480{
481 return HvCallEvent_signalLpEventFast(remoteLp,
482 HvLpEvent_Type_VirtualIo,
483 viomajorsubtype_chario | viocharopen,
484 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
485 viopath_sourceinst(remoteLp),
486 viopath_targetinst(remoteLp),
487 (u64)(unsigned long)sem, VIOVERSION << 16,
488 0, 0, 0, 0);
489}
490
491static int __init hvc_vio_init(void)
492{
493 atomic_t wait_flag;
494 int rc;
495
496 if (!firmware_has_feature(FW_FEATURE_ISERIES))
497 return -EIO;
498
499 /* +2 for fudge */
500 rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
501 viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
502 if (rc)
503 printk(KERN_WARNING "hvc: error opening to primary %d\n", rc);
504
505 if (viopath_hostLp == HvLpIndexInvalid)
506 vio_set_hostlp();
507
508 /*
509 * And if the primary is not the same as the hosting LP, open to the
510 * hosting lp
511 */
512 if ((viopath_hostLp != HvLpIndexInvalid) &&
513 (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
514 printk(KERN_INFO "hvc: open path to hosting (%d)\n",
515 viopath_hostLp);
516 rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
517 VIOCHAR_WINDOW + 2); /* +2 for fudge */
518 if (rc)
519 printk(KERN_WARNING
520 "error opening to partition %d: %d\n",
521 viopath_hostLp, rc);
522 }
523
524 if (vio_setHandler(viomajorsubtype_chario, hvc_handle_event) < 0)
525 printk(KERN_WARNING
526 "hvc: error seting handler for console events!\n");
527
528 /*
529 * First, try to open the console to the hosting lp.
530 * Wait on a semaphore for the response.
531 */
532 atomic_set(&wait_flag, 0);
533 if ((viopath_isactive(viopath_hostLp)) &&
534 (send_open(viopath_hostLp, &wait_flag) == 0)) {
535 printk(KERN_INFO "hvc: hosting partition %d\n", viopath_hostLp);
536 while (atomic_read(&wait_flag) == 0)
537 mb();
538 atomic_set(&wait_flag, 0);
539 }
540
541 /*
542 * If we don't have an active console, try the primary
543 */
544 if ((!viopath_isactive(port_info[0].lp)) &&
545 (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
546 (send_open(HvLpConfig_getPrimaryLpIndex(), &wait_flag) == 0)) {
547 printk(KERN_INFO "hvc: opening console to primary partition\n");
548 while (atomic_read(&wait_flag) == 0)
549 mb();
550 }
551
552 /* Register as a vio device to receive callbacks */
553 rc = vio_register_driver(&hvc_vio_driver);
554
555 return rc;
556}
557module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
558
559static void __exit hvc_vio_exit(void)
560{
561 vio_unregister_driver(&hvc_vio_driver);
562}
563module_exit(hvc_vio_exit);
564
565/* the device tree order defines our numbering */
566static int __init hvc_find_vtys(void)
567{
568 struct device_node *vty;
569 int num_found = 0;
570
571 for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
572 vty = of_find_node_by_name(vty, "vty")) {
573 const uint32_t *vtermno;
574
575 /* We have statically defined space for only a certain number
576 * of console adapters.
577 */
578 if ((num_found >= MAX_NR_HVC_CONSOLES) ||
579 (num_found >= VTTY_PORTS)) {
580 of_node_put(vty);
581 break;
582 }
583
584 vtermno = of_get_property(vty, "reg", NULL);
585 if (!vtermno)
586 continue;
587
588 if (!of_device_is_compatible(vty, "IBM,iSeries-vty"))
589 continue;
590
591 if (num_found == 0)
592 add_preferred_console("hvc", 0, NULL);
593 hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
594 ++num_found;
595 }
596
597 return num_found;
598}
599console_initcall(hvc_find_vtys);
diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c
index 4c9b13e7748c..72228276fe31 100644
--- a/drivers/tty/hvc/hvc_udbg.c
+++ b/drivers/tty/hvc/hvc_udbg.c
@@ -36,7 +36,7 @@ static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
36{ 36{
37 int i; 37 int i;
38 38
39 for (i = 0; i < count; i++) 39 for (i = 0; i < count && udbg_putc; i++)
40 udbg_putc(buf[i]); 40 udbg_putc(buf[i]);
41 41
42 return i; 42 return i;
@@ -67,6 +67,9 @@ static int __init hvc_udbg_init(void)
67{ 67{
68 struct hvc_struct *hp; 68 struct hvc_struct *hp;
69 69
70 if (!udbg_putc)
71 return -ENODEV;
72
70 BUG_ON(hvc_udbg_dev); 73 BUG_ON(hvc_udbg_dev);
71 74
72 hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16); 75 hp = hvc_alloc(0, 0, &hvc_udbg_ops, 16);
@@ -88,6 +91,9 @@ module_exit(hvc_udbg_exit);
88 91
89static int __init hvc_udbg_console_init(void) 92static int __init hvc_udbg_console_init(void)
90{ 93{
94 if (!udbg_putc)
95 return -ENODEV;
96
91 hvc_instantiate(0, 0, &hvc_udbg_ops); 97 hvc_instantiate(0, 0, &hvc_udbg_ops);
92 add_preferred_console("hvc", 0, NULL); 98 add_preferred_console("hvc", 0, NULL);
93 99
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index fc3c3ad6c072..3a0d53d6368f 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -46,7 +46,6 @@
46#include <asm/hvconsole.h> 46#include <asm/hvconsole.h>
47#include <asm/vio.h> 47#include <asm/vio.h>
48#include <asm/prom.h> 48#include <asm/prom.h>
49#include <asm/firmware.h>
50#include <asm/hvsi.h> 49#include <asm/hvsi.h>
51#include <asm/udbg.h> 50#include <asm/udbg.h>
52 51
@@ -322,9 +321,6 @@ static int __init hvc_vio_init(void)
322{ 321{
323 int rc; 322 int rc;
324 323
325 if (firmware_has_feature(FW_FEATURE_ISERIES))
326 return -EIO;
327
328 /* Register as a vio device to receive callbacks */ 324 /* Register as a vio device to receive callbacks */
329 rc = vio_register_driver(&hvc_vio_driver); 325 rc = vio_register_driver(&hvc_vio_driver);
330 326
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 76e7764488e6..665beb68f670 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -853,7 +853,7 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
853 853
854config SERIAL_ICOM 854config SERIAL_ICOM
855 tristate "IBM Multiport Serial Adapter" 855 tristate "IBM Multiport Serial Adapter"
856 depends on PCI && (PPC_ISERIES || PPC_PSERIES) 856 depends on PCI && PPC_PSERIES
857 select SERIAL_CORE 857 select SERIAL_CORE
858 select FW_LOADER 858 select FW_LOADER
859 help 859 help
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index df9e8f0e327d..7e9e8f4d8f0c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1039,7 +1039,7 @@ config LANTIQ_WDT
1039 1039
1040config GEF_WDT 1040config GEF_WDT
1041 tristate "GE Watchdog Timer" 1041 tristate "GE Watchdog Timer"
1042 depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A 1042 depends on GE_FPGA
1043 ---help--- 1043 ---help---
1044 Watchdog timer found in a number of GE single board computers. 1044 Watchdog timer found in a number of GE single board computers.
1045 1045
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index b0f450a2bb7c..0d5071d29985 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -700,3 +700,26 @@ static int __init vmcore_init(void)
700 return 0; 700 return 0;
701} 701}
702module_init(vmcore_init) 702module_init(vmcore_init)
703
704/* Cleanup function for vmcore module. */
705void vmcore_cleanup(void)
706{
707 struct list_head *pos, *next;
708
709 if (proc_vmcore) {
710 remove_proc_entry(proc_vmcore->name, proc_vmcore->parent);
711 proc_vmcore = NULL;
712 }
713
714 /* clear the vmcore list. */
715 list_for_each_safe(pos, next, &vmcore_list) {
716 struct vmcore *m;
717
718 m = list_entry(pos, struct vmcore, list);
719 list_del(&m->list);
720 kfree(m);
721 }
722 kfree(elfcorebuf);
723 elfcorebuf = NULL;
724}
725EXPORT_SYMBOL_GPL(vmcore_cleanup);
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index 42b77b5446d2..70cfcb2d63c4 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -24,7 +24,9 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
24 * Atomically increments @v by 1, so long as @v is non-zero. 24 * Atomically increments @v by 1, so long as @v is non-zero.
25 * Returns non-zero if @v was non-zero, and zero otherwise. 25 * Returns non-zero if @v was non-zero, and zero otherwise.
26 */ 26 */
27#ifndef atomic_inc_not_zero
27#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 28#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
29#endif
28 30
29/** 31/**
30 * atomic_inc_not_zero_hint - increment if not null 32 * atomic_inc_not_zero_hint - increment if not null
diff --git a/include/linux/device.h b/include/linux/device.h
index 7c46bc32fcbf..5ad17cccdd71 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -262,10 +262,6 @@ extern int __must_check driver_create_file(struct device_driver *driver,
262extern void driver_remove_file(struct device_driver *driver, 262extern void driver_remove_file(struct device_driver *driver,
263 const struct driver_attribute *attr); 263 const struct driver_attribute *attr);
264 264
265extern int __must_check driver_add_kobj(struct device_driver *drv,
266 struct kobject *kobj,
267 const char *fmt, ...);
268
269extern int __must_check driver_for_each_device(struct device_driver *drv, 265extern int __must_check driver_for_each_device(struct device_driver *drv,
270 struct device *start, 266 struct device *start,
271 void *data, 267 void *data,
diff --git a/include/linux/of.h b/include/linux/of.h
index f02d8b2f799d..d46a18ffbebb 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -58,6 +58,9 @@ struct device_node {
58 struct kref kref; 58 struct kref kref;
59 unsigned long _flags; 59 unsigned long _flags;
60 void *data; 60 void *data;
61#if defined(CONFIG_EEH)
62 struct eeh_dev *edev;
63#endif
61#if defined(CONFIG_SPARC) 64#if defined(CONFIG_SPARC)
62 char *path_component_name; 65 char *path_component_name;
63 unsigned int unique_id; 66 unsigned int unique_id;
@@ -72,6 +75,13 @@ struct of_phandle_args {
72 uint32_t args[MAX_PHANDLE_ARGS]; 75 uint32_t args[MAX_PHANDLE_ARGS];
73}; 76};
74 77
78#if defined(CONFIG_EEH)
79static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
80{
81 return dn->edev;
82}
83#endif
84
75#ifdef CONFIG_OF_DYNAMIC 85#ifdef CONFIG_OF_DYNAMIC
76extern struct device_node *of_node_get(struct device_node *node); 86extern struct device_node *of_node_get(struct device_node *node);
77extern void of_node_put(struct device_node *node); 87extern void of_node_put(struct device_node *node);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index b843fe79583b..27bf521bcebd 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1660,6 +1660,13 @@ static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
1660static inline void pci_release_bus_of_node(struct pci_bus *bus) { } 1660static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
1661#endif /* CONFIG_OF */ 1661#endif /* CONFIG_OF */
1662 1662
1663#ifdef CONFIG_EEH
1664static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev)
1665{
1666 return pdev->dev.archdata.edev;
1667}
1668#endif
1669
1663/** 1670/**
1664 * pci_find_upstream_pcie_bridge - find upstream PCIe-to-PCI bridge of a device 1671 * pci_find_upstream_pcie_bridge - find upstream PCIe-to-PCI bridge of a device
1665 * @pdev: the PCI device 1672 * @pdev: the PCI device
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 887629e24c54..01f1306aa26e 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -178,7 +178,7 @@ int __init rd_load_image(char *from)
178 char *buf = NULL; 178 char *buf = NULL;
179 unsigned short rotate = 0; 179 unsigned short rotate = 0;
180 decompress_fn decompressor = NULL; 180 decompress_fn decompressor = NULL;
181#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) 181#if !defined(CONFIG_S390)
182 char rotator[4] = { '|' , '/' , '-' , '\\' }; 182 char rotator[4] = { '|' , '/' , '-' , '\\' };
183#endif 183#endif
184 184
@@ -264,7 +264,7 @@ int __init rd_load_image(char *from)
264 } 264 }
265 sys_read(in_fd, buf, BLOCK_SIZE); 265 sys_read(in_fd, buf, BLOCK_SIZE);
266 sys_write(out_fd, buf, BLOCK_SIZE); 266 sys_write(out_fd, buf, BLOCK_SIZE);
267#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) 267#if !defined(CONFIG_S390)
268 if (!(i % 16)) { 268 if (!(i % 16)) {
269 printk("%c\b", rotator[rotate & 0x3]); 269 printk("%c\b", rotator[rotate & 0x3]);
270 rotate++; 270 rotate++;