Merge tag 'iwlwifi-for-kalle-2016-04-12_2' of https://git.kernel.org/pub/scm/linux...
authorKalle Valo <kvalo@codeaurora.org>
Thu, 21 Apr 2016 12:40:13 +0000 (15:40 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 21 Apr 2016 12:40:13 +0000 (15:40 +0300)
* add new device IDs for 8265
* fix a NULL pointer dereference when paging firmware asserts
* remove a WARNING on gscan capabilities
* fix MODULE_FIRMWARE for 8260

499 files changed:
Documentation/ABI/testing/sysfs-class-cxl
Documentation/DMA-attributes.txt
Documentation/devicetree/bindings/arm/arm-boards
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/input/ads7846.txt
Documentation/devicetree/bindings/powerpc/fsl/fman.txt
Documentation/devicetree/bindings/property-units.txt [new file with mode: 0644]
Documentation/devicetree/bindings/soc/fsl/rcpm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/booting-without-of.txt
Documentation/driver-model/porting.txt
Documentation/kernel-parameters.txt
Documentation/networking/ip-sysctl.txt
Documentation/powerpc/cxl.txt
MAINTAINERS
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/piggy.S [new file with mode: 0644]
arch/arm/boot/compressed/piggy.gzip.S [deleted file]
arch/arm/boot/compressed/piggy.lz4.S [deleted file]
arch/arm/boot/compressed/piggy.lzma.S [deleted file]
arch/arm/boot/compressed/piggy.lzo.S [deleted file]
arch/arm/boot/compressed/piggy.xzkern.S [deleted file]
arch/arm/boot/compressed/string.c
arch/arm/common/sa1111.c
arch/arm/include/asm/Kbuild
arch/arm/include/asm/div64.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/sections.h [new file with mode: 0644]
arch/arm/include/asm/sparsemem.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/hibernate.c
arch/arm/kernel/hyp-stub.S
arch/arm/kernel/irq.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/module.c
arch/arm/kernel/reboot.c
arch/arm/kernel/topology.c
arch/arm/kernel/vmlinux-xip.lds.S [new file with mode: 0644]
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-davinci/include/mach/uncompress.h
arch/arm/mach-footbridge/Kconfig
arch/arm/mach-keystone/keystone.c
arch/arm/mach-ks8695/include/mach/uncompress.h
arch/arm/mach-netx/include/mach/uncompress.h
arch/arm/mach-omap1/include/mach/uncompress.h
arch/arm/mach-rpc/include/mach/uncompress.h
arch/arm/mach-sa1100/include/mach/uncompress.h
arch/arm/mach-w90x900/include/mach/uncompress.h
arch/arm/mm/Kconfig
arch/arm/mm/cache-tauros2.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/idmap.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v7.S
arch/arm/plat-orion/time.c
arch/arm64/kernel/psci.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/dts/fsl/b4860qds.dts
arch/powerpc/boot/dts/fsl/b4qds.dtsi
arch/powerpc/boot/dts/fsl/bsc9131rdb.dtsi
arch/powerpc/boot/dts/fsl/bsc9132qds.dtsi
arch/powerpc/boot/dts/fsl/c293pcie.dts
arch/powerpc/boot/dts/fsl/gef_ppc9a.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/gef_sbc310.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/gef_sbc610.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/kmcoge4.dts
arch/powerpc/boot/dts/fsl/mpc8536ds.dtsi
arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/mvme2500.dts
arch/powerpc/boot/dts/fsl/p1010rdb.dtsi
arch/powerpc/boot/dts/fsl/p1020rdb-pc.dtsi
arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts
arch/powerpc/boot/dts/fsl/p1020rdb.dtsi
arch/powerpc/boot/dts/fsl/p1021mds.dts
arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi
arch/powerpc/boot/dts/fsl/p1022ds.dtsi
arch/powerpc/boot/dts/fsl/p1022rdk.dts
arch/powerpc/boot/dts/fsl/p1024rdb.dtsi
arch/powerpc/boot/dts/fsl/p1025rdb.dtsi
arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi
arch/powerpc/boot/dts/fsl/p2020rdb.dts
arch/powerpc/boot/dts/fsl/p2041rdb.dts
arch/powerpc/boot/dts/fsl/p3041ds.dts
arch/powerpc/boot/dts/fsl/p4080ds.dts
arch/powerpc/boot/dts/fsl/p5020ds.dts
arch/powerpc/boot/dts/fsl/p5040ds.dts
arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
arch/powerpc/boot/dts/fsl/sbc8641d.dts [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/t1023rdb.dts
arch/powerpc/boot/dts/fsl/t1024qds.dts
arch/powerpc/boot/dts/fsl/t1024rdb.dts
arch/powerpc/boot/dts/fsl/t1040rdb.dts
arch/powerpc/boot/dts/fsl/t1042rdb.dts
arch/powerpc/boot/dts/fsl/t1042rdb_pi.dts
arch/powerpc/boot/dts/fsl/t104xd4rdb.dtsi
arch/powerpc/boot/dts/fsl/t104xqds.dtsi
arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
arch/powerpc/boot/dts/fsl/t2080qds.dts
arch/powerpc/boot/dts/fsl/t2080rdb.dts
arch/powerpc/boot/dts/fsl/t2081qds.dts
arch/powerpc/boot/dts/fsl/t208xqds.dtsi
arch/powerpc/boot/dts/fsl/t208xrdb.dtsi
arch/powerpc/boot/dts/fsl/t4240qds.dts
arch/powerpc/boot/dts/fsl/t4240rdb.dts
arch/powerpc/boot/dts/gef_ppc9a.dts [deleted file]
arch/powerpc/boot/dts/gef_sbc310.dts [deleted file]
arch/powerpc/boot/dts/gef_sbc610.dts [deleted file]
arch/powerpc/boot/dts/mpc8641_hpcn.dts [deleted file]
arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts [deleted file]
arch/powerpc/boot/dts/sbc8641d.dts [deleted file]
arch/powerpc/boot/rs6000.h
arch/powerpc/boot/treeboot-akebono.c
arch/powerpc/boot/treeboot-currituck.c
arch/powerpc/boot/treeboot-iss4xx.c
arch/powerpc/configs/83xx/mpc834x_itx_defconfig
arch/powerpc/configs/85xx/ksi8560_defconfig
arch/powerpc/configs/85xx/stx_gp3_defconfig
arch/powerpc/configs/86xx-hw.config [new file with mode: 0644]
arch/powerpc/configs/86xx-smp.config [new file with mode: 0644]
arch/powerpc/configs/86xx/gef_ppc9a_defconfig [deleted file]
arch/powerpc/configs/86xx/gef_sbc310_defconfig [deleted file]
arch/powerpc/configs/86xx/gef_sbc610_defconfig [deleted file]
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig [deleted file]
arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig [deleted file]
arch/powerpc/configs/86xx/sbc8641d_defconfig [deleted file]
arch/powerpc/configs/mpc86xx_basic_defconfig [new file with mode: 0644]
arch/powerpc/configs/mpc86xx_defconfig [deleted file]
arch/powerpc/configs/powernv_defconfig [new file with mode: 0644]
arch/powerpc/crypto/aes-spe-core.S
arch/powerpc/crypto/aes-spe-glue.c
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/book3s/32/mmu-hash.h [new file with mode: 0644]
arch/powerpc/include/asm/book3s/64/hash-4k.h
arch/powerpc/include/asm/book3s/64/hash-64k.h
arch/powerpc/include/asm/book3s/64/hash.h
arch/powerpc/include/asm/book3s/64/mmu-hash.h [new file with mode: 0644]
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/book3s/64/tlbflush-hash.h [new file with mode: 0644]
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/cacheflush.h
arch/powerpc/include/asm/checksum.h
arch/powerpc/include/asm/cmpxchg.h
arch/powerpc/include/asm/code-patching.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/cputhreads.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/fsl_pm.h [new file with mode: 0644]
arch/powerpc/include/asm/ftrace.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/hydra.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/mmu-8xx.h
arch/powerpc/include/asm/mmu-hash32.h [deleted file]
arch/powerpc/include/asm/mmu-hash64.h [deleted file]
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/nohash/32/pgtable.h
arch/powerpc/include/asm/nohash/64/pgtable.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/page_32.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/pgtable-types.h [new file with mode: 0644]
arch/powerpc/include/asm/pmac_feature.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/reg_8xx.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/smu.h
arch/powerpc/include/asm/switch_to.h
arch/powerpc/include/asm/time.h
arch/powerpc/include/asm/tlbflush.h
arch/powerpc/include/asm/uninorth.h
arch/powerpc/include/asm/xics.h
arch/powerpc/include/uapi/asm/epapr_hcalls.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_cache.c
arch/powerpc/kernel/eeh_dev.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/fpu.S
arch/powerpc/kernel/ftrace.c
arch/powerpc/kernel/head_44x.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/mce_power.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/module.c
arch/powerpc/kernel/module_32.c
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci-hotplug.c
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/ppc_ksyms_32.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal.h
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vector.S
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_64_vio.c
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_xics.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/lib/Makefile
arch/powerpc/lib/checksum_32.S
arch/powerpc/lib/checksum_64.S
arch/powerpc/lib/checksum_wrappers.c [new file with mode: 0644]
arch/powerpc/lib/checksum_wrappers_64.c [deleted file]
arch/powerpc/lib/ppc_ksyms.c
arch/powerpc/mm/8xx_mmu.c [new file with mode: 0644]
arch/powerpc/mm/Makefile
arch/powerpc/mm/dma-noncoherent.c
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash64_4k.c
arch/powerpc/mm/hash64_64k.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/mm/tlb_nohash_low.S
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/perf/hv-24x7.h
arch/powerpc/perf/hv-gpci.c
arch/powerpc/perf/power7-pmu.c
arch/powerpc/perf/power8-events-list.h [new file with mode: 0644]
arch/powerpc/perf/power8-pmu.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/common.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/85xx/smp.h
arch/powerpc/platforms/86xx/Makefile
arch/powerpc/platforms/86xx/common.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/gef_ppc9a.c
arch/powerpc/platforms/86xx/gef_sbc310.c
arch/powerpc/platforms/86xx/gef_sbc610.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx.h
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/86xx/sbc8641d.c
arch/powerpc/platforms/embedded6xx/mpc10x.h
arch/powerpc/platforms/powermac/Makefile
arch/powerpc/platforms/powermac/cache.S
arch/powerpc/platforms/powermac/feature.c
arch/powerpc/platforms/powernv/Makefile
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/idle.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/platforms/powernv/opal-msglog.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci-p5ioc2.c [deleted file]
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/powernv/subcore.c
arch/powerpc/platforms/ps3/gelic_udbg.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/pseries/hvconsole.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/scripts/gcc-check-mprofile-kernel.sh [new file with mode: 0755]
arch/powerpc/sysdev/Kconfig
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/cpm1.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_rcpm.c [new file with mode: 0644]
arch/powerpc/sysdev/fsl_rmu.c
arch/powerpc/sysdev/i8259.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/xmon/xmon.c
arch/sh/Kconfig
arch/sh/boards/Kconfig
arch/sh/boards/Makefile
arch/sh/boards/of-generic.c [new file with mode: 0644]
arch/sh/boot/compressed/Makefile
arch/sh/include/asm/Kbuild
arch/sh/include/asm/clkdev.h [deleted file]
arch/sh/include/asm/smp.h
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/sh2/entry.S
arch/sh/kernel/cpu/sh2a/entry.S
arch/sh/kernel/entry-common.S
arch/sh/kernel/head_32.S
arch/sh/kernel/localtimer.c [deleted file]
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/kernel/smp.c
arch/sh/lib/ashlsi3.S
arch/sh/lib/ashrsi3.S
arch/sh/lib/lshrsi3.S
arch/sh/mm/kmap.c
drivers/base/dd.c
drivers/bcma/main.c
drivers/clk/clkdev.c
drivers/firmware/psci.c
drivers/isdn/mISDN/clock.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/misc/cxl/Makefile
drivers/misc/cxl/api.c
drivers/misc/cxl/base.c
drivers/misc/cxl/context.c
drivers/misc/cxl/cxl.h
drivers/misc/cxl/debugfs.c
drivers/misc/cxl/fault.c
drivers/misc/cxl/file.c
drivers/misc/cxl/flash.c [new file with mode: 0644]
drivers/misc/cxl/guest.c [new file with mode: 0644]
drivers/misc/cxl/hcalls.c [new file with mode: 0644]
drivers/misc/cxl/hcalls.h [new file with mode: 0644]
drivers/misc/cxl/irq.c
drivers/misc/cxl/main.c
drivers/misc/cxl/native.c
drivers/misc/cxl/of.c [new file with mode: 0644]
drivers/misc/cxl/pci.c
drivers/misc/cxl/sysfs.c
drivers/misc/cxl/trace.h
drivers/misc/cxl/vphb.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/hisilicon/hns/hnae.h
drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/geneve.c
drivers/net/phy/mdio-sun4i.c
drivers/net/usb/lan78xx.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9002_phy.c
drivers/net/wireless/broadcom/b43/main.c
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c
drivers/nvdimm/bus.c
drivers/of/base.c
drivers/of/of_reserved_mem.c
drivers/of/resolver.c
drivers/of/unittest.c
drivers/pci/bus.c
drivers/pci/iov.c
drivers/scsi/cxlflash/common.h
drivers/scsi/cxlflash/main.c
drivers/soc/fsl/qe/qe_common.c
drivers/soc/fsl/qe/qe_ic.c
include/linux/atomic.h
include/linux/bug.h
include/linux/clkdev.h
include/linux/device.h
include/linux/dma-attrs.h
include/linux/fsl/guts.h
include/linux/huge_mm.h
include/linux/mISDNif.h
include/linux/netdevice.h
include/linux/of.h
include/linux/pci.h
include/linux/psci.h
include/media/videobuf2-dma-contig.h
include/misc/cxl.h
include/net/flow.h
include/net/inet6_connection_sock.h
include/net/ip_tunnels.h
include/net/ipv6.h
include/net/sctp/sctp.h
include/net/sctp/structs.h
include/net/vxlan.h
include/soc/fsl/qe/qe.h
include/trace/events/fib6.h
include/uapi/linux/ethtool.h
include/uapi/linux/if_link.h
include/uapi/misc/cxl.h
mm/huge_memory.c
net/Kconfig
net/bridge/br_if.c
net/core/dev.c
net/core/gen_estimator.c
net/core/gen_stats.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/af_inet.c
net/ipv4/fib_frontend.c
net/ipv4/fou.c
net/ipv4/gre_offload.c
net/ipv4/ip_tunnel_core.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/ip6_offload.c
net/ipv6/sit.c
net/netlink/af_netlink.c
net/sctp/associola.c
net/sctp/bind_addr.c
net/sctp/input.c
net/sctp/outqueue.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/transport.c
net/vmw_vsock/af_vsock.c
scripts/Makefile.lib
scripts/dtc/checks.c
scripts/dtc/dtc-lexer.l
scripts/dtc/dtc-lexer.lex.c_shipped
scripts/dtc/dtc-parser.tab.c_shipped
scripts/dtc/dtc-parser.y
scripts/dtc/dtc.c
scripts/dtc/dtx_diff [new file with mode: 0755]
scripts/dtc/libfdt/fdt.c
scripts/dtc/libfdt/fdt_ro.c
scripts/dtc/libfdt/fdt_rw.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/util.c
scripts/dtc/version_gen.h
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/basic_asm.h [new file with mode: 0644]
tools/testing/selftests/powerpc/math/.gitignore [new file with mode: 0644]
tools/testing/selftests/powerpc/math/Makefile [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_asm.S [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_preempt.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_signal.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/fpu_syscall.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_asm.S [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_preempt.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_signal.c [new file with mode: 0644]
tools/testing/selftests/powerpc/math/vmx_syscall.c [new file with mode: 0644]
tools/testing/selftests/powerpc/tm/tm-signal-msr-resv.c

index b07e86d..7fd737e 100644 (file)
@@ -159,7 +159,7 @@ Description:    read only
                 Decimal value of the Per Process MMIO space length.
 Users:         https://github.com/ibm-capi/libcxl
 
-What:           /sys/class/cxl/<afu>m/pp_mmio_off
+What:           /sys/class/cxl/<afu>m/pp_mmio_off (not in a guest)
 Date:           September 2014
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read only
@@ -183,7 +183,7 @@ Description:    read only
                 Identifies the revision level of the PSL.
 Users:         https://github.com/ibm-capi/libcxl
 
-What:           /sys/class/cxl/<card>/base_image
+What:           /sys/class/cxl/<card>/base_image (not in a guest)
 Date:           September 2014
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read only
@@ -193,7 +193,7 @@ Description:    read only
                 during the initial program load.
 Users:         https://github.com/ibm-capi/libcxl
 
-What:           /sys/class/cxl/<card>/image_loaded
+What:           /sys/class/cxl/<card>/image_loaded (not in a guest)
 Date:           September 2014
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read only
@@ -201,7 +201,7 @@ Description:    read only
                 onto the card.
 Users:         https://github.com/ibm-capi/libcxl
 
-What:           /sys/class/cxl/<card>/load_image_on_perst
+What:           /sys/class/cxl/<card>/load_image_on_perst (not in a guest)
 Date:           December 2014
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    read/write
@@ -224,7 +224,7 @@ Description:    write only
                 to reload the FPGA depending on load_image_on_perst.
 Users:         https://github.com/ibm-capi/libcxl
 
-What:          /sys/class/cxl/<card>/perst_reloads_same_image
+What:          /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest)
 Date:          July 2015
 Contact:       linuxppc-dev@lists.ozlabs.org
 Description:   read/write
index 18dc52c..e8cf9cf 100644 (file)
@@ -100,3 +100,29 @@ allocated by dma_alloc_attrs() function from individual pages if it can
 be mapped as contiguous chunk into device dma address space. By
 specifying this attribute the allocated buffer is forced to be contiguous
 also in physical memory.
+
+DMA_ATTR_ALLOC_SINGLE_PAGES
+---------------------------
+
+This is a hint to the DMA-mapping subsystem that it's probably not worth
+the time to try to allocate memory to in a way that gives better TLB
+efficiency (AKA it's not worth trying to build the mapping out of larger
+pages).  You might want to specify this if:
+- You know that the accesses to this memory won't thrash the TLB.
+  You might know that the accesses are likely to be sequential or
+  that they aren't sequential but it's unlikely you'll ping-pong
+  between many addresses that are likely to be in different physical
+  pages.
+- You know that the penalty of TLB misses while accessing the
+  memory will be small enough to be inconsequential.  If you are
+  doing a heavy operation like decryption or decompression this
+  might be the case.
+- You know that the DMA mapping is fairly transitory.  If you expect
+  the mapping to have a short lifetime then it may be worth it to
+  optimize allocation (avoid coming up with large pages) instead of
+  getting the slight performance win of larger pages.
+Setting this hint doesn't guarantee that you won't get huge pages, but it
+means that we won't try quite as hard to get them.
+
+NOTE: At the moment DMA_ATTR_ALLOC_SINGLE_PAGES is only implemented on ARM,
+though ARM64 patches will likely be posted soon.
index 1a70997..100db73 100644 (file)
@@ -123,7 +123,9 @@ Required nodes:
 
 - syscon: some subnode of the RealView SoC node must be a
   system controller node pointing to the control registers,
-  with the compatible string set to one of these tuples:
+  with the compatible string set to one of these:
+   "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon"
+   "arm,realview-eb11mp-revc-syscon", "arm,realview-eb-syscon", "syscon"
    "arm,realview-eb-syscon", "syscon"
    "arm,realview-pb1176-syscon", "syscon"
    "arm,realview-pb11mp-syscon", "syscon"
index ae9be07..afcf50f 100644 (file)
@@ -250,7 +250,7 @@ nodes to be present and contain the properties described below.
                Usage: optional
                Value type: <prop-encoded-array>
                Definition: A u32 value that represents the running time dynamic
-                           power coefficient in units of mW/MHz/uVolt^2. The
+                           power coefficient in units of mW/MHz/uV^2. The
                            coefficient can either be calculated from power
                            measurements or derived by analysis.
 
index 33a1638..c6cfe2e 100644 (file)
@@ -29,6 +29,8 @@ Optional properties:
        ti,vref-delay-usecs             vref supply delay in usecs, 0 for
                                        external vref (u16).
        ti,vref-mv                      The VREF voltage, in millivolts (u16).
+                                       Set to 0 to use internal refernce
+                                       (ADS7846).
        ti,keep-vref-on                 set to keep vref on for differential
                                        measurements as well
        ti,swap-xy                      swap x and y axis
index 1fc5328..55c2c03 100644 (file)
@@ -315,6 +315,16 @@ PROPERTIES
                Value type: <phandle>
                Definition: A phandle for 1EEE1588 timer.
 
+- pcsphy-handle
+               Usage required for "fsl,fman-memac" MACs
+               Value type: <phandle>
+               Definition: A phandle for pcsphy.
+
+- tbi-handle
+               Usage required for "fsl,fman-dtsec" MACs
+               Value type: <phandle>
+               Definition: A phandle for tbiphy.
+
 EXAMPLE
 
 fman1_tx28: port@a8000 {
@@ -340,6 +350,7 @@ ethernet@e0000 {
        reg = <0xe0000 0x1000>;
        fsl,fman-ports = <&fman1_rx8 &fman1_tx28>;
        ptp-timer = <&ptp-timer>;
+       tbi-handle = <&tbi0>;
 };
 
 ============================================================================
@@ -415,6 +426,13 @@ PROPERTIES
                The settings and programming routines for internal/external
                MDIO are different. Must be included for internal MDIO.
 
+For internal PHY device on internal mdio bus, a PHY node should be created.
+See the definition of the PHY node in booting-without-of.txt for an
+example of how to define a PHY (Internal PHY has no interrupt line).
+- For "fsl,fman-mdio" compatible internal mdio bus, the PHY is TBI PHY.
+- For "fsl,fman-memac-mdio" compatible internal mdio bus, the PHY is PCS PHY,
+  PCS PHY addr must be '0'.
+
 EXAMPLE
 
 Example for FMan v2 external MDIO:
@@ -425,12 +443,29 @@ mdio@f1000 {
        interrupts = <101 2 0 0>;
 };
 
+Example for FMan v2 internal MDIO:
+
+mdio@e3120 {
+       compatible = "fsl,fman-mdio";
+       reg = <0xe3120 0xee0>;
+       fsl,fman-internal-mdio;
+
+       tbi1: tbi-phy@8 {
+               reg = <0x8>;
+               device_type = "tbi-phy";
+       };
+};
+
 Example for FMan v3 internal MDIO:
 
 mdio@f1000 {
        compatible = "fsl,fman-memac-mdio";
        reg = <0xf1000 0x1000>;
        fsl,fman-internal-mdio;
+
+       pcsphy6: ethernet-phy@0 {
+               reg = <0x0>;
+       };
 };
 
 =============================================================================
@@ -568,6 +603,7 @@ fman@400000 {
                cell-index = <0>;
                reg = <0xe0000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x8 &fman1_tx_0x28>;
+               tbi-handle = <&tbi5>;
        };
 
        ethernet@e2000 {
@@ -575,6 +611,7 @@ fman@400000 {
                cell-index = <1>;
                reg = <0xe2000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x9 &fman1_tx_0x29>;
+               tbi-handle = <&tbi6>;
        };
 
        ethernet@e4000 {
@@ -582,6 +619,7 @@ fman@400000 {
                cell-index = <2>;
                reg = <0xe4000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0xa &fman1_tx_0x2a>;
+               tbi-handle = <&tbi7>;
        };
 
        ethernet@e6000 {
@@ -589,6 +627,7 @@ fman@400000 {
                cell-index = <3>;
                reg = <0xe6000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0xb &fman1_tx_0x2b>;
+               tbi-handle = <&tbi8>;
        };
 
        ethernet@e8000 {
@@ -596,6 +635,7 @@ fman@400000 {
                cell-index = <4>;
                reg = <0xf0000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0xc &fman1_tx_0x2c>;
+               tbi-handle = <&tbi9>;
 
        ethernet@f0000 {
                cell-index = <8>;
diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt
new file mode 100644 (file)
index 0000000..12278d7
--- /dev/null
@@ -0,0 +1,39 @@
+Standard Unit Suffixes for Property names
+
+Properties which have a unit of measure are recommended to have a unit
+suffix appended to the property name. The list below contains the
+recommended suffixes. Other variations exist in bindings, but should not
+be used in new bindings or added here. The inconsistency in the unit
+prefixes is due to selecting the most commonly used variants.
+
+It is also recommended to use the units listed here and not add additional
+unit prefixes.
+
+Time/Frequency
+----------------------------------------
+-mhz           : megahertz
+-hz            : Hertz (preferred)
+-sec           : seconds
+-ms            : milliseconds
+-us            : microseconds
+-ns            : nanoseconds
+
+Distance
+----------------------------------------
+-mm            : millimeters
+
+Electricity
+----------------------------------------
+-microamp      : micro amps
+-ohms          : Ohms
+-micro-ohms    : micro Ohms
+-microvolt     : micro volts
+
+Temperature
+----------------------------------------
+-celsius       : Degrees Celsius
+-millicelsius  : Degreee milli-Celsius
+
+Pressure
+----------------------------------------
+-kpascal       : kiloPascal
diff --git a/Documentation/devicetree/bindings/soc/fsl/rcpm.txt b/Documentation/devicetree/bindings/soc/fsl/rcpm.txt
new file mode 100644 (file)
index 0000000..e284e4e
--- /dev/null
@@ -0,0 +1,63 @@
+* Run Control and Power Management
+-------------------------------------------
+The RCPM performs all device-level tasks associated with device run control
+and power management.
+
+Required properites:
+  - reg : Offset and length of the register set of the RCPM block.
+  - fsl,#rcpm-wakeup-cells : The number of IPPDEXPCR register cells in the
+       fsl,rcpm-wakeup property.
+  - compatible : Must contain a chip-specific RCPM block compatible string
+       and (if applicable) may contain a chassis-version RCPM compatible
+       string. Chip-specific strings are of the form "fsl,<chip>-rcpm",
+       such as:
+       * "fsl,p2041-rcpm"
+       * "fsl,p5020-rcpm"
+       * "fsl,t4240-rcpm"
+
+       Chassis-version strings are of the form "fsl,qoriq-rcpm-<version>",
+       such as:
+       * "fsl,qoriq-rcpm-1.0": for chassis 1.0 rcpm
+       * "fsl,qoriq-rcpm-2.0": for chassis 2.0 rcpm
+       * "fsl,qoriq-rcpm-2.1": for chassis 2.1 rcpm
+
+All references to "1.0" and "2.0" refer to the QorIQ chassis version to
+which the chip complies.
+Chassis Version                Example Chips
+---------------                -------------------------------
+1.0                            p4080, p5020, p5040, p2041, p3041
+2.0                            t4240, b4860, b4420
+2.1                            t1040, ls1021
+
+Example:
+The RCPM node for T4240:
+       rcpm: global-utilities@e2000 {
+               compatible = "fsl,t4240-rcpm", "fsl,qoriq-rcpm-2.0";
+               reg = <0xe2000 0x1000>;
+               fsl,#rcpm-wakeup-cells = <2>;
+       };
+
+* Freescale RCPM Wakeup Source Device Tree Bindings
+-------------------------------------------
+Required fsl,rcpm-wakeup property should be added to a device node if the device
+can be used as a wakeup source.
+
+  - fsl,rcpm-wakeup: Consists of a phandle to the rcpm node and the IPPDEXPCR
+       register cells. The number of IPPDEXPCR register cells is defined in
+       "fsl,#rcpm-wakeup-cells" in the rcpm node. The first register cell is
+       the bit mask that should be set in IPPDEXPCR0, and the second register
+       cell is for IPPDEXPCR1, and so on.
+
+       Note: IPPDEXPCR(IP Powerdown Exception Control Register) provides a
+       mechanism for keeping certain blocks awake during STANDBY and MEM, in
+       order to use them as wake-up sources.
+
+Example:
+       lpuart0: serial@2950000 {
+               compatible = "fsl,ls1021a-lpuart";
+               reg = <0x0 0x2950000 0x0 0x1000>;
+               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&sysclk>;
+               clock-names = "ipg";
+               fsl,rcpm-wakeup = <&rcpm 0x0 0x40000000>;
+       };
index 156731c..787d422 100644 (file)
@@ -72,6 +72,7 @@ dmo   Data Modul AG
 ea     Embedded Artists AB
 ebv    EBV Elektronik
 edt    Emerging Display Technologies
+eeti   eGalax_eMPIA Technology Inc
 elan   Elan Microelectronic Corp.
 emmicro        EM Microelectronic
 energymicro    Silicon Laboratories (formerly Energy Micro AS)
@@ -247,6 +248,7 @@ tplink      TP-LINK Technologies Co., Ltd.
 tronfy Tronfy
 truly  Truly Semiconductors Limited
 upisemi        uPI Semiconductor Corp.
+urt    United Radiant Technology Corporation
 usi    Universal Scientific Industrial Co., Ltd.
 v3     V3 Semiconductor
 variscite      Variscite Ltd.
index 04d34f6..3f1437f 100644 (file)
@@ -16,6 +16,7 @@ Table of Contents
     2) Entry point for arch/powerpc
     3) Entry point for arch/x86
     4) Entry point for arch/mips/bmips
+    5) Entry point for arch/sh
 
   II - The DT block format
     1) Header
@@ -316,6 +317,18 @@ it with special cases.
   This convention is defined for 32-bit systems only, as there are not
   currently any 64-bit BMIPS implementations.
 
+5) Entry point for arch/sh
+--------------------------
+
+  Device-tree-compatible SH bootloaders are expected to provide the physical
+  address of the device tree blob in r4. Since legacy bootloaders did not
+  guarantee any particular initial register state, kernels built to
+  inter-operate with old bootloaders must either use a builtin DTB or
+  select a legacy board option (something other than CONFIG_SH_DEVICE_TREE)
+  that does not use device tree. Support for the latter is being phased out
+  in favor of device tree.
+
+
 II - The DT block format
 ========================
 
index 92d86f7..453053f 100644 (file)
@@ -340,8 +340,10 @@ comparison:
 
   int (*match)(struct device * dev, struct device_driver * drv);
 
-match should return '1' if the driver supports the device, and '0'
-otherwise. 
+match should return positive value if the driver supports the device,
+and zero otherwise. It may also return error code (for example
+-EPROBE_DEFER) if determining that given driver supports the device is
+not possible.
 
 When a device is registered, the bus's list of drivers is iterated
 over. bus->match() is called for each one until a match is found. 
index eef242e..1f780d9 100644 (file)
@@ -2620,7 +2620,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        nolapic_timer   [X86-32,APIC] Do not use the local APIC timer.
 
        noltlbs         [PPC] Do not use large page/tlb entries for kernel
-                       lowmem mapping on PPC40x.
+                       lowmem mapping on PPC40x and PPC8xx
 
        nomca           [IA-64] Disable machine check abort handling
 
index d5df40c..b183e2b 100644 (file)
@@ -946,15 +946,20 @@ igmp_max_memberships - INTEGER
        The value 5459 assumes no IP header options, so in practice
        this number may be lower.
 
-       conf/interface/*  changes special settings per interface (where
-       "interface" is the name of your network interface)
-
-       conf/all/*        is special, changes the settings for all interfaces
+igmp_max_msf - INTEGER
+       Maximum number of addresses allowed in the source filter list for a
+       multicast group.
+       Default: 10
 
 igmp_qrv - INTEGER
-        Controls the IGMP query robustness variable (see RFC2236 8.1).
-        Default: 2 (as specified by RFC2236 8.1)
-        Minimum: 1 (as specified by RFC6636 4.5)
+       Controls the IGMP query robustness variable (see RFC2236 8.1).
+       Default: 2 (as specified by RFC2236 8.1)
+       Minimum: 1 (as specified by RFC6636 4.5)
+
+conf/interface/*  changes special settings per interface (where
+"interface" is the name of your network interface)
+
+conf/all/*       is special, changes the settings for all interfaces
 
 log_martians - BOOLEAN
        Log packets with impossible addresses to kernel log.
index 205c1b8..d5506ba 100644 (file)
@@ -116,6 +116,8 @@ Work Element Descriptor (WED)
 User API
 ========
 
+1. AFU character devices
+
     For AFUs operating in AFU directed mode, two character device
     files will be created. /dev/cxl/afu0.0m will correspond to a
     master context and /dev/cxl/afu0.0s will correspond to a slave
@@ -362,6 +364,59 @@ read
         reserved fields:
             For future extensions and padding
 
+
+2. Card character device (powerVM guest only)
+
+    In a powerVM guest, an extra character device is created for the
+    card. The device is only used to write (flash) a new image on the
+    FPGA accelerator. Once the image is written and verified, the
+    device tree is updated and the card is reset to reload the updated
+    image.
+
+open
+----
+
+    Opens the device and allocates a file descriptor to be used with
+    the rest of the API. The device can only be opened once.
+
+ioctl
+-----
+
+CXL_IOCTL_DOWNLOAD_IMAGE:
+CXL_IOCTL_VALIDATE_IMAGE:
+    Starts and controls flashing a new FPGA image. Partial
+    reconfiguration is not supported (yet), so the image must contain
+    a copy of the PSL and AFU(s). Since an image can be quite large,
+    the caller may have to iterate, splitting the image in smaller
+    chunks.
+
+    Takes a pointer to a struct cxl_adapter_image:
+        struct cxl_adapter_image {
+            __u64 flags;
+            __u64 data;
+            __u64 len_data;
+            __u64 len_image;
+            __u64 reserved1;
+            __u64 reserved2;
+            __u64 reserved3;
+            __u64 reserved4;
+        };
+
+    flags:
+        These flags indicate which optional fields are present in
+        this struct. Currently all fields are mandatory.
+
+    data:
+        Pointer to a buffer with part of the image to write to the
+        card.
+
+    len_data:
+        Size of the buffer pointed to by data.
+
+    len_image:
+        Full size of the image.
+
+
 Sysfs Class
 ===========
 
index 74acd99..0cbfc69 100644 (file)
@@ -4250,13 +4250,6 @@ M:       Maxim Levitsky <maximlevitsky@gmail.com>
 S:     Maintained
 F:     drivers/media/rc/ene_ir.*
 
-ENHANCED ERROR HANDLING (EEH)
-M:     Gavin Shan <shangw@linux.vnet.ibm.com>
-L:     linuxppc-dev@lists.ozlabs.org
-S:     Supported
-F:     Documentation/powerpc/eeh-pci-error-recovery.txt
-F:     arch/powerpc/kernel/eeh*.c
-
 EPSON S1D13XXX FRAMEBUFFER DRIVER
 M:     Kristoffer Ericson <kristoffer.ericson@gmail.com>
 S:     Maintained
@@ -8315,6 +8308,15 @@ L:       linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/PCI/pci-error-recovery.txt
 
+PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC
+M:     Russell Currey <ruscur@russell.cc>
+L:     linuxppc-dev@lists.ozlabs.org
+S:     Supported
+F:     Documentation/powerpc/eeh-pci-error-recovery.txt
+F:     arch/powerpc/kernel/eeh*.c
+F:     arch/powerpc/platforms/*/eeh*.c
+F:     arch/powerpc/include/*/eeh*.h
+
 PCI SUBSYSTEM
 M:     Bjorn Helgaas <bhelgaas@google.com>
 L:     linux-pci@vger.kernel.org
index 1d00da1..f6c185f 100644 (file)
@@ -572,7 +572,6 @@ config ARCH_RPC
        select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        select NO_IOPORT_MAP
-       select VIRT_TO_BUS
        help
          On the Acorn Risc-PC, Linux can support the internal IDE disk and
          CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -1336,7 +1335,6 @@ config BIG_LITTLE
 config BL_SWITCHER
        bool "big.LITTLE switcher support"
        depends on BIG_LITTLE && MCPM && HOTPLUG_CPU && ARM_GIC
-       select ARM_CPU_SUSPEND
        select CPU_PM
        help
          The big.LITTLE "switcher" provides the core functionality to
@@ -2110,7 +2108,8 @@ config ARCH_SUSPEND_POSSIBLE
        def_bool y
 
 config ARM_CPU_SUSPEND
-       def_bool PM_SLEEP
+       def_bool PM_SLEEP || BL_SWITCHER || ARM_PSCI_FW
+       depends on ARCH_SUSPEND_POSSIBLE
 
 config ARCH_HIBERNATION_POSSIBLE
        bool
index fe25410..46fb1ca 100644 (file)
@@ -352,7 +352,6 @@ archclean:
 
 # My testing targets (bypasses dependencies)
 bp:;   $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage
-i zi:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
 
 define archhelp
index 9eca7ae..48fab15 100644 (file)
@@ -88,7 +88,7 @@ $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
        @$(kecho) '  Kernel: $@ is ready'
 
-PHONY += initrd FORCE
+PHONY += initrd
 initrd:
        @test "$(INITRD_PHYS)" != "" || \
        (echo This machine does not support INITRD; exit -1)
@@ -107,12 +107,4 @@ uinstall:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
        $(obj)/uImage System.map "$(INSTALL_PATH)"
 
-zi:
-       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
-       $(obj)/zImage System.map "$(INSTALL_PATH)"
-
-i:
-       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
-       $(obj)/Image System.map "$(INSTALL_PATH)"
-
 subdir-            := bootp compressed dts
index 0714e03..86b2f5d 100644 (file)
@@ -3,11 +3,7 @@ bswapsdi2.S
 font.c
 lib1funcs.S
 hyp-stub.S
-piggy.gzip
-piggy.lzo
-piggy.lzma
-piggy.xzkern
-piggy.lz4
+piggy_data
 vmlinux
 vmlinux.lds
 
index 43788b1..d50430c 100644 (file)
@@ -66,11 +66,11 @@ endif
 
 CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
 
-suffix_$(CONFIG_KERNEL_GZIP) = gzip
-suffix_$(CONFIG_KERNEL_LZO)  = lzo
-suffix_$(CONFIG_KERNEL_LZMA) = lzma
-suffix_$(CONFIG_KERNEL_XZ)   = xzkern
-suffix_$(CONFIG_KERNEL_LZ4)  = lz4
+compress-$(CONFIG_KERNEL_GZIP) = gzip
+compress-$(CONFIG_KERNEL_LZO)  = lzo
+compress-$(CONFIG_KERNEL_LZMA) = lzma
+compress-$(CONFIG_KERNEL_XZ)   = xzkern
+compress-$(CONFIG_KERNEL_LZ4)  = lz4
 
 # Borrowed libfdt files for the ATAG compatibility mode
 
@@ -89,15 +89,12 @@ ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
 OBJS   += $(libfdt_objs) atags_to_fdt.o
 endif
 
-targets       := vmlinux vmlinux.lds \
-                piggy.$(suffix_y) piggy.$(suffix_y).o \
-                lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S bswapsdi2.o \
-                bswapsdi2.S font.o font.c head.o misc.o $(OBJS)
+targets       := vmlinux vmlinux.lds piggy_data piggy.o \
+                lib1funcs.o ashldi3.o bswapsdi2.o \
+                head.o $(OBJS)
 
-# Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern piggy.lz4 \
-                lib1funcs.S ashldi3.S bswapsdi2.S $(libfdt) $(libfdt_hdrs) \
-                hyp-stub.S
+clean-files += piggy_data lib1funcs.S ashldi3.S bswapsdi2.S \
+               $(libfdt) $(libfdt_hdrs) hyp-stub.S
 
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 
@@ -178,17 +175,17 @@ fi
 
 efi-obj-$(CONFIG_EFI_STUB) := $(objtree)/drivers/firmware/efi/libstub/lib.a
 
-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \
                $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) \
                $(bswapsdi2) $(efi-obj-y) FORCE
        @$(check_for_multiple_zreladdr)
        $(call if_changed,ld)
        @$(check_for_bad_syms)
 
-$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
-       $(call if_changed,$(suffix_y))
+$(obj)/piggy_data: $(obj)/../Image FORCE
+       $(call if_changed,$(compress-y))
 
-$(obj)/piggy.$(suffix_y).o:  $(obj)/piggy.$(suffix_y) FORCE
+$(obj)/piggy.o: $(obj)/piggy_data
 
 CFLAGS_font.o := -Dstatic=
 
diff --git a/arch/arm/boot/compressed/piggy.S b/arch/arm/boot/compressed/piggy.S
new file mode 100644 (file)
index 0000000..f720884
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy_data"
+       .globl  input_data_end
+input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.gzip.S b/arch/arm/boot/compressed/piggy.gzip.S
deleted file mode 100644 (file)
index a68adf9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.gzip"
-       .globl  input_data_end
-input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.lz4.S b/arch/arm/boot/compressed/piggy.lz4.S
deleted file mode 100644 (file)
index 3d9a575..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.lz4"
-       .globl  input_data_end
-input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.lzma.S b/arch/arm/boot/compressed/piggy.lzma.S
deleted file mode 100644 (file)
index d7e69cf..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.lzma"
-       .globl  input_data_end
-input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.lzo.S b/arch/arm/boot/compressed/piggy.lzo.S
deleted file mode 100644 (file)
index a425ad9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.lzo"
-       .globl  input_data_end
-input_data_end:
diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S
deleted file mode 100644 (file)
index 5703f30..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-       .section .piggydata,#alloc
-       .globl  input_data
-input_data:
-       .incbin "arch/arm/boot/compressed/piggy.xzkern"
-       .globl  input_data_end
-input_data_end:
index 36e53ef..6894674 100644 (file)
@@ -65,6 +65,15 @@ size_t strlen(const char *s)
        return sc - s;
 }
 
+size_t strnlen(const char *s, size_t count)
+{
+       const char *sc;
+
+       for (sc = s; count-- && *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+
 int memcmp(const void *cs, const void *ct, size_t count)
 {
        const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
index 3d22494..fb0a0a4 100644 (file)
@@ -1290,7 +1290,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
        struct sa1111_dev *dev = SA1111_DEV(_dev);
        struct sa1111_driver *drv = SA1111_DRV(_drv);
 
-       return dev->devid & drv->devid;
+       return !!(dev->devid & drv->devid);
 }
 
 static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
index 16da638..3f6616b 100644 (file)
@@ -23,7 +23,6 @@ generic-y += preempt.h
 generic-y += resource.h
 generic-y += rwsem.h
 generic-y += seccomp.h
-generic-y += sections.h
 generic-y += segment.h
 generic-y += sembuf.h
 generic-y += serial.h
index e1f0776..7d919a9 100644 (file)
@@ -74,7 +74,7 @@ static inline uint32_t __div64_32(uint64_t *n, uint32_t base)
 static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
 {
        unsigned long long res;
-       unsigned int tmp = 0;
+       register unsigned int tmp asm("ip") = 0;
 
        if (!bias) {
                asm (   "umull  %Q0, %R0, %Q1, %Q2\n\t"
@@ -90,12 +90,12 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
                        : "r" (m), "r" (n)
                        : "cc");
        } else {
-               asm (   "umull  %Q0, %R0, %Q1, %Q2\n\t"
-                       "cmn    %Q0, %Q1\n\t"
-                       "adcs   %R0, %R0, %R1\n\t"
-                       "adc    %Q0, %3, #0"
-                       : "=&r" (res)
-                       : "r" (m), "r" (n), "r" (tmp)
+               asm (   "umull  %Q0, %R0, %Q2, %Q3\n\t"
+                       "cmn    %Q0, %Q2\n\t"
+                       "adcs   %R0, %R0, %R2\n\t"
+                       "adc    %Q0, %1, #0"
+                       : "=&r" (res), "+&r" (tmp)
+                       : "r" (m), "r" (n)
                        : "cc");
        }
 
index c79b57b..9427fd6 100644 (file)
  */
 #define PLAT_PHYS_OFFSET       UL(CONFIG_PHYS_OFFSET)
 
+#ifdef CONFIG_XIP_KERNEL
+/*
+ * When referencing data in RAM from the XIP region in a relative manner
+ * with the MMU off, we need the relative offset between the two physical
+ * addresses.  The macro below achieves this, which is:
+ *    __pa(v_data) - __xip_pa(v_text)
+ */
+#define PHYS_RELATIVE(v_data, v_text) \
+       (((v_data) - PAGE_OFFSET + PLAT_PHYS_OFFSET) - \
+        ((v_text) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + \
+          CONFIG_XIP_PHYS_ADDR))
+#else
+#define PHYS_RELATIVE(v_data, v_text) ((v_data) - (v_text))
+#endif
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -273,14 +288,14 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define __va(x)                        ((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)      __va((phys_addr_t)(pfn) << PAGE_SHIFT)
 
-extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
+extern unsigned long (*arch_virt_to_idmap)(unsigned long x);
 
 /*
  * These are for systems that have a hardware interconnect supported alias of
  * physical memory for idmap purposes.  Most cases should leave these
- * untouched.
+ * untouched.  Note: this can only return addresses less than 4GiB.
  */
-static inline phys_addr_t __virt_to_idmap(unsigned long x)
+static inline unsigned long __virt_to_idmap(unsigned long x)
 {
        if (IS_ENABLED(CONFIG_MMU) && arch_virt_to_idmap)
                return arch_virt_to_idmap(x);
@@ -303,20 +318,6 @@ static inline phys_addr_t __virt_to_idmap(unsigned long x)
 #define __bus_to_pfn(x)        __phys_to_pfn(x)
 #endif
 
-#ifdef CONFIG_VIRT_TO_BUS
-#define virt_to_bus virt_to_bus
-static inline __deprecated unsigned long virt_to_bus(void *x)
-{
-       return __virt_to_bus((unsigned long)x);
-}
-
-#define bus_to_virt bus_to_virt
-static inline __deprecated void *bus_to_virt(unsigned long x)
-{
-       return (void *)__bus_to_virt(x);
-}
-#endif
-
 /*
  * Conversion between a struct page and a physical address.
  *
index 432ce81..fa5b42d 100644 (file)
@@ -26,7 +26,12 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 #ifdef CONFIG_CPU_HAS_ASID
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
-#define init_new_context(tsk,mm)       ({ atomic64_set(&(mm)->context.id, 0); 0; })
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       atomic64_set(&mm->context.id, 0);
+       return 0;
+}
 
 #ifdef CONFIG_ARM_ERRATA_798181
 void a15_erratum_get_cpumask(int this_cpu, struct mm_struct *mm,
@@ -85,7 +90,12 @@ static inline void finish_arch_post_lock_switch(void)
 
 #endif /* CONFIG_MMU */
 
-#define init_new_context(tsk,mm)       0
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       return 0;
+}
+
 
 #endif /* CONFIG_CPU_HAS_ASID */
 
diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h
new file mode 100644 (file)
index 0000000..803bbf2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _ASM_ARM_SECTIONS_H
+#define _ASM_ARM_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+extern char _exiprom[];
+
+#endif /* _ASM_ARM_SECTIONS_H */
index 0009861..73e5e85 100644 (file)
  * Eg, if you have 2 banks of up to 64MB at 0x80000000, 0x84000000,
  * then MAX_PHYSMEM_BITS is 32, SECTION_SIZE_BITS is 26.
  *
- * Define these in your mach/memory.h.
+ * These can be overridden in your mach/memory.h.
  */
-#if !defined(SECTION_SIZE_BITS) || !defined(MAX_PHYSMEM_BITS)
-#error Sparsemem is not supported on this platform
+#if !defined(MAX_PHYSMEM_BITS) || !defined(SECTION_SIZE_BITS)
+#define MAX_PHYSMEM_BITS       36
+#define SECTION_SIZE_BITS      28
 #endif
 
 #endif
index 3ce377f..e255050 100644 (file)
@@ -1064,7 +1064,6 @@ ENDPROC(vector_\name)
        .endm
 
        .section .stubs, "ax", %progbits
-__stubs_start:
        @ This must be the first word
        .word   vector_swi
 
@@ -1202,14 +1201,13 @@ vector_addrexcptn:
        .long   __fiq_svc                       @  e
        .long   __fiq_svc                       @  f
 
-       .globl  vector_fiq_offset
-       .equ    vector_fiq_offset, vector_fiq
+       .globl  vector_fiq
 
        .section .vectors, "ax", %progbits
-__vectors_start:
+.L__vectors_start:
        W(b)    vector_rst
        W(b)    vector_und
-       W(ldr)  pc, __vectors_start + 0x1000
+       W(ldr)  pc, .L__vectors_start + 0x1000
        W(b)    vector_pabt
        W(b)    vector_dabt
        W(b)    vector_addrexcptn
index a71501f..b09561a 100644 (file)
@@ -62,7 +62,7 @@ static int notrace arch_save_image(unsigned long unused)
 
        ret = swsusp_save();
        if (ret == 0)
-               _soft_restart(virt_to_phys(cpu_resume), false);
+               _soft_restart(virt_to_idmap(cpu_resume), false);
        return ret;
 }
 
@@ -87,7 +87,7 @@ static void notrace arch_restore_image(void *unused)
        for (pbe = restore_pblist; pbe; pbe = pbe->next)
                copy_page(pbe->orig_address, pbe->address);
 
-       _soft_restart(virt_to_phys(cpu_resume), false);
+       _soft_restart(virt_to_idmap(cpu_resume), false);
 }
 
 static u64 resume_stack[PAGE_SIZE/2/sizeof(u64)] __nosavedata;
index 2a55373..0b1e4a9 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/irqchip/arm-gic-v3.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/virt.h>
@@ -159,6 +160,29 @@ ARM_BE8(orr        r7, r7, #(1 << 25))     @ HSCTLR.EE
        bic     r7, #1                  @ Clear ENABLE
        mcr     p15, 0, r7, c14, c3, 1  @ CNTV_CTL
 1:
+#endif
+
+#ifdef CONFIG_ARM_GIC_V3
+       @ Check whether GICv3 system registers are available
+       mrc     p15, 0, r7, c0, c1, 1   @ ID_PFR1
+       ubfx    r7, r7, #28, #4
+       cmp     r7, #1
+       bne     2f
+
+       @ Enable system register accesses
+       mrc     p15, 4, r7, c12, c9, 5  @ ICC_HSRE
+       orr     r7, r7, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
+       mcr     p15, 4, r7, c12, c9, 5  @ ICC_HSRE
+       isb
+
+       @ SRE bit could be forced to 0 by firmware.
+       @ Check whether it sticks before accessing any other sysreg
+       mrc     p15, 4, r7, c12, c9, 5  @ ICC_HSRE
+       tst     r7, #ICC_SRE_EL2_SRE
+       beq     2f
+       mov     r7, #0
+       mcr     p15, 4, r7, c12, c11, 0 @ ICH_HCR
+2:
 #endif
 
        bx      lr                      @ The boot CPU mode is left in r4.
index 1d45320..ece04a4 100644 (file)
@@ -95,7 +95,7 @@ void __init init_IRQ(void)
                        outer_cache.write_sec = machine_desc->l2c_write_sec;
                ret = l2x0_of_init(machine_desc->l2c_aux_val,
                                   machine_desc->l2c_aux_mask);
-               if (ret)
+               if (ret && ret != -ENODEV)
                        pr_err("L2C: failed to init: %d\n", ret);
        }
 
index 8bf3b7c..59fd0e2 100644 (file)
@@ -143,10 +143,8 @@ void (*kexec_reinit)(void);
 
 void machine_kexec(struct kimage *image)
 {
-       unsigned long page_list;
-       unsigned long reboot_code_buffer_phys;
-       unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
-       unsigned long reboot_entry_phys;
+       unsigned long page_list, reboot_entry_phys;
+       void (*reboot_entry)(void);
        void *reboot_code_buffer;
 
        /*
@@ -159,9 +157,6 @@ void machine_kexec(struct kimage *image)
 
        page_list = image->head & PAGE_MASK;
 
-       /* we need both effective and real address here */
-       reboot_code_buffer_phys =
-           page_to_pfn(image->control_code_page) << PAGE_SHIFT;
        reboot_code_buffer = page_address(image->control_code_page);
 
        /* Prepare parameters for reboot_code_buffer*/
@@ -174,10 +169,11 @@ void machine_kexec(struct kimage *image)
 
        /* copy our kernel relocation code to the control code page */
        reboot_entry = fncpy(reboot_code_buffer,
-                            reboot_entry,
+                            &relocate_new_kernel,
                             relocate_new_kernel_size);
-       reboot_entry_phys = (unsigned long)reboot_entry +
-               (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
+
+       /* get the identity mapping physical address for the reboot code */
+       reboot_entry_phys = virt_to_idmap(reboot_entry);
 
        pr_info("Bye!\n");
 
index efdddcb..4f14b5c 100644 (file)
@@ -34,7 +34,7 @@
  * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
  */
 #undef MODULES_VADDR
-#define MODULES_VADDR  (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK)
+#define MODULES_VADDR  (((unsigned long)_exiprom + ~PMD_MASK) & PMD_MASK)
 #endif
 
 #ifdef CONFIG_MMU
index 3826935..71a2ff9 100644 (file)
@@ -50,7 +50,7 @@ static void __soft_restart(void *addr)
        flush_cache_all();
 
        /* Switch to the identity mapping. */
-       phys_reset = (phys_reset_t)(unsigned long)virt_to_idmap(cpu_reset);
+       phys_reset = (phys_reset_t)virt_to_idmap(cpu_reset);
        phys_reset((unsigned long)addr);
 
        /* Should never get here. */
index 08b7847..ec279d1 100644 (file)
@@ -40,7 +40,7 @@
  * to run the rebalance_domains for all idle cores and the cpu_capacity can be
  * updated during this sequence.
  */
-static DEFINE_PER_CPU(unsigned long, cpu_scale);
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
 
 unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
@@ -306,8 +306,6 @@ void __init init_cpu_topology(void)
                cpu_topo->socket_id = -1;
                cpumask_clear(&cpu_topo->core_sibling);
                cpumask_clear(&cpu_topo->thread_sibling);
-
-               set_capacity_scale(cpu, SCHED_CAPACITY_SCALE);
        }
        smp_wmb();
 
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
new file mode 100644 (file)
index 0000000..cba1ec8
--- /dev/null
@@ -0,0 +1,316 @@
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version by Russell King
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+#define PROC_INFO                                                      \
+       . = ALIGN(4);                                                   \
+       VMLINUX_SYMBOL(__proc_info_begin) = .;                          \
+       *(.proc.info.init)                                              \
+       VMLINUX_SYMBOL(__proc_info_end) = .;
+
+#define IDMAP_TEXT                                                     \
+       ALIGN_FUNCTION();                                               \
+       VMLINUX_SYMBOL(__idmap_text_start) = .;                         \
+       *(.idmap.text)                                                  \
+       VMLINUX_SYMBOL(__idmap_text_end) = .;                           \
+       . = ALIGN(PAGE_SIZE);                                           \
+       VMLINUX_SYMBOL(__hyp_idmap_text_start) = .;                     \
+       *(.hyp.idmap.text)                                              \
+       VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define ARM_CPU_DISCARD(x)
+#define ARM_CPU_KEEP(x)                x
+#else
+#define ARM_CPU_DISCARD(x)     x
+#define ARM_CPU_KEEP(x)
+#endif
+
+#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
+       defined(CONFIG_GENERIC_BUG)
+#define ARM_EXIT_KEEP(x)       x
+#define ARM_EXIT_DISCARD(x)
+#else
+#define ARM_EXIT_KEEP(x)
+#define ARM_EXIT_DISCARD(x)    x
+#endif
+
+OUTPUT_ARCH(arm)
+ENTRY(stext)
+
+#ifndef __ARMEB__
+jiffies = jiffies_64;
+#else
+jiffies = jiffies_64 + 4;
+#endif
+
+SECTIONS
+{
+       /*
+        * XXX: The linker does not define how output sections are
+        * assigned to input sections when there are multiple statements
+        * matching the same input section name.  There is no documented
+        * order of matching.
+        *
+        * unwind exit sections must be discarded before the rest of the
+        * unwind sections get included.
+        */
+       /DISCARD/ : {
+               *(.ARM.exidx.exit.text)
+               *(.ARM.extab.exit.text)
+               ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+               ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
+               ARM_EXIT_DISCARD(EXIT_TEXT)
+               ARM_EXIT_DISCARD(EXIT_DATA)
+               EXIT_CALL
+#ifndef CONFIG_MMU
+               *(.text.fixup)
+               *(__ex_table)
+#endif
+#ifndef CONFIG_SMP_ON_UP
+               *(.alt.smp.init)
+#endif
+               *(.discard)
+               *(.discard.*)
+       }
+
+       . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
+       _xiprom = .;                    /* XIP ROM area to be mapped */
+
+       .head.text : {
+               _text = .;
+               HEAD_TEXT
+       }
+
+       .text : {                       /* Real text segment            */
+               _stext = .;             /* Text and read-only data      */
+                       IDMAP_TEXT
+                       __exception_text_start = .;
+                       *(.exception.text)
+                       __exception_text_end = .;
+                       IRQENTRY_TEXT
+                       TEXT_TEXT
+                       SCHED_TEXT
+                       LOCK_TEXT
+                       KPROBES_TEXT
+                       *(.gnu.warning)
+                       *(.glue_7)
+                       *(.glue_7t)
+               . = ALIGN(4);
+               *(.got)                 /* Global offset table          */
+                       ARM_CPU_KEEP(PROC_INFO)
+       }
+
+       RO_DATA(PAGE_SIZE)
+
+       . = ALIGN(4);
+       __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
+               __start___ex_table = .;
+#ifdef CONFIG_MMU
+               *(__ex_table)
+#endif
+               __stop___ex_table = .;
+       }
+
+#ifdef CONFIG_ARM_UNWIND
+       /*
+        * Stack unwinding tables
+        */
+       . = ALIGN(8);
+       .ARM.unwind_idx : {
+               __start_unwind_idx = .;
+               *(.ARM.exidx*)
+               __stop_unwind_idx = .;
+       }
+       .ARM.unwind_tab : {
+               __start_unwind_tab = .;
+               *(.ARM.extab*)
+               __stop_unwind_tab = .;
+       }
+#endif
+
+       NOTES
+
+       _etext = .;                     /* End of text and rodata section */
+
+       /*
+        * The vectors and stubs are relocatable code, and the
+        * only thing that matters is their relative offsets
+        */
+       __vectors_start = .;
+       .vectors 0xffff0000 : AT(__vectors_start) {
+               *(.vectors)
+       }
+       . = __vectors_start + SIZEOF(.vectors);
+       __vectors_end = .;
+
+       __stubs_start = .;
+       .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
+               *(.stubs)
+       }
+       . = __stubs_start + SIZEOF(.stubs);
+       __stubs_end = .;
+
+       PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors));
+
+       INIT_TEXT_SECTION(8)
+       .exit.text : {
+               ARM_EXIT_KEEP(EXIT_TEXT)
+       }
+       .init.proc.info : {
+               ARM_CPU_DISCARD(PROC_INFO)
+       }
+       .init.arch.info : {
+               __arch_info_begin = .;
+               *(.arch.info.init)
+               __arch_info_end = .;
+       }
+       .init.tagtable : {
+               __tagtable_begin = .;
+               *(.taglist.init)
+               __tagtable_end = .;
+       }
+#ifdef CONFIG_SMP_ON_UP
+       .init.smpalt : {
+               __smpalt_begin = .;
+               *(.alt.smp.init)
+               __smpalt_end = .;
+       }
+#endif
+       .init.pv_table : {
+               __pv_table_begin = .;
+               *(.pv_table)
+               __pv_table_end = .;
+       }
+       .init.data : {
+               INIT_SETUP(16)
+               INIT_CALLS
+               CON_INITCALL
+               SECURITY_INITCALL
+               INIT_RAM_FS
+       }
+
+#ifdef CONFIG_SMP
+       PERCPU_SECTION(L1_CACHE_BYTES)
+#endif
+
+       _exiprom = .;                   /* End of XIP ROM area */
+       __data_loc = ALIGN(4);          /* location in binary */
+       . = PAGE_OFFSET + TEXT_OFFSET;
+
+       .data : AT(__data_loc) {
+               _data = .;              /* address in memory */
+               _sdata = .;
+
+               /*
+                * first, the init task union, aligned
+                * to an 8192 byte boundary.
+                */
+               INIT_TASK_DATA(THREAD_SIZE)
+
+               . = ALIGN(PAGE_SIZE);
+               __init_begin = .;
+               INIT_DATA
+               ARM_EXIT_KEEP(EXIT_DATA)
+               . = ALIGN(PAGE_SIZE);
+               __init_end = .;
+
+               NOSAVE_DATA
+               CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+               READ_MOSTLY_DATA(L1_CACHE_BYTES)
+
+               /*
+                * and the usual data section
+                */
+               DATA_DATA
+               CONSTRUCTORS
+
+               _edata = .;
+       }
+       _edata_loc = __data_loc + SIZEOF(.data);
+
+#ifdef CONFIG_HAVE_TCM
+        /*
+        * We align everything to a page boundary so we can
+        * free it after init has commenced and TCM contents have
+        * been copied to its destination.
+        */
+       .tcm_start : {
+               . = ALIGN(PAGE_SIZE);
+               __tcm_start = .;
+               __itcm_start = .;
+       }
+
+       /*
+        * Link these to the ITCM RAM
+        * Put VMA to the TCM address and LMA to the common RAM
+        * and we'll upload the contents from RAM to TCM and free
+        * the used RAM after that.
+        */
+       .text_itcm ITCM_OFFSET : AT(__itcm_start)
+       {
+               __sitcm_text = .;
+               *(.tcm.text)
+               *(.tcm.rodata)
+               . = ALIGN(4);
+               __eitcm_text = .;
+       }
+
+       /*
+        * Reset the dot pointer, this is needed to create the
+        * relative __dtcm_start below (to be used as extern in code).
+        */
+       . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm);
+
+       .dtcm_start : {
+               __dtcm_start = .;
+       }
+
+       /* TODO: add remainder of ITCM as well, that can be used for data! */
+       .data_dtcm DTCM_OFFSET : AT(__dtcm_start)
+       {
+               . = ALIGN(4);
+               __sdtcm_data = .;
+               *(.tcm.data)
+               . = ALIGN(4);
+               __edtcm_data = .;
+       }
+
+       /* Reset the dot pointer or the linker gets confused */
+       . = ADDR(.dtcm_start) + SIZEOF(.data_dtcm);
+
+       /* End marker for freeing TCM copy in linked object */
+       .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){
+               . = ALIGN(PAGE_SIZE);
+               __tcm_end = .;
+       }
+#endif
+
+       BSS_SECTION(0, 0, 0)
+       _end = .;
+
+       STABS_DEBUG
+}
+
+/*
+ * These must never be empty
+ * If you have to comment these two assert statements out, your
+ * binutils is too old (for other reasons as well)
+ */
+ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
+ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
+
+/*
+ * The HYP init code can't be more than a page long,
+ * and should not cross a page boundary.
+ * The above comment applies as well.
+ */
+ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
+       "HYP init code too big or misaligned")
index b4139cb..1fab979 100644 (file)
@@ -3,14 +3,16 @@
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
+#ifdef CONFIG_XIP_KERNEL
+#include "vmlinux-xip.lds.S"
+#else
+
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/page.h>
-#ifdef CONFIG_ARM_KERNMEM_PERMS
 #include <asm/pgtable.h>
-#endif
 
 #define PROC_INFO                                                      \
        . = ALIGN(4);                                                   \
@@ -89,17 +91,13 @@ SECTIONS
                *(.discard.*)
        }
 
-#ifdef CONFIG_XIP_KERNEL
-       . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
-#else
        . = PAGE_OFFSET + TEXT_OFFSET;
-#endif
        .head.text : {
                _text = .;
                HEAD_TEXT
        }
 
-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
 #endif
 
@@ -123,7 +121,7 @@ SECTIONS
                        ARM_CPU_KEEP(PROC_INFO)
        }
 
-#ifdef CONFIG_DEBUG_RODATA
+#ifdef CONFIG_DEBUG_ALIGN_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
 #endif
        RO_DATA(PAGE_SIZE)
@@ -158,32 +156,33 @@ SECTIONS
 
        _etext = .;                     /* End of text and rodata section */
 
-#ifndef CONFIG_XIP_KERNEL
-# ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
-# else
+#else
        . = ALIGN(PAGE_SIZE);
-# endif
-       __init_begin = .;
 #endif
+       __init_begin = .;
+
        /*
         * The vectors and stubs are relocatable code, and the
         * only thing that matters is their relative offsets
         */
        __vectors_start = .;
-       .vectors 0 : AT(__vectors_start) {
+       .vectors 0xffff0000 : AT(__vectors_start) {
                *(.vectors)
        }
        . = __vectors_start + SIZEOF(.vectors);
        __vectors_end = .;
 
        __stubs_start = .;
-       .stubs 0x1000 : AT(__stubs_start) {
+       .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
                *(.stubs)
        }
        . = __stubs_start + SIZEOF(.stubs);
        __stubs_end = .;
 
+       PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors));
+
        INIT_TEXT_SECTION(8)
        .exit.text : {
                ARM_EXIT_KEEP(EXIT_TEXT)
@@ -214,37 +213,28 @@ SECTIONS
                __pv_table_end = .;
        }
        .init.data : {
-#ifndef CONFIG_XIP_KERNEL
                INIT_DATA
-#endif
                INIT_SETUP(16)
                INIT_CALLS
                CON_INITCALL
                SECURITY_INITCALL
                INIT_RAM_FS
        }
-#ifndef CONFIG_XIP_KERNEL
        .exit.data : {
                ARM_EXIT_KEEP(EXIT_DATA)
        }
-#endif
 
 #ifdef CONFIG_SMP
        PERCPU_SECTION(L1_CACHE_BYTES)
 #endif
 
-#ifdef CONFIG_XIP_KERNEL
-       __data_loc = ALIGN(4);          /* location in binary */
-       . = PAGE_OFFSET + TEXT_OFFSET;
-#else
-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
        . = ALIGN(1<<SECTION_SHIFT);
 #else
        . = ALIGN(THREAD_SIZE);
 #endif
        __init_end = .;
        __data_loc = .;
-#endif
 
        .data : AT(__data_loc) {
                _data = .;              /* address in memory */
@@ -256,15 +246,6 @@ SECTIONS
                 */
                INIT_TASK_DATA(THREAD_SIZE)
 
-#ifdef CONFIG_XIP_KERNEL
-               . = ALIGN(PAGE_SIZE);
-               __init_begin = .;
-               INIT_DATA
-               ARM_EXIT_KEEP(EXIT_DATA)
-               . = ALIGN(PAGE_SIZE);
-               __init_end = .;
-#endif
-
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
                READ_MOSTLY_DATA(L1_CACHE_BYTES)
@@ -342,6 +323,15 @@ SECTIONS
        STABS_DEBUG
 }
 
+#ifdef CONFIG_DEBUG_RODATA
+/*
+ * Without CONFIG_DEBUG_ALIGN_RODATA, __start_rodata_section_aligned will
+ * be the first section-aligned location after __start_rodata. Otherwise,
+ * it will be equal to __start_rodata.
+ */
+__start_rodata_section_aligned = ALIGN(__start_rodata, 1 << SECTION_SHIFT);
+#endif
+
 /*
  * These must never be empty
  * If you have to comment these two assert statements out, your
@@ -357,3 +347,5 @@ ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
  */
 ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
        "HYP init code too big or misaligned")
+
+#endif /* CONFIG_XIP_KERNEL */
index 8fb97b9..53b456a 100644 (file)
@@ -30,7 +30,7 @@
 u32 *uart;
 
 /* PORT_16C550A, in polled non-fifo mode */
-static void putc(char c)
+static inline void putc(char c)
 {
        if (!uart)
                return;
index 07152d0..cbbdd84 100644 (file)
@@ -68,7 +68,6 @@ config ARCH_NETWINDER
        select ISA
        select ISA_DMA
        select PCI
-       select VIRT_TO_BUS
        help
          Say Y here if you intend to run this kernel on the Rebel.COM
          NetWinder.  Information about this machine can be found at:
index c279293..d80879c 100644 (file)
@@ -63,7 +63,7 @@ static void __init keystone_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static phys_addr_t keystone_virt_to_idmap(unsigned long x)
+static unsigned long keystone_virt_to_idmap(unsigned long x)
 {
        return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
 }
index c089a1a..a001c7c 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 #include <mach/regs-uart.h>
 
-static void putc(char c)
+static inline void putc(char c)
 {
        while (!(__raw_readl((void __iomem*)KS8695_UART_PA + KS8695_URLS) & URLS_URTHRE))
                barrier();
index 5cb1051..033875d 100644 (file)
@@ -40,7 +40,7 @@
 #define FR_BUSY (1<<3)
 #define FR_TXFF (1<<5)
 
-static void putc(char c)
+static inline void putc(char c)
 {
        unsigned long base;
 
index 4869633..9cca6a5 100644 (file)
@@ -45,7 +45,7 @@ static void set_omap_uart_info(unsigned char port)
        *uart_info = port;
 }
 
-static void putc(int c)
+static inline void putc(int c)
 {
        if (!uart_base)
                return;
index 0fd4b0b..654a6f3 100644 (file)
@@ -76,7 +76,7 @@ int white;
 /*
  * This does not append a newline
  */
-static void putc(int c)
+static inline void putc(int c)
 {
        extern void ll_write_char(char *, char c, char white);
        int x,y;
index 73093dc..a1a041b 100644 (file)
@@ -19,7 +19,7 @@
 
 #define UART(x)                (*(volatile unsigned long *)(serial_port + (x)))
 
-static void putc(int c)
+static inline void putc(int c)
 {
        unsigned long serial_port;
 
index 4b7c324..3855ece 100644 (file)
@@ -27,7 +27,7 @@
 #define TX_DONE        (UART_LSR_TEMT | UART_LSR_THRE)
 static volatile u32 * const uart_base = (u32 *)UART0_PA;
 
-static void putc(int ch)
+static inline void putc(int ch)
 {
        /* Check THRE and TEMT bits before we transmit the character.
         */
index 549f6d3..5534766 100644 (file)
@@ -1037,24 +1037,26 @@ config ARCH_SUPPORTS_BIG_ENDIAN
          This option specifies the architecture can support big endian
          operation.
 
-config ARM_KERNMEM_PERMS
-       bool "Restrict kernel memory permissions"
-       depends on MMU
-       help
-         If this is set, kernel memory other than kernel text (and rodata)
-         will be made non-executable. The tradeoff is that each region is
-         padded to section-size (1MiB) boundaries (because their permissions
-         are different and splitting the 1M pages into 4K ones causes TLB
-         performance problems), wasting memory.
-
 config DEBUG_RODATA
        bool "Make kernel text and rodata read-only"
-       depends on ARM_KERNMEM_PERMS
+       depends on MMU && !XIP_KERNEL
+       default y if CPU_V7
+       help
+         If this is set, kernel text and rodata memory will be made
+         read-only, and non-text kernel memory will be made non-executable.
+         The tradeoff is that each region is padded to section-size (1MiB)
+         boundaries (because their permissions are different and splitting
+         the 1M pages into 4K ones causes TLB performance problems), which
+         can waste memory.
+
+config DEBUG_ALIGN_RODATA
+       bool "Make rodata strictly non-executable"
+       depends on DEBUG_RODATA
        default y
        help
-         If this is set, kernel text and rodata will be made read-only. This
-         is to help catch accidental or malicious attempts to change the
-         kernel's executable code. Additionally splits rodata from kernel
-         text so it can be made explicitly non-executable. This creates
-         another section-size padded region, so it can waste more memory
-         space while gaining the read-only protections.
+         If this is set, rodata will be made explicitly non-executable. This
+         provides protection on the rare chance that attackers might find and
+         use ROP gadgets that exist in the rodata section. This adds an
+         additional section-aligned split of rodata from kernel text so it
+         can be made explicitly non-executable. This padding may waste memory
+         space to gain the additional protection.
index 1e373d2..88255be 100644 (file)
 #include <asm/cputype.h>
 #include <asm/hardware/cache-tauros2.h>
 
+/* CP15 PJ4 Control configuration register */
+#define CCR_L2C_PREFETCH_DISABLE       BIT(24)
+#define CCR_L2C_ECC_ENABLE             BIT(23)
+#define CCR_L2C_WAY7_4_DISABLE         BIT(21)
+#define CCR_L2C_BURST8_ENABLE          BIT(20)
 
 /*
  * When Tauros2 is used on a CPU that supports the v7 hierarchical
@@ -182,18 +187,18 @@ static void enable_extra_feature(unsigned int features)
        u = read_extra_features();
 
        if (features & CACHE_TAUROS2_PREFETCH_ON)
-               u &= ~0x01000000;
+               u &= ~CCR_L2C_PREFETCH_DISABLE;
        else
-               u |= 0x01000000;
+               u |= CCR_L2C_PREFETCH_DISABLE;
        pr_info("Tauros2: %s L2 prefetch.\n",
                        (features & CACHE_TAUROS2_PREFETCH_ON)
                        ? "Enabling" : "Disabling");
 
        if (features & CACHE_TAUROS2_LINEFILL_BURST8)
-               u |= 0x00100000;
+               u |= CCR_L2C_BURST8_ENABLE;
        else
-               u &= ~0x00100000;
-       pr_info("Tauros2: %s line fill burt8.\n",
+               u &= ~CCR_L2C_BURST8_ENABLE;
+       pr_info("Tauros2: %s burst8 line fill.\n",
                        (features & CACHE_TAUROS2_LINEFILL_BURST8)
                        ? "Enabling" : "Disabling");
 
@@ -287,16 +292,15 @@ void __init tauros2_init(unsigned int features)
        node = of_find_matching_node(NULL, tauros2_ids);
        if (!node) {
                pr_info("Not found marvell,tauros2-cache, disable it\n");
-               return;
+       } else {
+               ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f);
+               if (ret) {
+                       pr_info("Not found marvell,tauros-cache-features property, "
+                               "disable extra features\n");
+                       features = 0;
+               } else
+                       features = f;
        }
-
-       ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f);
-       if (ret) {
-               pr_info("Not found marvell,tauros-cache-features property, "
-                       "disable extra features\n");
-               features = 0;
-       } else
-               features = f;
 #endif
        tauros2_internal_init(features);
 }
index 0eca381..deac58d 100644 (file)
 #include "dma.h"
 #include "mm.h"
 
+struct arm_dma_alloc_args {
+       struct device *dev;
+       size_t size;
+       gfp_t gfp;
+       pgprot_t prot;
+       const void *caller;
+       bool want_vaddr;
+};
+
+struct arm_dma_free_args {
+       struct device *dev;
+       size_t size;
+       void *cpu_addr;
+       struct page *page;
+       bool want_vaddr;
+};
+
+struct arm_dma_allocator {
+       void *(*alloc)(struct arm_dma_alloc_args *args,
+                      struct page **ret_page);
+       void (*free)(struct arm_dma_free_args *args);
+};
+
+struct arm_dma_buffer {
+       struct list_head list;
+       void *virt;
+       struct arm_dma_allocator *allocator;
+};
+
+static LIST_HEAD(arm_dma_bufs);
+static DEFINE_SPINLOCK(arm_dma_bufs_lock);
+
+static struct arm_dma_buffer *arm_dma_buffer_find(void *virt)
+{
+       struct arm_dma_buffer *buf, *found = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&arm_dma_bufs_lock, flags);
+       list_for_each_entry(buf, &arm_dma_bufs, list) {
+               if (buf->virt == virt) {
+                       list_del(&buf->list);
+                       found = buf;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&arm_dma_bufs_lock, flags);
+       return found;
+}
+
 /*
  * The DMA API is built upon the notion of "buffer ownership".  A buffer
  * is either exclusively owned by the CPU (and therefore may be accessed
@@ -592,7 +641,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
 #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv) NULL
 #define __alloc_from_pool(size, ret_page)                      NULL
 #define __alloc_from_contiguous(dev, size, prot, ret, c, wv)   NULL
-#define __free_from_pool(cpu_addr, size)                       0
+#define __free_from_pool(cpu_addr, size)                       do { } while (0)
 #define __free_from_contiguous(dev, page, cpu_addr, size, wv)  do { } while (0)
 #define __dma_free_remap(cpu_addr, size)                       do { } while (0)
 
@@ -610,7 +659,78 @@ static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
        return page_address(page);
 }
 
+static void *simple_allocator_alloc(struct arm_dma_alloc_args *args,
+                                   struct page **ret_page)
+{
+       return __alloc_simple_buffer(args->dev, args->size, args->gfp,
+                                    ret_page);
+}
+
+static void simple_allocator_free(struct arm_dma_free_args *args)
+{
+       __dma_free_buffer(args->page, args->size);
+}
 
+static struct arm_dma_allocator simple_allocator = {
+       .alloc = simple_allocator_alloc,
+       .free = simple_allocator_free,
+};
+
+static void *cma_allocator_alloc(struct arm_dma_alloc_args *args,
+                                struct page **ret_page)
+{
+       return __alloc_from_contiguous(args->dev, args->size, args->prot,
+                                      ret_page, args->caller,
+                                      args->want_vaddr);
+}
+
+static void cma_allocator_free(struct arm_dma_free_args *args)
+{
+       __free_from_contiguous(args->dev, args->page, args->cpu_addr,
+                              args->size, args->want_vaddr);
+}
+
+static struct arm_dma_allocator cma_allocator = {
+       .alloc = cma_allocator_alloc,
+       .free = cma_allocator_free,
+};
+
+static void *pool_allocator_alloc(struct arm_dma_alloc_args *args,
+                                 struct page **ret_page)
+{
+       return __alloc_from_pool(args->size, ret_page);
+}
+
+static void pool_allocator_free(struct arm_dma_free_args *args)
+{
+       __free_from_pool(args->cpu_addr, args->size);
+}
+
+static struct arm_dma_allocator pool_allocator = {
+       .alloc = pool_allocator_alloc,
+       .free = pool_allocator_free,
+};
+
+static void *remap_allocator_alloc(struct arm_dma_alloc_args *args,
+                                  struct page **ret_page)
+{
+       return __alloc_remap_buffer(args->dev, args->size, args->gfp,
+                                   args->prot, ret_page, args->caller,
+                                   args->want_vaddr);
+}
+
+static void remap_allocator_free(struct arm_dma_free_args *args)
+{
+       if (args->want_vaddr)
+               __dma_free_remap(args->cpu_addr, args->size);
+
+       __dma_free_buffer(args->page, args->size);
+}
+
+static struct arm_dma_allocator remap_allocator = {
+       .alloc = remap_allocator_alloc,
+       .free = remap_allocator_free,
+};
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent,
@@ -619,7 +739,16 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
        u64 mask = get_coherent_dma_mask(dev);
        struct page *page = NULL;
        void *addr;
-       bool want_vaddr;
+       bool allowblock, cma;
+       struct arm_dma_buffer *buf;
+       struct arm_dma_alloc_args args = {
+               .dev = dev,
+               .size = PAGE_ALIGN(size),
+               .gfp = gfp,
+               .prot = prot,
+               .caller = caller,
+               .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+       };
 
 #ifdef CONFIG_DMA_API_DEBUG
        u64 limit = (mask + 1) & ~mask;
@@ -633,6 +762,10 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
        if (!mask)
                return NULL;
 
+       buf = kzalloc(sizeof(*buf), gfp);
+       if (!buf)
+               return NULL;
+
        if (mask < 0xffffffffULL)
                gfp |= GFP_DMA;
 
@@ -644,28 +777,37 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
         * platform; see CONFIG_HUGETLBFS.
         */
        gfp &= ~(__GFP_COMP);
+       args.gfp = gfp;
 
        *handle = DMA_ERROR_CODE;
-       size = PAGE_ALIGN(size);
-       want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);
-
-       if (nommu())
-               addr = __alloc_simple_buffer(dev, size, gfp, &page);
-       else if (dev_get_cma_area(dev) && (gfp & __GFP_DIRECT_RECLAIM))
-               addr = __alloc_from_contiguous(dev, size, prot, &page,
-                                              caller, want_vaddr);
-       else if (is_coherent)
-               addr = __alloc_simple_buffer(dev, size, gfp, &page);
-       else if (!gfpflags_allow_blocking(gfp))
-               addr = __alloc_from_pool(size, &page);
+       allowblock = gfpflags_allow_blocking(gfp);
+       cma = allowblock ? dev_get_cma_area(dev) : false;
+
+       if (cma)
+               buf->allocator = &cma_allocator;
+       else if (nommu() || is_coherent)
+               buf->allocator = &simple_allocator;
+       else if (allowblock)
+               buf->allocator = &remap_allocator;
        else
-               addr = __alloc_remap_buffer(dev, size, gfp, prot, &page,
-                                           caller, want_vaddr);
+               buf->allocator = &pool_allocator;
+
+       addr = buf->allocator->alloc(&args, &page);
+
+       if (page) {
+               unsigned long flags;
 
-       if (page)
                *handle = pfn_to_dma(dev, page_to_pfn(page));
+               buf->virt = args.want_vaddr ? addr : page;
+
+               spin_lock_irqsave(&arm_dma_bufs_lock, flags);
+               list_add(&buf->list, &arm_dma_bufs);
+               spin_unlock_irqrestore(&arm_dma_bufs_lock, flags);
+       } else {
+               kfree(buf);
+       }
 
-       return want_vaddr ? addr : page;
+       return args.want_vaddr ? addr : page;
 }
 
 /*
@@ -741,25 +883,21 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                           bool is_coherent)
 {
        struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
-       bool want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);
-
-       size = PAGE_ALIGN(size);
-
-       if (nommu()) {
-               __dma_free_buffer(page, size);
-       } else if (!is_coherent && __free_from_pool(cpu_addr, size)) {
+       struct arm_dma_buffer *buf;
+       struct arm_dma_free_args args = {
+               .dev = dev,
+               .size = PAGE_ALIGN(size),
+               .cpu_addr = cpu_addr,
+               .page = page,
+               .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+       };
+
+       buf = arm_dma_buffer_find(cpu_addr);
+       if (WARN(!buf, "Freeing invalid buffer %p\n", cpu_addr))
                return;
-       } else if (!dev_get_cma_area(dev)) {
-               if (want_vaddr && !is_coherent)
-                       __dma_free_remap(cpu_addr, size);
-               __dma_free_buffer(page, size);
-       } else {
-               /*
-                * Non-atomic allocations cannot be freed with IRQs disabled
-                */
-               WARN_ON(irqs_disabled());
-               __free_from_contiguous(dev, page, cpu_addr, size, want_vaddr);
-       }
+
+       buf->allocator->free(&args);
+       kfree(buf);
 }
 
 void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
@@ -1122,6 +1260,9 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
        spin_unlock_irqrestore(&mapping->lock, flags);
 }
 
+/* We'll try 2M, 1M, 64K, and finally 4K; array must end with 0! */
+static const int iommu_order_array[] = { 9, 8, 4, 0 };
+
 static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                                          gfp_t gfp, struct dma_attrs *attrs)
 {
@@ -1129,6 +1270,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
        int count = size >> PAGE_SHIFT;
        int array_size = count * sizeof(struct page *);
        int i = 0;
+       int order_idx = 0;
 
        if (array_size <= PAGE_SIZE)
                pages = kzalloc(array_size, GFP_KERNEL);
@@ -1154,6 +1296,10 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
                return pages;
        }
 
+       /* Go straight to 4K chunks if caller says it's OK. */
+       if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs))
+               order_idx = ARRAY_SIZE(iommu_order_array) - 1;
+
        /*
         * IOMMU can map any pages, so himem can also be used here
         */
@@ -1162,22 +1308,24 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
        while (count) {
                int j, order;
 
-               for (order = __fls(count); order > 0; --order) {
-                       /*
-                        * We do not want OOM killer to be invoked as long
-                        * as we can fall back to single pages, so we force
-                        * __GFP_NORETRY for orders higher than zero.
-                        */
-                       pages[i] = alloc_pages(gfp | __GFP_NORETRY, order);
-                       if (pages[i])
-                               break;
+               order = iommu_order_array[order_idx];
+
+               /* Drop down when we get small */
+               if (__fls(count) < order) {
+                       order_idx++;
+                       continue;
                }
 
-               if (!pages[i]) {
-                       /*
-                        * Fall back to single page allocation.
-                        * Might invoke OOM killer as last resort.
-                        */
+               if (order) {
+                       /* See if it's easy to allocate a high-order chunk */
+                       pages[i] = alloc_pages(gfp | __GFP_NORETRY, order);
+
+                       /* Go down a notch at first sign of pressure */
+                       if (!pages[i]) {
+                               order_idx++;
+                               continue;
+                       }
+               } else {
                        pages[i] = alloc_pages(gfp, 0);
                        if (!pages[i])
                                goto error;
index d659096..bd274a0 100644 (file)
@@ -15,7 +15,7 @@
  * page tables.
  */
 pgd_t *idmap_pgd;
-phys_addr_t (*arch_virt_to_idmap) (unsigned long x);
+unsigned long (*arch_virt_to_idmap)(unsigned long x);
 
 #ifdef CONFIG_ARM_LPAE
 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
index 49bd081..370581a 100644 (file)
@@ -572,8 +572,9 @@ void __init mem_init(void)
        }
 }
 
-#ifdef CONFIG_ARM_KERNMEM_PERMS
+#ifdef CONFIG_DEBUG_RODATA
 struct section_perm {
+       const char *name;
        unsigned long start;
        unsigned long end;
        pmdval_t mask;
@@ -581,9 +582,13 @@ struct section_perm {
        pmdval_t clear;
 };
 
+/* First section-aligned location at or after __start_rodata. */
+extern char __start_rodata_section_aligned[];
+
 static struct section_perm nx_perms[] = {
        /* Make pages tables, etc before _stext RW (set NX). */
        {
+               .name   = "pre-text NX",
                .start  = PAGE_OFFSET,
                .end    = (unsigned long)_stext,
                .mask   = ~PMD_SECT_XN,
@@ -591,26 +596,26 @@ static struct section_perm nx_perms[] = {
        },
        /* Make init RW (set NX). */
        {
+               .name   = "init NX",
                .start  = (unsigned long)__init_begin,
                .end    = (unsigned long)_sdata,
                .mask   = ~PMD_SECT_XN,
                .prot   = PMD_SECT_XN,
        },
-#ifdef CONFIG_DEBUG_RODATA
        /* Make rodata NX (set RO in ro_perms below). */
        {
-               .start  = (unsigned long)__start_rodata,
+               .name   = "rodata NX",
+               .start  = (unsigned long)__start_rodata_section_aligned,
                .end    = (unsigned long)__init_begin,
                .mask   = ~PMD_SECT_XN,
                .prot   = PMD_SECT_XN,
        },
-#endif
 };
 
-#ifdef CONFIG_DEBUG_RODATA
 static struct section_perm ro_perms[] = {
        /* Make kernel code and rodata RX (set RO). */
        {
+               .name   = "text/rodata RO",
                .start  = (unsigned long)_stext,
                .end    = (unsigned long)__init_begin,
 #ifdef CONFIG_ARM_LPAE
@@ -623,7 +628,6 @@ static struct section_perm ro_perms[] = {
 #endif
        },
 };
-#endif
 
 /*
  * Updates section permissions only for the current mm (sections are
@@ -670,8 +674,8 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
        for (i = 0; i < n; i++) {
                if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||
                    !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {
-                       pr_err("BUG: section %lx-%lx not aligned to %lx\n",
-                               perms[i].start, perms[i].end,
+                       pr_err("BUG: %s section %lx-%lx not aligned to %lx\n",
+                               perms[i].name, perms[i].start, perms[i].end,
                                SECTION_SIZE);
                        continue;
                }
@@ -712,7 +716,6 @@ void fix_kernmem_perms(void)
        stop_machine(__fix_kernmem_perms, NULL, NULL);
 }
 
-#ifdef CONFIG_DEBUG_RODATA
 int __mark_rodata_ro(void *unused)
 {
        update_sections_early(ro_perms, ARRAY_SIZE(ro_perms));
@@ -735,11 +738,10 @@ void set_kernel_text_ro(void)
        set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
                                current->active_mm);
 }
-#endif /* CONFIG_DEBUG_RODATA */
 
 #else
 static inline void fix_kernmem_perms(void) { }
-#endif /* CONFIG_ARM_KERNMEM_PERMS */
+#endif /* CONFIG_DEBUG_RODATA */
 
 void free_tcmmem(void)
 {
index 88fbe0d..62f4d01 100644 (file)
@@ -1253,7 +1253,7 @@ static inline void prepare_page_table(void)
 
 #ifdef CONFIG_XIP_KERNEL
        /* The XIP kernel is mapped in the module area -- skip over it */
-       addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK;
+       addr = ((unsigned long)_exiprom + PMD_SIZE - 1) & PMD_MASK;
 #endif
        for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -1335,7 +1335,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
 #ifdef CONFIG_XIP_KERNEL
        map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
        map.virtual = MODULES_VADDR;
-       map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;
+       map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
        map.type = MT_ROM;
        create_mapping(&map);
 #endif
@@ -1426,7 +1426,11 @@ static void __init kmap_init(void)
 static void __init map_lowmem(void)
 {
        struct memblock_region *reg;
+#ifdef CONFIG_XIP_KERNEL
+       phys_addr_t kernel_x_start = round_down(__pa(_sdata), SECTION_SIZE);
+#else
        phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
+#endif
        phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
 
        /* Map all the lowmem memory banks. */
index 0f92d57..0f8963a 100644 (file)
@@ -487,7 +487,7 @@ __errata_finish:
 
        .align  2
 __v7_setup_stack_ptr:
-       .word   __v7_setup_stack - .
+       .word   PHYS_RELATIVE(__v7_setup_stack, .)
 ENDPROC(__v7_setup)
 
        .bss
index 8085a8a..ffb93db 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/irq.h>
 #include <linux/sched_clock.h>
 #include <plat/time.h>
+#include <asm/delay.h>
 
 /*
  * MBus bridge block registers.
@@ -188,6 +189,15 @@ orion_time_set_base(void __iomem *_timer_base)
        timer_base = _timer_base;
 }
 
+static unsigned long orion_delay_timer_read(void)
+{
+       return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+static struct delay_timer orion_delay_timer = {
+       .read_current_timer = orion_delay_timer_read,
+};
+
 void __init
 orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
                unsigned int irq, unsigned int tclk)
@@ -202,6 +212,9 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
 
        ticks_per_jiffy = (tclk + HZ/2) / HZ;
 
+       orion_delay_timer.freq = tclk;
+       register_current_timer_delay(&orion_delay_timer);
+
        /*
         * Set scale and timer for sched_clock.
         */
index f67f35b..42816be 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/smp.h>
 #include <linux/delay.h>
 #include <linux/psci.h>
-#include <linux/slab.h>
 
 #include <uapi/linux/psci.h>
 
 #include <asm/cpu_ops.h>
 #include <asm/errno.h>
 #include <asm/smp_plat.h>
-#include <asm/suspend.h>
-
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
-
-static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
-{
-       int i, ret, count = 0;
-       u32 *psci_states;
-       struct device_node *state_node, *cpu_node;
-
-       cpu_node = of_get_cpu_node(cpu, NULL);
-       if (!cpu_node)
-               return -ENODEV;
-
-       /*
-        * If the PSCI cpu_suspend function hook has not been initialized
-        * idle states must not be enabled, so bail out
-        */
-       if (!psci_ops.cpu_suspend)
-               return -EOPNOTSUPP;
-
-       /* Count idle states */
-       while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
-                                             count))) {
-               count++;
-               of_node_put(state_node);
-       }
-
-       if (!count)
-               return -ENODEV;
-
-       psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
-       if (!psci_states)
-               return -ENOMEM;
-
-       for (i = 0; i < count; i++) {
-               u32 state;
-
-               state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
-
-               ret = of_property_read_u32(state_node,
-                                          "arm,psci-suspend-param",
-                                          &state);
-               if (ret) {
-                       pr_warn(" * %s missing arm,psci-suspend-param property\n",
-                               state_node->full_name);
-                       of_node_put(state_node);
-                       goto free_mem;
-               }
-
-               of_node_put(state_node);
-               pr_debug("psci-power-state %#x index %d\n", state, i);
-               if (!psci_power_state_is_valid(state)) {
-                       pr_warn("Invalid PSCI power state %#x\n", state);
-                       ret = -EINVAL;
-                       goto free_mem;
-               }
-               psci_states[i] = state;
-       }
-       /* Idle states parsed correctly, initialize per-cpu pointer */
-       per_cpu(psci_power_state, cpu) = psci_states;
-       return 0;
-
-free_mem:
-       kfree(psci_states);
-       return ret;
-}
 
 static int __init cpu_psci_cpu_init(unsigned int cpu)
 {
@@ -178,38 +110,11 @@ static int cpu_psci_cpu_kill(unsigned int cpu)
 }
 #endif
 
-static int psci_suspend_finisher(unsigned long index)
-{
-       u32 *state = __this_cpu_read(psci_power_state);
-
-       return psci_ops.cpu_suspend(state[index - 1],
-                                   virt_to_phys(cpu_resume));
-}
-
-static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
-{
-       int ret;
-       u32 *state = __this_cpu_read(psci_power_state);
-       /*
-        * idle state index 0 corresponds to wfi, should never be called
-        * from the cpu_suspend operations
-        */
-       if (WARN_ON_ONCE(!index))
-               return -EINVAL;
-
-       if (!psci_power_state_loses_context(state[index - 1]))
-               ret = psci_ops.cpu_suspend(state[index - 1], 0);
-       else
-               ret = cpu_suspend(index, psci_suspend_finisher);
-
-       return ret;
-}
-
 const struct cpu_operations cpu_psci_ops = {
        .name           = "psci",
 #ifdef CONFIG_CPU_IDLE
-       .cpu_init_idle  = cpu_psci_cpu_init_idle,
-       .cpu_suspend    = cpu_psci_cpu_suspend,
+       .cpu_init_idle  = psci_cpu_init_idle,
+       .cpu_suspend    = psci_cpu_suspend_enter,
 #endif
        .cpu_init       = cpu_psci_cpu_init,
        .cpu_prepare    = cpu_psci_cpu_prepare,
index a030e5e..7cd32c0 100644 (file)
@@ -94,6 +94,7 @@ config PPC
        select OF_RESERVED_MEM
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select SYSCTL_EXCEPTION_TRACE
@@ -304,7 +305,7 @@ config ZONE_DMA32
 config PGTABLE_LEVELS
        int
        default 2 if !PPC64
-       default 3 if PPC_64K_PAGES
+       default 3 if PPC_64K_PAGES && !PPC_BOOK3S_64
        default 4
 
 source "init/Kconfig"
@@ -374,6 +375,24 @@ config PPC_TRANSACTIONAL_MEM
        ---help---
          Support user-mode Transactional Memory on POWERPC.
 
+config DISABLE_MPROFILE_KERNEL
+       bool "Disable use of mprofile-kernel for kernel tracing"
+       depends on PPC64 && CPU_LITTLE_ENDIAN
+       default y
+       help
+         Selecting this options disables use of the mprofile-kernel ABI for
+         kernel tracing. That will cause options such as live patching
+         (CONFIG_LIVEPATCH) which depend on CONFIG_DYNAMIC_FTRACE_WITH_REGS to
+         be disabled also.
+
+         If you have a toolchain which supports mprofile-kernel, then you can
+         enable this. Otherwise leave it disabled. If you're not sure, say
+         "N".
+
+config MPROFILE_KERNEL
+       depends on PPC64 && CPU_LITTLE_ENDIAN
+       def_bool !DISABLE_MPROFILE_KERNEL
+
 config IOMMU_HELPER
        def_bool PPC64
 
@@ -390,7 +409,7 @@ config SWIOTLB
 config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
        depends on SMP && (PPC_PSERIES || \
-       PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
+       PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE)
        ---help---
          Say Y here to be able to disable and re-enable individual
          CPUs at runtime on SMP machines.
index 96efd82..709a22a 100644 (file)
@@ -133,6 +133,21 @@ else
 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
 endif
 
+ifdef CONFIG_MPROFILE_KERNEL
+    ifeq ($(shell $(srctree)/arch/powerpc/scripts/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__),OK)
+        CC_FLAGS_FTRACE := -pg -mprofile-kernel
+        KBUILD_CPPFLAGS += -DCC_USING_MPROFILE_KERNEL
+    else
+        # If the user asked for mprofile-kernel but the toolchain doesn't
+        # support it, emit a warning and deliberately break the build later
+        # with mprofile-kernel-not-supported. We would prefer to make this an
+        # error right here, but then the user would never be able to run
+        # oldconfig to change their configuration.
+        $(warning Compiler does not support mprofile-kernel, set CONFIG_DISABLE_MPROFILE_KERNEL)
+        CC_FLAGS_FTRACE := -mprofile-kernel-not-supported
+    endif
+endif
+
 CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
 CFLAGS-$(CONFIG_POWER4_CPU) += $(call cc-option,-mcpu=power4)
 CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
@@ -310,6 +325,16 @@ corenet64_smp_defconfig:
        $(call merge_into_defconfig,corenet_basic_defconfig,\
                85xx-64bit 85xx-smp altivec 85xx-hw fsl-emb-nonhw)
 
+PHONY += mpc86xx_defconfig
+mpc86xx_defconfig:
+       $(call merge_into_defconfig,mpc86xx_basic_defconfig,\
+               86xx-hw fsl-emb-nonhw)
+
+PHONY += mpc86xx_smp_defconfig
+mpc86xx_smp_defconfig:
+       $(call merge_into_defconfig,mpc86xx_basic_defconfig,\
+               86xx-smp 86xx-hw fsl-emb-nonhw)
+
 define archhelp
   @echo '* zImage          - Build default images selected by kernel config'
   @echo '  zImage.*        - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
index ba8c9be..a8bc419 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * B4860DS Device Tree Source
  *
- * Copyright 2012 Freescale Semiconductor Inc.
+ * Copyright 2012 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        model = "fsl,B4860QDS";
        compatible = "fsl,B4860QDS";
 
+       aliases {
+               phy_sgmii_1e = &phy_sgmii_1e;
+               phy_sgmii_1f = &phy_sgmii_1f;
+               phy_xaui_slot1 = &phy_xaui_slot1;
+               phy_xaui_slot2 = &phy_xaui_slot2;
+       };
+
        ifc: localbus@ffe124000 {
                board-control@3,0 {
                        compatible = "fsl,b4860qds-fpga", "fsl,fpga-qixis";
                };
        };
 
+       soc@ffe000000 {
+               fman@400000 {
+                       ethernet@e8000 {
+                               phy-handle = <&phy_sgmii_1e>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@ea000 {
+                               phy-handle = <&phy_sgmii_1f>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xaui_slot1>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       ethernet@f2000 {
+                               phy-handle = <&phy_xaui_slot2>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       mdio@fc000 {
+                               phy_sgmii_1e: ethernet-phy@1e {
+                                       reg = <0x1e>;
+                                       status = "disabled";
+                               };
+
+                               phy_sgmii_1f: ethernet-phy@1f {
+                                       reg = <0x1f>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       mdio@fd000 {
+                               phy_xaui_slot1: xaui-phy@slot1 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x7>;
+                                       status = "disabled";
+                               };
+
+                               phy_xaui_slot2: xaui-phy@slot2 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x6>;
+                                       status = "disabled";
+                               };
+                       };
+               };
+       };
+
        rio: rapidio@ffe0c0000 {
                reg = <0xf 0xfe0c0000 0 0x11000>;
 
                        ranges = <0 0 0xc 0x30000000 0 0x10000000>;
                };
        };
-
 };
 
 /include/ "b4860si-post.dtsi"
index 6455774..3785ef8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * B4420DS Device Tree Source
  *
- * Copyright 2012 - 2014 Freescale Semiconductor, Inc.
+ * Copyright 2012 - 2015 Freescale Semiconductor, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               phy_sgmii_10 = &phy_sgmii_10;
+               phy_sgmii_11 = &phy_sgmii_11;
+               phy_sgmii_1c = &phy_sgmii_1c;
+               phy_sgmii_1d = &phy_sgmii_1d;
+       };
+
        ifc: localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x2000>;
                ranges = <0 0 0xf 0xe8000000 0x08000000
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "sst,sst25wf040";
+                               compatible = "sst,sst25wf040", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                        };
                        phy_type = "ulpi";
                };
 
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-handle = <&phy_sgmii_10>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy_sgmii_11>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_1c>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy_sgmii_1d>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       mdio@fc000 {
+                               phy_sgmii_10: ethernet-phy@10 {
+                                       reg = <0x10>;
+                               };
+
+                               phy_sgmii_11: ethernet-phy@11 {
+                                       reg = <0x11>;
+                               };
+
+                               phy_sgmii_1c: ethernet-phy@1c {
+                                       reg = <0x1c>;
+                                       status = "disabled";
+                               };
+
+                               phy_sgmii_1d: ethernet-phy@1d {
+                                       reg = <0x1d>;
+                                       status = "disabled";
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe200000 {
                                  0 0x00010000>;
                };
        };
-
 };
 
 /include/ "b4si-post.dtsi"
index f4d96d2..53f8b95 100644 (file)
@@ -53,7 +53,7 @@
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <50000000>;
 
index 7a13bf2..fead484 100644 (file)
@@ -55,7 +55,7 @@
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <30000000>;
                };
index 53ab4db..6670978 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <50000000>;
 
diff --git a/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts b/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts
new file mode 100644 (file)
index 0000000..0424fc2
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * GE PPC9A Device Tree Source
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_ppc9a.dtb gef_ppc9a.dts
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "GEF_PPC9A";
+       compatible = "gef,ppc9a";
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x40000000>; // set by uboot
+       };
+
+       lbc: localbus@fef05000 {
+               reg = <0xfef05000 0x1000>;
+
+               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+                         1 0 0xe8000000 0x08000000     // Paged Flash 0
+                         2 0 0xe0000000 0x08000000     // Paged Flash 1
+                         3 0 0xfc100000 0x00020000     // NVRAM
+                         4 0 0xfc000000 0x00008000     // FPGA
+                         5 0 0xfc008000 0x00008000     // AFIX FPGA
+                         6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
+                         7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
+
+               /* flash@0,0 is a mirror of part of the memory in flash@1,0
+               flash@0,0 {
+                       compatible = "gef,ppc9a-firmware-mirror", "cfi-flash";
+                       reg = <0x0 0x0 0x1000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "firmware";
+                               reg = <0x0 0x1000000>;
+                               read-only;
+                       };
+               };
+               */
+
+               flash@1,0 {
+                       compatible = "gef,ppc9a-paged-flash", "cfi-flash";
+                       reg = <0x1 0x0 0x8000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "user";
+                               reg = <0x0 0x7800000>;
+                       };
+                       partition@7800000 {
+                               label = "firmware";
+                               reg = <0x7800000 0x800000>;
+                               read-only;
+                       };
+               };
+
+               nvram@3,0 {
+                       device_type = "nvram";
+                       compatible = "simtek,stk14ca8";
+                       reg = <0x3 0x0 0x20000>;
+               };
+
+               fpga@4,0 {
+                       compatible = "gef,ppc9a-fpga-regs";
+                       reg = <0x4 0x0 0x40>;
+               };
+
+               wdt@4,2000 {
+                       compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
+                               "gef,fpga-wdt";
+                       reg = <0x4 0x2000 0x8>;
+                       interrupts = <0x1a 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               /* Second watchdog available, driver currently supports one.
+               wdt@4,2010 {
+                       compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
+                               "gef,fpga-wdt";
+                       reg = <0x4 0x2010 0x8>;
+                       interrupts = <0x1b 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               */
+               gef_pic: pic@4,4000 {
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       compatible = "gef,ppc9a-fpga-pic", "gef,fpga-pic-1.00";
+                       reg = <0x4 0x4000 0x20>;
+                       interrupts = <0x8 0x9 0 0>;
+
+               };
+               gef_gpio: gpio@7,14000 {
+                       #gpio-cells = <2>;
+                       compatible = "gef,ppc9a-gpio", "gef,sbc610-gpio";
+                       reg = <0x7 0x14000 0x24>;
+                       gpio-controller;
+               };
+       };
+
+       soc: soc@fef00000 {
+               ranges = <0x0 0xfef00000 0x00100000>;
+
+               i2c@3000 {
+                       hwmon@48 {
+                               compatible = "national,lm92";
+                               reg = <0x48>;
+                       };
+
+                       hwmon@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+
+                       rtc@51 {
+                               compatible = "epson,rx8581";
+                               reg = <0x00000051>;
+                       };
+
+                       eti@6b {
+                               compatible = "dallas,ds1682";
+                               reg = <0x6b>;
+                       };
+               };
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x9 0x4>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x8 0x4>;
+                               reg = <3>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet2: ethernet@25000 {
+                       status = "disabled";
+               };
+
+               mdio@25520 {
+                       status = "disabled";
+               };
+
+               enet3: ethernet@27000 {
+                       status = "disabled";
+               };
+
+               mdio@27520 {
+                       status = "disabled";
+               };
+       };
+
+       pci0: pcie@fef08000 {
+               reg = <0xfef08000 0x1000>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x40000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00400000>;
+               };
+       };
+};
+
+/include/ "mpc8641si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/gef_sbc310.dts b/arch/powerpc/boot/dts/fsl/gef_sbc310.dts
new file mode 100644 (file)
index 0000000..84b3d38
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * GE SBC310 Device Tree Source
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_sbc310.dtb gef_sbc310.dts
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "GEF_SBC310";
+       compatible = "gef,sbc310";
+
+       aliases {
+               pci1 = &pci1;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x40000000>; // set by uboot
+       };
+
+       lbc: localbus@fef05000 {
+               reg = <0xfef05000 0x1000>;
+
+               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+                         1 0 0xe0000000 0x08000000     // Paged Flash 0
+                         2 0 0xe8000000 0x08000000     // Paged Flash 1
+                         3 0 0xfc100000 0x00020000     // NVRAM
+                         4 0 0xfc000000 0x00010000>;   // FPGA
+
+               /* flash@0,0 is a mirror of part of the memory in flash@1,0
+               flash@0,0 {
+                       compatible = "gef,sbc310-firmware-mirror", "cfi-flash";
+                       reg = <0x0 0x0 0x01000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "firmware";
+                               reg = <0x0 0x01000000>;
+                               read-only;
+                       };
+               };
+               */
+
+               flash@1,0 {
+                       compatible = "gef,sbc310-paged-flash", "cfi-flash";
+                       reg = <0x1 0x0 0x8000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "user";
+                               reg = <0x0 0x7800000>;
+                       };
+                       partition@7800000 {
+                               label = "firmware";
+                               reg = <0x7800000 0x800000>;
+                               read-only;
+                       };
+               };
+
+               nvram@3,0 {
+                       device_type = "nvram";
+                       compatible = "simtek,stk14ca8";
+                       reg = <0x3 0x0 0x20000>;
+               };
+
+               fpga@4,0 {
+                       compatible = "gef,fpga-regs";
+                       reg = <0x4 0x0 0x40>;
+               };
+
+               wdt@4,2000 {
+                       compatible = "gef,sbc310-fpga-wdt", "gef,fpga-wdt-1.00",
+                               "gef,fpga-wdt";
+                       reg = <0x4 0x2000 0x8>;
+                       interrupts = <0x1a 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+/*
+               wdt@4,2010 {
+                       compatible = "gef,sbc310-fpga-wdt", "gef,fpga-wdt-1.00",
+                               "gef,fpga-wdt";
+                       reg = <0x4 0x2010 0x8>;
+                       interrupts = <0x1b 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+*/
+               gef_pic: pic@4,4000 {
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       compatible = "gef,sbc310-fpga-pic", "gef,fpga-pic";
+                       reg = <0x4 0x4000 0x20>;
+                       interrupts = <0x8 0x9 0 0>;
+
+               };
+               gef_gpio: gpio@4,8000 {
+                       #gpio-cells = <2>;
+                       compatible = "gef,sbc310-gpio";
+                       reg = <0x4 0x8000 0x24>;
+                       gpio-controller;
+               };
+       };
+
+       soc: soc@fef00000 {
+               ranges = <0x0 0xfef00000 0x00100000>;
+
+               i2c@3000 {
+                       rtc@51 {
+                               compatible = "epson,rx8581";
+                               reg = <0x00000051>;
+                       };
+               };
+
+               i2c@3100 {
+                       hwmon@48 {
+                               compatible = "national,lm92";
+                               reg = <0x48>;
+                       };
+
+                       hwmon@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+
+                       eti@6b {
+                               compatible = "dallas,ds1682";
+                               reg = <0x6b>;
+                       };
+               };
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x9 0x4>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x8 0x4>;
+                               reg = <3>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet2: ethernet@25000 {
+                       status = "disabled";
+               };
+
+               mdio@25520 {
+                       status = "disabled";
+               };
+
+               enet3: ethernet@27000 {
+                       status = "disabled";
+               };
+
+               mdio@27520 {
+                       status = "disabled";
+               };
+       };
+
+       pci0: pcie@fef08000 {
+               reg = <0xfef08000 0x1000>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+               interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+               interrupt-map = <
+                       0x0000 0x0 0x0 0x1 &mpic 0x0 0x2
+                       0x0000 0x0 0x0 0x2 &mpic 0x1 0x2
+                       0x0000 0x0 0x0 0x3 &mpic 0x2 0x2
+                       0x0000 0x0 0x0 0x4 &mpic 0x3 0x2
+               >;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x40000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00400000>;
+               };
+       };
+
+       pci1: pcie@fef09000 {
+               compatible = "fsl,mpc8641-pcie";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xfef09000 0x1000>;
+               bus-range = <0x0 0xff>;
+               ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xfe400000 0x0 0x00400000>;
+               clock-frequency = <100000000>;
+               interrupts = <0x19 0x2 0 0>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+                       0x0000 0x0 0x0 0x1 &mpic 0x4 0x2
+                       0x0000 0x0 0x0 0x2 &mpic 0x5 0x2
+                       0x0000 0x0 0x0 0x3 &mpic 0x6 0x2
+                       0x0000 0x0 0x0 0x4 &mpic 0x7 0x2
+                       >;
+
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x02000000 0x0 0xc0000000
+                                 0x02000000 0x0 0xc0000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00400000>;
+               };
+       };
+};
+
+/include/ "mpc8641si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/gef_sbc610.dts b/arch/powerpc/boot/dts/fsl/gef_sbc610.dts
new file mode 100644 (file)
index 0000000..974446a
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * GE SBC610 Device Tree Source
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Based on: SBS CM6 Device Tree Source
+ * Copyright 2007 SBS Technologies GmbH & Co. KG
+ * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ */
+
+/*
+ * Compiled with dtc -I dts -O dtb -o gef_sbc610.dtb gef_sbc610.dts
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "GEF_SBC610";
+       compatible = "gef,sbc610";
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x40000000>; // set by uboot
+       };
+
+       lbc: localbus@fef05000 {
+               reg = <0xfef05000 0x1000>;
+
+               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+                         1 0 0xe8000000 0x08000000     // Paged Flash 0
+                         2 0 0xe0000000 0x08000000     // Paged Flash 1
+                         3 0 0xfc100000 0x00020000     // NVRAM
+                         4 0 0xfc000000 0x00008000     // FPGA
+                         5 0 0xfc008000 0x00008000     // AFIX FPGA
+                         6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
+                         7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
+
+               /* flash@0,0 is a mirror of part of the memory in flash@1,0
+               flash@0,0 {
+                       compatible = "gef,sbc610-firmware-mirror", "cfi-flash";
+                       reg = <0x0 0x0 0x1000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "firmware";
+                               reg = <0x0 0x1000000>;
+                               read-only;
+                       };
+               };
+               */
+
+               flash@1,0 {
+                       compatible = "gef,sbc610-paged-flash", "cfi-flash";
+                       reg = <0x1 0x0 0x8000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "user";
+                               reg = <0x0 0x7800000>;
+                       };
+                       partition@7800000 {
+                               label = "firmware";
+                               reg = <0x7800000 0x800000>;
+                               read-only;
+                       };
+               };
+
+               nvram@3,0 {
+                       device_type = "nvram";
+                       compatible = "simtek,stk14ca8";
+                       reg = <0x3 0x0 0x20000>;
+               };
+
+               fpga@4,0 {
+                       compatible = "gef,fpga-regs";
+                       reg = <0x4 0x0 0x40>;
+               };
+
+               wdt@4,2000 {
+                       compatible = "gef,fpga-wdt";
+                       reg = <0x4 0x2000 0x8>;
+                       interrupts = <0x1a 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               /* Second watchdog available, driver currently supports one.
+               wdt@4,2010 {
+                       compatible = "gef,fpga-wdt";
+                       reg = <0x4 0x2010 0x8>;
+                       interrupts = <0x1b 0x4>;
+                       interrupt-parent = <&gef_pic>;
+               };
+               */
+               gef_pic: pic@4,4000 {
+                       #interrupt-cells = <1>;
+                       interrupt-controller;
+                       compatible = "gef,fpga-pic";
+                       reg = <0x4 0x4000 0x20>;
+                       interrupts = <0x8 0x9 0 0>;
+
+               };
+               gef_gpio: gpio@7,14000 {
+                       #gpio-cells = <2>;
+                       compatible = "gef,sbc610-gpio";
+                       reg = <0x7 0x14000 0x24>;
+                       gpio-controller;
+               };
+       };
+
+       soc: soc@fef00000 {
+               ranges = <0x0 0xfef00000 0x00100000>;
+
+               i2c@3000 {
+                       hwmon@48 {
+                               compatible = "national,lm92";
+                               reg = <0x48>;
+                       };
+
+                       hwmon@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+
+                       rtc@51 {
+                               compatible = "epson,rx8581";
+                               reg = <0x00000051>;
+                       };
+
+                       eti@6b {
+                               compatible = "dallas,ds1682";
+                               reg = <0x6b>;
+                       };
+               };
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x9 0x4>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&gef_pic>;
+                               interrupts = <0x8 0x4>;
+                               reg = <3>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "gmii";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet2: ethernet@25000 {
+                       status = "disabled";
+               };
+
+               mdio@25520 {
+                       status = "disabled";
+               };
+
+               enet3: ethernet@27000 {
+                       status = "disabled";
+               };
+
+               mdio@27520 {
+                       status = "disabled";
+               };
+       };
+
+       pci0: pcie@fef08000 {
+               reg = <0xfef08000 0x1000>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
+                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x40000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00400000>;
+               };
+       };
+};
+
+/include/ "mpc8641si-post.dtsi"
index 6858ec9..2d4b64f 100644 (file)
@@ -63,7 +63,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25fl256s1";
+                               compatible = "spansion,s25fl256s1", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <20000000>; /* input clock */
                        };
@@ -77,7 +77,7 @@
                        flash@2 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,m25p32";
+                               compatible = "micron,m25p32", "jedec,spi-nor";
                                reg = <2>;
                                spi-max-frequency = <15000000>;
                        };
index 937ad7e..a925fe4 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>;
                        partition@u-boot {
                        };
                };
                flash@1 {
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <1>;
                        spi-max-frequency = <40000000>;
                };
                flash@2 {
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <2>;
                        spi-max-frequency = <40000000>;
                };
                flash@3 {
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <3>;
                        spi-max-frequency = <40000000>;
                };
diff --git a/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts
new file mode 100644 (file)
index 0000000..554001f
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "MPC8641HPCN";
+       compatible = "fsl,mpc8641hpcn";
+
+       aliases {
+               pci1 = &pci1;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x40000000>;  // 1G at 0x0
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0xffe05000 0x1000>;
+
+               ranges = <0 0 0xef800000 0x00800000
+                         2 0 0xffdf8000 0x00008000
+                         3 0 0xffdf0000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x00800000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "kernel";
+                               reg = <0x00000000 0x00300000>;
+                       };
+                       partition@300000 {
+                               label = "firmware b";
+                               reg = <0x00300000 0x00100000>;
+                               read-only;
+                       };
+                       partition@400000 {
+                               label = "fs";
+                               reg = <0x00400000 0x00300000>;
+                       };
+                       partition@700000 {
+                               label = "firmware a";
+                               reg = <0x00700000 0x00100000>;
+                               read-only;
+                       };
+               };
+       };
+
+       soc: soc8641@ffe00000 {
+               ranges = <0x00000000 0xffe00000 0x00100000>;
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@0 {
+                               interrupts = <10 1 0 0>;
+                               reg = <0>;
+                       };
+                       phy1: ethernet-phy@1 {
+                               interrupts = <10 1 0 0>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupts = <10 1 0 0>;
+                               reg = <2>;
+                       };
+                       phy3: ethernet-phy@3 {
+                               interrupts = <10 1 0 0>;
+                               reg = <3>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@25000 {
+                       tbi-handle = <&tbi1>;
+                       phy-handle = <&phy1>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@25520 {
+                       tbi1: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+               
+               enet2: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet3: ethernet@27000 {
+                       tbi-handle = <&tbi3>;
+                       phy-handle = <&phy3>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@27520 {
+                       tbi3: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               rmu: rmu@d3000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,srio-rmu";
+                       reg = <0xd3000 0x500>;
+                       ranges = <0x0 0xd3000 0x500>;
+
+                       message-unit@0 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x0 0x100>;
+                               interrupts = <
+                                       53 2 0 0  /* msg1_tx_irq */
+                                       54 2 0 0>;/* msg1_rx_irq */
+                       };
+                       message-unit@100 {
+                               compatible = "fsl,srio-msg-unit";
+                               reg = <0x100 0x100>;
+                               interrupts = <
+                                       55 2 0 0  /* msg2_tx_irq */
+                                       56 2 0 0>;/* msg2_rx_irq */
+                       };
+                       doorbell-unit@400 {
+                               compatible = "fsl,srio-dbell-unit";
+                               reg = <0x400 0x80>;
+                               interrupts = <
+                                       49 2 0 0  /* bell_outb_irq */
+                                       50 2 0 0>;/* bell_inb_irq */
+                       };
+                       port-write-unit@4e0 {
+                               compatible = "fsl,srio-port-write-unit";
+                               reg = <0x4e0 0x20>;
+                               interrupts = <48 2 0 0>;
+                       };
+               };
+       };
+
+       pci0: pcie@ffe08000 {
+               reg = <0xffe08000 0x1000>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xffc00000 0x0 0x00010000>;
+               interrupt-map-mask = <0xff00 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x11 func 0 - PCI slot 1 */
+                       0x8800 0 0 1 &mpic 2 1
+                       0x8800 0 0 2 &mpic 3 1
+                       0x8800 0 0 3 &mpic 4 1
+                       0x8800 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 1 - PCI slot 1 */
+                       0x8900 0 0 1 &mpic 2 1
+                       0x8900 0 0 2 &mpic 3 1
+                       0x8900 0 0 3 &mpic 4 1
+                       0x8900 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 2 - PCI slot 1 */
+                       0x8a00 0 0 1 &mpic 2 1
+                       0x8a00 0 0 2 &mpic 3 1
+                       0x8a00 0 0 3 &mpic 4 1
+                       0x8a00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 3 - PCI slot 1 */
+                       0x8b00 0 0 1 &mpic 2 1
+                       0x8b00 0 0 2 &mpic 3 1
+                       0x8b00 0 0 3 &mpic 4 1
+                       0x8b00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 4 - PCI slot 1 */
+                       0x8c00 0 0 1 &mpic 2 1
+                       0x8c00 0 0 2 &mpic 3 1
+                       0x8c00 0 0 3 &mpic 4 1
+                       0x8c00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 5 - PCI slot 1 */
+                       0x8d00 0 0 1 &mpic 2 1
+                       0x8d00 0 0 2 &mpic 3 1
+                       0x8d00 0 0 3 &mpic 4 1
+                       0x8d00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 6 - PCI slot 1 */
+                       0x8e00 0 0 1 &mpic 2 1
+                       0x8e00 0 0 2 &mpic 3 1
+                       0x8e00 0 0 3 &mpic 4 1
+                       0x8e00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 7 - PCI slot 1 */
+                       0x8f00 0 0 1 &mpic 2 1
+                       0x8f00 0 0 2 &mpic 3 1
+                       0x8f00 0 0 3 &mpic 4 1
+                       0x8f00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x12 func 0 - PCI slot 2 */
+                       0x9000 0 0 1 &mpic 3 1
+                       0x9000 0 0 2 &mpic 4 1
+                       0x9000 0 0 3 &mpic 1 1
+                       0x9000 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 1 - PCI slot 2 */
+                       0x9100 0 0 1 &mpic 3 1
+                       0x9100 0 0 2 &mpic 4 1
+                       0x9100 0 0 3 &mpic 1 1
+                       0x9100 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 2 - PCI slot 2 */
+                       0x9200 0 0 1 &mpic 3 1
+                       0x9200 0 0 2 &mpic 4 1
+                       0x9200 0 0 3 &mpic 1 1
+                       0x9200 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 3 - PCI slot 2 */
+                       0x9300 0 0 1 &mpic 3 1
+                       0x9300 0 0 2 &mpic 4 1
+                       0x9300 0 0 3 &mpic 1 1
+                       0x9300 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 4 - PCI slot 2 */
+                       0x9400 0 0 1 &mpic 3 1
+                       0x9400 0 0 2 &mpic 4 1
+                       0x9400 0 0 3 &mpic 1 1
+                       0x9400 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 5 - PCI slot 2 */
+                       0x9500 0 0 1 &mpic 3 1
+                       0x9500 0 0 2 &mpic 4 1
+                       0x9500 0 0 3 &mpic 1 1
+                       0x9500 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 6 - PCI slot 2 */
+                       0x9600 0 0 1 &mpic 3 1
+                       0x9600 0 0 2 &mpic 4 1
+                       0x9600 0 0 3 &mpic 1 1
+                       0x9600 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 7 - PCI slot 2 */
+                       0x9700 0 0 1 &mpic 3 1
+                       0x9700 0 0 2 &mpic 4 1
+                       0x9700 0 0 3 &mpic 1 1
+                       0x9700 0 0 4 &mpic 2 1
+
+                       // IDSEL 0x1c  USB
+                       0xe000 0 0 1 &i8259 12 2
+                       0xe100 0 0 2 &i8259 9 2
+                       0xe200 0 0 3 &i8259 10 2
+                       0xe300 0 0 4 &i8259 11 2
+
+                       // IDSEL 0x1d  Audio
+                       0xe800 0 0 1 &i8259 6 2
+
+                       // IDSEL 0x1e Legacy
+                       0xf000 0 0 1 &i8259 7 2
+                       0xf100 0 0 1 &i8259 7 2
+
+                       // IDSEL 0x1f IDE/SATA
+                       0xf800 0 0 1 &i8259 14 2
+                       0xf900 0 0 1 &i8259 5 2
+                       >;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00010000>;
+                       uli1575@0 {
+                               reg = <0 0 0 0 0>;
+                               #size-cells = <2>;
+                               #address-cells = <3>;
+                               ranges = <0x02000000 0x0 0x80000000
+                                         0x02000000 0x0 0x80000000
+                                         0x0 0x20000000
+                                         0x01000000 0x0 0x00000000
+                                         0x01000000 0x0 0x00000000
+                                         0x0 0x00010000>;
+                               isa@1e {
+                                       device_type = "isa";
+                                       #size-cells = <1>;
+                                       #address-cells = <2>;
+                                       reg = <0xf000 0 0 0 0>;
+                                       ranges = <1 0 0x01000000 0 0
+                                                 0x00001000>;
+                                       interrupt-parent = <&i8259>;
+
+                                       i8259: interrupt-controller@20 {
+                                               reg = <1 0x20 2
+                                                      1 0xa0 2
+                                                      1 0x4d0 2>;
+                                               interrupt-controller;
+                                               device_type = "interrupt-controller";
+                                               #address-cells = <0>;
+                                               #interrupt-cells = <2>;
+                                               compatible = "chrp,iic";
+                                               interrupts = <9 2 0 0>;
+                                       };
+
+                                       i8042@60 {
+                                               #size-cells = <0>;
+                                               #address-cells = <1>;
+                                               reg = <1 0x60 1 1 0x64 1>;
+                                               interrupts = <1 3 12 3>;
+                                               interrupt-parent = <&i8259>;
+
+                                               keyboard@0 {
+                                                       reg = <0>;
+                                                       compatible = "pnpPNP,303";
+                                               };
+
+                                               mouse@1 {
+                                                       reg = <1>;
+                                                       compatible = "pnpPNP,f03";
+                                               };
+                                       };
+
+                                       rtc@70 {
+                                               compatible =
+                                                       "pnpPNP,b00";
+                                               reg = <1 0x70 2>;
+                                       };
+
+                                       gpio@400 {
+                                               reg = <1 0x400 0x80>;
+                                       };
+                               };
+                       };
+               };
+
+       };
+
+       pci1: pcie@ffe09000 {
+               compatible = "fsl,mpc8641-pcie";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xffe09000 0x1000>;
+               bus-range = <0 0xff>;
+               ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xffc10000 0x0 0x00010000>;
+               clock-frequency = <100000000>;
+               interrupts = <25 2 0 0>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0x0000 0 0 1 &mpic 4 1
+                       0x0000 0 0 2 &mpic 5 1
+                       0x0000 0 0 3 &mpic 6 1
+                       0x0000 0 0 4 &mpic 7 1
+                       >;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x02000000 0x0 0xa0000000
+                                 0x02000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00010000>;
+               };
+       };
+/*
+ * Only one of Rapid IO or PCI can be present due to HW limitations and
+ * due to the fact that the 2 now share address space in the new memory
+ * map.  The most likely case is that we have PCI, so comment out the
+ * rapidio node.  Leave it here for reference.
+
+       rapidio@ffec0000 {
+               reg = <0xffec0000 0x11000>;
+               compatible = "fsl,srio";
+               interrupts = <48 2 0 0>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               fsl,srio-rmu-handle = <&rmu>;
+               ranges;
+
+               port1 {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       cell-index = <1>;
+                       ranges = <0 0 0x80000000 0 0x20000000>;
+               };
+       };
+*/
+
+};
+
+/include/ "mpc8641si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts b/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts
new file mode 100644 (file)
index 0000000..fec5867
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2008-2009 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "MPC8641HPCN";
+       compatible = "fsl,mpc8641hpcn";
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases {
+               pci1 = &pci1;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x00000000 0x0 0x40000000>;  // 1G at 0x0
+       };
+
+       lbc: localbus@fffe05000 {
+               reg = <0x0f 0xffe05000 0x0 0x1000>;
+
+               ranges = <0 0 0xf 0xef800000 0x00800000
+                         2 0 0xf 0xffdf8000 0x00008000
+                         3 0 0xf 0xffdf0000 0x00008000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x00800000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "kernel";
+                               reg = <0x00000000 0x00300000>;
+                       };
+                       partition@300000 {
+                               label = "firmware b";
+                               reg = <0x00300000 0x00100000>;
+                               read-only;
+                       };
+                       partition@400000 {
+                               label = "fs";
+                               reg = <0x00400000 0x00300000>;
+                       };
+                       partition@700000 {
+                               label = "firmware a";
+                               reg = <0x00700000 0x00100000>;
+                               read-only;
+                       };
+               };
+       };
+
+       soc: soc8641@fffe00000 {
+               ranges = <0x00000000 0x0f 0xffe00000 0x00100000>;
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@0 {
+                               interrupts = <10 1 0 0>;
+                               reg = <0>;
+                       };
+                       phy1: ethernet-phy@1 {
+                               interrupts = <10 1 0 0>;
+                               reg = <1>;
+                       };
+                       phy2: ethernet-phy@2 {
+                               interrupts = <10 1 0 0>;
+                               reg = <2>;
+                       };
+                       phy3: ethernet-phy@3 {
+                               interrupts = <10 1 0 0>;
+                               reg = <3>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@25000 {
+                       tbi-handle = <&tbi1>;
+                       phy-handle = <&phy1>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@25520 {
+                       tbi1: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet2: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet3: ethernet@27000 {
+                       tbi-handle = <&tbi3>;
+                       phy-handle = <&phy3>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@27520 {
+                       tbi3: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+       };
+
+       pci0: pcie@fffe08000 {
+               reg = <0x0f 0xffe08000 0x0 0x1000>;
+               ranges = <0x02000000 0x0 0xe0000000 0x0c 0x00000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0x0f 0xffc00000 0x0 0x00010000>;
+               interrupt-map-mask = <0xff00 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x11 func 0 - PCI slot 1 */
+                       0x8800 0 0 1 &mpic 2 1
+                       0x8800 0 0 2 &mpic 3 1
+                       0x8800 0 0 3 &mpic 4 1
+                       0x8800 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 1 - PCI slot 1 */
+                       0x8900 0 0 1 &mpic 2 1
+                       0x8900 0 0 2 &mpic 3 1
+                       0x8900 0 0 3 &mpic 4 1
+                       0x8900 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 2 - PCI slot 1 */
+                       0x8a00 0 0 1 &mpic 2 1
+                       0x8a00 0 0 2 &mpic 3 1
+                       0x8a00 0 0 3 &mpic 4 1
+                       0x8a00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 3 - PCI slot 1 */
+                       0x8b00 0 0 1 &mpic 2 1
+                       0x8b00 0 0 2 &mpic 3 1
+                       0x8b00 0 0 3 &mpic 4 1
+                       0x8b00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 4 - PCI slot 1 */
+                       0x8c00 0 0 1 &mpic 2 1
+                       0x8c00 0 0 2 &mpic 3 1
+                       0x8c00 0 0 3 &mpic 4 1
+                       0x8c00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 5 - PCI slot 1 */
+                       0x8d00 0 0 1 &mpic 2 1
+                       0x8d00 0 0 2 &mpic 3 1
+                       0x8d00 0 0 3 &mpic 4 1
+                       0x8d00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 6 - PCI slot 1 */
+                       0x8e00 0 0 1 &mpic 2 1
+                       0x8e00 0 0 2 &mpic 3 1
+                       0x8e00 0 0 3 &mpic 4 1
+                       0x8e00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x11 func 7 - PCI slot 1 */
+                       0x8f00 0 0 1 &mpic 2 1
+                       0x8f00 0 0 2 &mpic 3 1
+                       0x8f00 0 0 3 &mpic 4 1
+                       0x8f00 0 0 4 &mpic 1 1
+
+                       /* IDSEL 0x12 func 0 - PCI slot 2 */
+                       0x9000 0 0 1 &mpic 3 1
+                       0x9000 0 0 2 &mpic 4 1
+                       0x9000 0 0 3 &mpic 1 1
+                       0x9000 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 1 - PCI slot 2 */
+                       0x9100 0 0 1 &mpic 3 1
+                       0x9100 0 0 2 &mpic 4 1
+                       0x9100 0 0 3 &mpic 1 1
+                       0x9100 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 2 - PCI slot 2 */
+                       0x9200 0 0 1 &mpic 3 1
+                       0x9200 0 0 2 &mpic 4 1
+                       0x9200 0 0 3 &mpic 1 1
+                       0x9200 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 3 - PCI slot 2 */
+                       0x9300 0 0 1 &mpic 3 1
+                       0x9300 0 0 2 &mpic 4 1
+                       0x9300 0 0 3 &mpic 1 1
+                       0x9300 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 4 - PCI slot 2 */
+                       0x9400 0 0 1 &mpic 3 1
+                       0x9400 0 0 2 &mpic 4 1
+                       0x9400 0 0 3 &mpic 1 1
+                       0x9400 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 5 - PCI slot 2 */
+                       0x9500 0 0 1 &mpic 3 1
+                       0x9500 0 0 2 &mpic 4 1
+                       0x9500 0 0 3 &mpic 1 1
+                       0x9500 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 6 - PCI slot 2 */
+                       0x9600 0 0 1 &mpic 3 1
+                       0x9600 0 0 2 &mpic 4 1
+                       0x9600 0 0 3 &mpic 1 1
+                       0x9600 0 0 4 &mpic 2 1
+
+                       /* IDSEL 0x12 func 7 - PCI slot 2 */
+                       0x9700 0 0 1 &mpic 3 1
+                       0x9700 0 0 2 &mpic 4 1
+                       0x9700 0 0 3 &mpic 1 1
+                       0x9700 0 0 4 &mpic 2 1
+
+                       // IDSEL 0x1c  USB
+                       0xe000 0 0 1 &i8259 12 2
+                       0xe100 0 0 2 &i8259 9 2
+                       0xe200 0 0 3 &i8259 10 2
+                       0xe300 0 0 4 &i8259 11 2
+
+                       // IDSEL 0x1d  Audio
+                       0xe800 0 0 1 &i8259 6 2
+
+                       // IDSEL 0x1e Legacy
+                       0xf000 0 0 1 &i8259 7 2
+                       0xf100 0 0 1 &i8259 7 2
+
+                       // IDSEL 0x1f IDE/SATA
+                       0xf800 0 0 1 &i8259 14 2
+                       0xf900 0 0 1 &i8259 5 2
+                       >;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0xe0000000
+                                 0x02000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00010000>;
+                       uli1575@0 {
+                               reg = <0 0 0 0 0>;
+                               #size-cells = <2>;
+                               #address-cells = <3>;
+                               ranges = <0x02000000 0x0 0xe0000000
+                                         0x02000000 0x0 0xe0000000
+                                         0x0 0x20000000
+                                         0x01000000 0x0 0x00000000
+                                         0x01000000 0x0 0x00000000
+                                         0x0 0x00010000>;
+                               isa@1e {
+                                       device_type = "isa";
+                                       #size-cells = <1>;
+                                       #address-cells = <2>;
+                                       reg = <0xf000 0 0 0 0>;
+                                       ranges = <1 0 0x01000000 0 0
+                                                 0x00001000>;
+                                       interrupt-parent = <&i8259>;
+
+                                       i8259: interrupt-controller@20 {
+                                               reg = <1 0x20 2
+                                                      1 0xa0 2
+                                                      1 0x4d0 2>;
+                                               interrupt-controller;
+                                               device_type = "interrupt-controller";
+                                               #address-cells = <0>;
+                                               #interrupt-cells = <2>;
+                                               compatible = "chrp,iic";
+                                               interrupts = <9 2 0 0>;
+                                       };
+
+                                       i8042@60 {
+                                               #size-cells = <0>;
+                                               #address-cells = <1>;
+                                               reg = <1 0x60 1 1 0x64 1>;
+                                               interrupts = <1 3 12 3>;
+                                               interrupt-parent = <&i8259>;
+
+                                               keyboard@0 {
+                                                       reg = <0>;
+                                                       compatible = "pnpPNP,303";
+                                               };
+
+                                               mouse@1 {
+                                                       reg = <1>;
+                                                       compatible = "pnpPNP,f03";
+                                               };
+                                       };
+
+                                       rtc@70 {
+                                               compatible =
+                                                       "pnpPNP,b00";
+                                               reg = <1 0x70 2>;
+                                       };
+
+                                       gpio@400 {
+                                               reg = <1 0x400 0x80>;
+                                       };
+                               };
+                       };
+               };
+
+       };
+
+       pci1: pcie@fffe09000 {
+               compatible = "fsl,mpc8641-pcie";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0x0f 0xffe09000 0x0 0x1000>;
+               bus-range = <0x0 0xff>;
+               ranges = <0x02000000 0x0 0xe0000000 0x0c 0x20000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0x0f 0xffc10000 0x0 0x00010000>;
+               clock-frequency = <100000000>;
+               interrupts = <25 2 0 0>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0x0000 0 0 1 &mpic 4 1
+                       0x0000 0 0 2 &mpic 5 1
+                       0x0000 0 0 3 &mpic 6 1
+                       0x0000 0 0 4 &mpic 7 1
+                       >;
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x02000000 0x0 0xe0000000
+                                 0x02000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00010000>;
+               };
+       };
+};
+
+/include/ "mpc8641si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi b/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi
new file mode 100644 (file)
index 0000000..70889d8
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * MPC8641 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+&lbc {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       compatible = "fsl,mpc8641-localbus", "simple-bus";
+       interrupts = <19 2 0 0>;
+};
+
+&soc {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       device_type = "soc";
+       compatible = "fsl,mpc8641-soc", "simple-bus";
+       bus-frequency = <0>;
+
+       mcm-law@0 {
+               compatible = "fsl,mcm-law";
+               reg = <0x0 0x1000>;
+               fsl,num-laws = <10>;
+       };
+
+       mcm@1000 {
+               compatible = "fsl,mpc8641-mcm", "fsl,mcm";
+               reg = <0x1000 0x1000>;
+               interrupts = <17 2 0 0>;
+       };
+
+/include/ "pq3-i2c-0.dtsi"
+/include/ "pq3-i2c-1.dtsi"
+/include/ "pq3-duart-0.dtsi"
+       serial@4600 {
+               interrupts = <28 2 0 0>;
+       };
+/include/ "pq3-dma-0.dtsi"
+       dma@21300 {
+               compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
+       };
+       dma-channel@0 {
+               compatible = "fsl,mpc8641-dma-channel", "fsl,eloplus-dma-channel";
+       };
+       dma-channel@80 {
+               compatible = "fsl,mpc8641-dma-channel", "fsl,eloplus-dma-channel";
+       };
+       dma-channel@100 {
+               compatible = "fsl,mpc8641-dma-channel", "fsl,eloplus-dma-channel";
+       };
+       dma-channel@180 {
+               compatible = "fsl,mpc8641-dma-channel", "fsl,eloplus-dma-channel";
+       };
+
+/include/ "pq3-etsec1-0.dtsi"
+       ethernet@24000 {
+               model = "TSEC";
+       };
+/include/ "pq3-etsec1-1.dtsi"
+       ethernet@25000 {
+               model = "TSEC";
+       };
+/include/ "pq3-etsec1-2.dtsi"
+       ethernet@26000 {
+               model = "TSEC";
+       };
+/include/ "pq3-etsec1-3.dtsi"
+       ethernet@27000 {
+               model = "TSEC";
+       };
+
+/include/ "qoriq-mpic.dtsi"
+       msi@41600 {
+               compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
+       };
+       msi@41800 {
+               compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
+       };
+       msi@41a00 {
+               compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
+       };
+
+       global-utilities@e0000 {
+               compatible = "fsl,mpc8641-guts";
+               reg = <0xe0000 0x1000>;
+               fsl,has-rstcr;
+       };
+};
+
+&pci0 {
+       compatible = "fsl,mpc8641-pcie";
+       device_type = "pci";
+       #size-cells = <2>;
+       #address-cells = <3>;
+       bus-range = <0x0 0xff>;
+       clock-frequency = <100000000>;
+       interrupts = <24 2 0 0>;
+       interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+
+       interrupt-map = <
+               0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
+               0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
+               0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
+               0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
+               >;
+
+       pcie@0 {
+               reg = <0 0 0 0 0>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi
new file mode 100644 (file)
index 0000000..9e03328
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * MPC8641 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2016 Elettra-Sincrotrone Trieste S.C.p.A.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&mpic>;
+
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8641@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <32768>;
+                       i-cache-size = <32768>;
+                       timebase-frequency = <0>;
+                       bus-frequency = <0>;
+                       clock-frequency = <0>;
+               };
+
+               PowerPC,8641@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <32768>;
+                       i-cache-size = <32768>;
+                       timebase-frequency = <0>;
+                       bus-frequency = <0>;
+                       clock-frequency = <0>;
+               };
+       };
+};
index c7bc1a0..69559e9 100644 (file)
                        fsl,espi-num-chipselects = <2>;
 
                        flash@0 {
-                               compatible = "atmel,at25df641";
+                               compatible = "atmel,at25df641", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>;
                        };
                        flash@1 {
-                               compatible = "atmel,at25df641";
+                               compatible = "atmel,at25df641", "jedec,spi-nor";
                                reg = <1>;
                                spi-max-frequency = <10000000>;
                        };
index 14b6295..a8e4ba0 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>;
 
index c952cd3..25f81ee 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>; /* input clock */
 
index 740553c..f2dc6c0 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                /* input clock */
                                spi-max-frequency = <40000000>;
index 1fb7e0e..703142e 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>; /* input clock */
 
index 27fdfd7..291454c 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
 
index e8a0f95..18f9b31 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>; /* input clock */
 
index 149da0f..ddefbf6 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>; /* input clock */
 
index 04c1633..d505d7c 100644 (file)
@@ -86,7 +86,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,m25p80";
+                               compatible = "spansion,m25p80", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <1000000>;
                                partition@0 {
index b05dcb4..b4d0586 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,m25p80";
+                       compatible = "spansion,m25p80", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>;
 
index f502564..d44bb12 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
+                       compatible = "spansion,s25sl12801", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>; /* input clock */
 
index ad2e242..03c9afc 100644 (file)
                flash@0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       compatible = "spansion,m25p80";
+                       compatible = "spansion,m25p80", "jedec,spi-nor";
                        reg = <0>;
                        spi-max-frequency = <40000000>;
 
index 70cf090..435a319 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>;
 
index e9bd894..e50fea9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P2041RDB Device Tree Source
  *
- * Copyright 2011 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2011 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               phy_rgmii_0 = &phy_rgmii_0;
+               phy_rgmii_1 = &phy_rgmii_1;
+               phy_sgmii_2 = &phy_sgmii_2;
+               phy_sgmii_3 = &phy_sgmii_3;
+               phy_sgmii_4 = &phy_sgmii_4;
+               phy_sgmii_1c = &phy_sgmii_1c;
+               phy_sgmii_1d = &phy_sgmii_1d;
+               phy_sgmii_1e = &phy_sgmii_1e;
+               phy_sgmii_1f = &phy_sgmii_1f;
+               phy_xgmii_2 = &phy_xgmii_2;
+       };
+
        memory {
                device_type = "memory";
        };
@@ -83,7 +96,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                                partition@u-boot {
                usb1: usb@211000 {
                        dr_mode = "host";
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-handle = <&phy_sgmii_2>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       mdio@e1120 {
+                               phy_rgmii_0: ethernet-phy@0 {
+                                       reg = <0x0>;
+                               };
+
+                               phy_rgmii_1: ethernet-phy@1 {
+                                       reg = <0x1>;
+                               };
+
+                               phy_sgmii_2: ethernet-phy@2 {
+                                       reg = <0x2>;
+                               };
+
+                               phy_sgmii_3: ethernet-phy@3 {
+                                       reg = <0x3>;
+                               };
+
+                               phy_sgmii_4: ethernet-phy@4 {
+                                       reg = <0x4>;
+                               };
+
+                               phy_sgmii_1c: ethernet-phy@1c {
+                                       reg = <0x1c>;
+                               };
+
+                               phy_sgmii_1d: ethernet-phy@1d {
+                                       reg = <0x1d>;
+                               };
+
+                               phy_sgmii_1e: ethernet-phy@1e {
+                                       reg = <0x1e>;
+                               };
+
+                               phy_sgmii_1f: ethernet-phy@1f {
+                                       reg = <0x1f>;
+                               };
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy_sgmii_3>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_4>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy_rgmii_1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_0>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xgmii_2>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       mdio@f1000 {
+                               phy_xgmii_2: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+               };
        };
 
        rio: rapidio@ffe0c0000 {
index f2b1d40..40748e4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P3041DS Device Tree Source
  *
- * Copyright 2010 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2010 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases{
+               phy_rgmii_0 = &phy_rgmii_0;
+               phy_rgmii_1 = &phy_rgmii_1;
+               phy_sgmii_1c = &phy_sgmii_1c;
+               phy_sgmii_1d = &phy_sgmii_1d;
+               phy_sgmii_1e = &phy_sgmii_1e;
+               phy_sgmii_1f = &phy_sgmii_1f;
+               phy_xgmii_1 = &phy_xgmii_1;
+               phy_xgmii_2 = &phy_xgmii_2;
+               emi1_rgmii = &hydra_mdio_rgmii;
+               emi1_sgmii = &hydra_mdio_sgmii;
+               emi2_xgmii = &hydra_mdio_xgmii;
+       };
+
        memory {
                device_type = "memory";
        };
@@ -83,7 +97,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <35000000>; /* input clock */
                                partition@u-boot {
                                reg = <0x4c>;
                        };
                };
+
+               fman@400000{
+                       ethernet@e0000 {
+                               phy-handle = <&phy_sgmii_1c>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy_sgmii_1d>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_1e>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy_sgmii_1f>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xgmii_1>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       hydra_mdio_xgmii: mdio@f1000 {
+                               status = "disabled";
+
+                               phy_xgmii_1: ethernet-phy@4 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x4>;
+                               };
+
+                               phy_xgmii_2: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+               };
        };
 
        rio: rapidio@ffe0c0000 {
                };
 
                board-control@3,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
                        compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
                        reg = <3 0 0x30>;
+                       ranges = <0 3 0 0x30>;
+
+                       mdio-mux-emi1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&mdio0>;
+                               reg = <9 1>;
+                               mux-mask = <0x78>;
+
+                               hydra_mdio_rgmii: rgmii-mdio@8 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <8>;
+                                       status = "disabled";
+
+                                       phy_rgmii_0: ethernet-phy@0 {
+                                               reg = <0x0>;
+                                       };
+
+                                       phy_rgmii_1: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+                               };
+
+                               hydra_mdio_sgmii: sgmii-mdio@28 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x28>;
+                                       status = "disabled";
+
+                                       phy_sgmii_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                       };
                };
        };
 
index 28a55c5..816b978 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P4080DS Device Tree Source
  *
- * Copyright 2009 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2009 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               phy_rgmii = &phyrgmii;
+               phy5_slot3 = &phy5slot3;
+               phy6_slot3 = &phy6slot3;
+               phy7_slot3 = &phy7slot3;
+               phy8_slot3 = &phy8slot3;
+               emi1_slot3 = &p4080mdio2;
+               emi1_slot4 = &p4080mdio1;
+               emi1_slot5 = &p4080mdio3;
+               emi1_rgmii = &p4080mdio0;
+               emi2_slot4 = &p4080xmdio1;
+               emi2_slot5 = &p4080xmdio3;
+       };
+
        memory {
                device_type = "memory";
        };
@@ -84,7 +98,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                                partition@u-boot {
                        dr_mode = "host";
                        phy_type = "ulpi";
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-handle = <&phy0>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy1>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy2>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy3>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy10>;
+                               phy-connection-type = "xgmii";
+                       };
+               };
+
+               fman@500000 {
+                       ethernet@e0000 {
+                               phy-handle = <&phy5>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy6>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy7>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy8>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy11>;
+                               phy-connection-type = "xgmii";
+                       };
+               };
        };
 
        rio: rapidio@ffe0c0000 {
                };
        };
 
+       mdio-mux-emi1 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "mdio-mux-gpio", "mdio-mux";
+               mdio-parent-bus = <&mdio0>;
+               gpios = <&gpio0 1 0>, <&gpio0 0 0>;
+
+               p4080mdio0: mdio@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       phyrgmii: ethernet-phy@0 {
+                               reg = <0x0>;
+                       };
+               };
+
+               p4080mdio1: mdio@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <1>;
+
+                       phy5: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy6: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy7: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy8: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               p4080mdio2: mdio@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <2>;
+                       status = "disabled";
+
+                       phy5slot3: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy6slot3: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy7slot3: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy8slot3: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               p4080mdio3: mdio@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <3>;
+
+                       phy0: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy1: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy2: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy3: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+       };
+
+       mdio-mux-emi2 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "mdio-mux-gpio", "mdio-mux";
+               mdio-parent-bus = <&xmdio0>;
+               gpios = <&gpio0 3 0>, <&gpio0 2 0>;
+
+               p4080xmdio1: mdio@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <1>;
+
+                       phy11: ethernet-phy@0 {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0x0>;
+                       };
+               };
+
+               p4080xmdio3: mdio@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <3>;
+
+                       phy10: ethernet-phy@4 {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0x4>;
+                       };
+               };
+       };
 };
 
 /include/ "p4080si-post.dtsi"
index 920dc77..cd6f373 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P5020DS Device Tree Source
  *
- * Copyright 2010 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2010 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               phy_rgmii_0 = &phy_rgmii_0;
+               phy_rgmii_1 = &phy_rgmii_1;
+               phy_sgmii_1c = &phy_sgmii_1c;
+               phy_sgmii_1d = &phy_sgmii_1d;
+               phy_sgmii_1e = &phy_sgmii_1e;
+               phy_sgmii_1f = &phy_sgmii_1f;
+               phy_xgmii_1 = &phy_xgmii_1;
+               phy_xgmii_2 = &phy_xgmii_2;
+               emi1_rgmii = &hydra_mdio_rgmii;
+               emi1_sgmii = &hydra_mdio_sgmii;
+               emi2_xgmii = &hydra_mdio_xgmii;
+       };
+
        memory {
                device_type = "memory";
        };
@@ -83,7 +97,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                                partition@u-boot {
                                reg = <0x4c>;
                        };
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-handle = <&phy_sgmii_1c>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy_sgmii_1d>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_1e>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy_sgmii_1f>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xgmii_1>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       hydra_mdio_xgmii: mdio@f1000 {
+                               status = "disabled";
+
+                               phy_xgmii_1: ethernet-phy@4 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x4>;
+                               };
+
+                               phy_xgmii_2: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+               };
        };
 
        rio: rapidio@ffe0c0000 {
                };
 
                board-control@3,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
                        compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
                        reg = <3 0 0x30>;
+                       ranges = <0 3 0 0x30>;
+
+                       mdio-mux-emi1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&mdio0>;
+                               reg = <9 1>;
+                               mux-mask = <0x78>;
+
+                               hydra_mdio_rgmii: rgmii-mdio@8 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <8>;
+                                       status = "disabled";
+
+                                       phy_rgmii_0: ethernet-phy@0 {
+                                               reg = <0x0>;
+                                       };
+
+                                       phy_rgmii_1: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+                               };
+
+                               hydra_mdio_sgmii: sgmii-mdio@28 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x28>;
+                                       status = "disabled";
+
+                                       phy_sgmii_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                       };
                };
        };
 
index e169cc2..4508473 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P5040DS Device Tree Source
  *
- * Copyright 2012 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2012 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases{
+               phy_sgmii_slot2_1c = &phy_sgmii_slot2_1c;
+               phy_sgmii_slot2_1d = &phy_sgmii_slot2_1d;
+               phy_sgmii_slot2_1e = &phy_sgmii_slot2_1e;
+               phy_sgmii_slot2_1f = &phy_sgmii_slot2_1f;
+               phy_sgmii_slot3_1c = &phy_sgmii_slot3_1c;
+               phy_sgmii_slot3_1d = &phy_sgmii_slot3_1d;
+               phy_sgmii_slot3_1e = &phy_sgmii_slot3_1e;
+               phy_sgmii_slot3_1f = &phy_sgmii_slot3_1f;
+               phy_sgmii_slot5_1c = &phy_sgmii_slot5_1c;
+               phy_sgmii_slot5_1d = &phy_sgmii_slot5_1d;
+               phy_sgmii_slot5_1e = &phy_sgmii_slot5_1e;
+               phy_sgmii_slot5_1f = &phy_sgmii_slot5_1f;
+               phy_sgmii_slot6_1c = &phy_sgmii_slot6_1c;
+               phy_sgmii_slot6_1d = &phy_sgmii_slot6_1d;
+               phy_sgmii_slot6_1e = &phy_sgmii_slot6_1e;
+               phy_sgmii_slot6_1f = &phy_sgmii_slot6_1f;
+               hydra_rg = &hydra_rg;
+               hydra_sg_slot2 = &hydra_sg_slot2;
+               hydra_sg_slot3 = &hydra_sg_slot3;
+               hydra_sg_slot5 = &hydra_sg_slot5;
+               hydra_sg_slot6 = &hydra_sg_slot6;
+               hydra_xg_slot1 = &hydra_xg_slot1;
+               hydra_xg_slot2 = &hydra_xg_slot2;
+       };
+
        memory {
                device_type = "memory";
        };
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
+                               compatible = "spansion,s25sl12801", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                                partition@u-boot {
                                reg = <0x4c>;
                        };
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_0>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xgmii_slot_2>;
+                               phy-connection-type = "xgmii";
+                       };
+               };
+
+               fman@500000 {
+                       ethernet@e0000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&phy_xgmii_slot_1>;
+                               phy-connection-type = "xgmii";
+                       };
+               };
        };
 
        lbc: localbus@ffe124000 {
                };
 
                board-control@3,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
                        compatible = "fsl,p5040ds-fpga", "fsl,fpga-ngpixis";
                        reg = <3 0 0x40>;
+                       ranges = <0 3 0 0x40>;
+
+                       mdio-mux-emi1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&mdio0>;
+                               reg = <9 1>;
+                               mux-mask = <0x78>;
+
+                               hydra_rg:rgmii-mdio@8 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <8>;
+                                       status = "disabled";
+
+                                       phy_rgmii_0: ethernet-phy@0 {
+                                               reg = <0x0>;
+                                       };
+
+                                       phy_rgmii_1: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+                               };
+
+                               hydra_sg_slot2: sgmii-mdio@28 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x28>;
+                                       status = "disabled";
+
+                                       phy_sgmii_slot2_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_slot2_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_slot2_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_slot2_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               hydra_sg_slot3: sgmii-mdio@68 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x68>;
+                                       status = "disabled";
+
+                                       phy_sgmii_slot3_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_slot3_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_slot3_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_slot3_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               hydra_sg_slot5: sgmii-mdio@38 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x38>;
+                                       status = "disabled";
+
+                                       phy_sgmii_slot5_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_slot5_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_slot5_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_slot5_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                               hydra_sg_slot6: sgmii-mdio@48 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x48>;
+                                       status = "disabled";
+
+                                       phy_sgmii_slot6_1c: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_sgmii_slot6_1d: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_sgmii_slot6_1e: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_sgmii_slot6_1f: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                       };
+
+                       mdio-mux-emi2 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&xmdio0>;
+                               reg = <9 1>;
+                               mux-mask = <0x06>;
+
+                               hydra_xg_slot1: hydra-xg-slot1@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+                                       status = "disabled";
+
+                                       phy_xgmii_slot_1: ethernet-phy@0 {
+                                               compatible = "ethernet-phy-ieee802.3-c45";
+                                               reg = <4>;
+                                       };
+                               };
+
+                               hydra_xg_slot2: hydra-xg-slot2@2 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <2>;
+
+                                       phy_xgmii_slot_2: ethernet-phy@4 {
+                                               compatible = "ethernet-phy-ieee802.3-c45";
+                                               reg = <0>;
+                                       };
+                               };
+                       };
                };
        };
 
index 2f227b1..e2bd931 100644 (file)
                fsl,iommu-parent = <&pamu4>;
        };
 
+/include/ "qoriq-raid1.0-0.dtsi"
 /include/ "qoriq-qman1.dtsi"
 /include/ "qoriq-bman1.dtsi"
 
index 0659d5b..dbd5775 100644 (file)
                rtic_d = &rtic_d;
                sec_mon = &sec_mon;
 
+               raideng = &raideng;
+               raideng_jr0 = &raideng_jr0;
+               raideng_jr1 = &raideng_jr1;
+               raideng_jr2 = &raideng_jr2;
+               raideng_jr3 = &raideng_jr3;
+
                fman0 = &fman0;
                fman1 = &fman1;
                ethernet0 = &enet0;
index 2e441fa..e1a961f 100644 (file)
@@ -55,6 +55,7 @@ fman@400000 {
                reg = <0xe0000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy0>;
        };
 
        mdio@e1000 {
@@ -62,5 +63,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe1000 0x1000>;
+
+               pcsphy0: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 0b8f87f..c288f3c 100644 (file)
@@ -52,6 +52,7 @@ fman@400000 {
                compatible = "fsl,fman-memac";
                reg = <0xf0000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x10 &fman0_tx_0x30>;
+               pcsphy-handle = <&pcsphy6>;
        };
 
        mdio@f1000 {
@@ -59,5 +60,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xf1000 0x1000>;
+
+               pcsphy6: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index ba6f227..94f3e71 100644 (file)
@@ -55,6 +55,7 @@ fman@400000 {
                reg = <0xe2000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy1>;
        };
 
        mdio@e3000 {
@@ -62,5 +63,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe3000 0x1000>;
+
+               pcsphy1: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 8860038..94a7698 100644 (file)
@@ -52,6 +52,7 @@ fman@400000 {
                compatible = "fsl,fman-memac";
                reg = <0xf2000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x11 &fman0_tx_0x31>;
+               pcsphy-handle = <&pcsphy7>;
        };
 
        mdio@f3000 {
@@ -59,5 +60,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xf3000 0x1000>;
+
+               pcsphy7: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index ace9c13..b5ff5f7 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xe0000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy0>;
        };
 
        mdio@e1000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe1000 0x1000>;
+
+               pcsphy0: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index a4fc286..ee44182 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xe2000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy1>;
        };
 
        mdio@e3000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe3000 0x1000>;
+
+               pcsphy1: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 78596fa..f05f0d7 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xe4000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x0a &fman0_tx_0x2a>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy2>;
        };
 
        mdio@e5000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe5000 0x1000>;
+
+               pcsphy2: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index af93abd..a9114ec 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xe6000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x0b &fman0_tx_0x2b>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy3>;
        };
 
        mdio@e7000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe7000 0x1000>;
+
+               pcsphy3: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 97cffd7..44dd00a 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xe8000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x0c &fman0_tx_0x2c>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy4>;
        };
 
        mdio@e9000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe9000 0x1000>;
+
+               pcsphy4: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 232c5c2..5b1b84b 100644 (file)
@@ -51,6 +51,7 @@ fman@400000 {
                reg = <0xea000 0x1000>;
                fsl,fman-ports = <&fman0_rx_0x0d &fman0_tx_0x2d>;
                ptp-timer = <&ptp_timer0>;
+               pcsphy-handle = <&pcsphy5>;
        };
 
        mdio@eb000 {
@@ -58,5 +59,9 @@ fman@400000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xeb000 0x1000>;
+
+               pcsphy5: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 89d64ee..0e1daae 100644 (file)
@@ -52,6 +52,7 @@ fman@500000 {
                compatible = "fsl,fman-memac";
                reg = <0xf0000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x10 &fman1_tx_0x30>;
+               pcsphy-handle = <&pcsphy14>;
        };
 
        mdio@f1000 {
@@ -59,5 +60,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xf1000 0x1000>;
+
+               pcsphy14: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 7fa9260..68c5ef7 100644 (file)
@@ -52,6 +52,7 @@ fman@500000 {
                compatible = "fsl,fman-memac";
                reg = <0xf2000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x11 &fman1_tx_0x31>;
+               pcsphy-handle = <&pcsphy15>;
        };
 
        mdio@f3000 {
@@ -59,5 +60,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xf3000 0x1000>;
+
+               pcsphy15: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 3d23666..605363c 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xe0000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x08 &fman1_tx_0x28>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy8>;
        };
 
        mdio@e1000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe1000 0x1000>;
+
+               pcsphy8: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 97dc2ee..1955dfa 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xe2000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x09 &fman1_tx_0x29>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy9>;
        };
 
        mdio@e3000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe3000 0x1000>;
+
+               pcsphy9: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index f084dd2..2c14764 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xe4000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x0a &fman1_tx_0x2a>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy10>;
        };
 
        mdio@e5000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe5000 0x1000>;
+
+               pcsphy10: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index bb627b3..b8b541f 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xe6000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x0b &fman1_tx_0x2b>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy11>;
        };
 
        mdio@e7000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe7000 0x1000>;
+
+               pcsphy11: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index 821ed12..4b2cfdd 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xe8000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x0c &fman1_tx_0x2c>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy12>;
        };
 
        mdio@e9000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xe9000 0x1000>;
+
+               pcsphy12: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
index e245f1a..0a52ddf 100644 (file)
@@ -51,6 +51,7 @@ fman@500000 {
                reg = <0xea000 0x1000>;
                fsl,fman-ports = <&fman1_rx_0x0d &fman1_tx_0x2d>;
                ptp-timer = <&ptp_timer1>;
+               pcsphy-handle = <&pcsphy13>;
        };
 
        mdio@eb000 {
@@ -58,5 +59,9 @@ fman@500000 {
                #size-cells = <0>;
                compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
                reg = <0xeb000 0x1000>;
+
+               pcsphy13: ethernet-phy@0 {
+                       reg = <0x0>;
+               };
        };
 };
diff --git a/arch/powerpc/boot/dts/fsl/sbc8641d.dts b/arch/powerpc/boot/dts/fsl/sbc8641d.dts
new file mode 100644 (file)
index 0000000..0a9733c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * SBC8641D Device Tree Source
+ *
+ * Copyright 2008 Wind River Systems Inc.
+ *
+ * Paul Gortmaker (see MAINTAINERS for contact information)
+ *
+ * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "mpc8641si-pre.dtsi"
+
+/ {
+       model = "SBC8641D";
+       compatible = "wind,sbc8641";
+
+       aliases {
+               pci1 = &pci1;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>;  // 512M at 0x0
+       };
+
+       lbc: localbus@f8005000 {
+               reg = <0xf8005000 0x1000>;
+
+               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
+                         1 0 0xf0000000 0x00010000     // 64KB EEPROM
+                         2 0 0xf1000000 0x00100000     // EPLD (1MB)
+                         3 0 0xe0000000 0x04000000     // 64MB LB SDRAM (CS3)
+                         4 0 0xe4000000 0x04000000     // 64MB LB SDRAM (CS4)
+                         6 0 0xf4000000 0x00100000     // LCD display (1MB)
+                         7 0 0xe8000000 0x04000000>;   // 64MB OneNAND
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x01000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       partition@0 {
+                               label = "dtb";
+                               reg = <0x00000000 0x00100000>;
+                               read-only;
+                       };
+                       partition@300000 {
+                               label = "kernel";
+                               reg = <0x00100000 0x00400000>;
+                               read-only;
+                       };
+                       partition@400000 {
+                               label = "fs";
+                               reg = <0x00500000 0x00a00000>;
+                       };
+                       partition@700000 {
+                               label = "firmware";
+                               reg = <0x00f00000 0x00100000>;
+                               read-only;
+                       };
+               };
+
+               epld@2,0 {
+                       compatible = "wrs,epld-localbus";
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+                       reg = <2 0 0x100000>;
+                       ranges = <0 0 5 0 1     // User switches
+                                 1 0 5 1 1     // Board ID/Rev
+                                 3 0 5 3 1>;   // LEDs
+               };
+       };
+
+       soc: soc@f8000000 {
+               ranges = <0x00000000 0xf8000000 0x00100000>;
+
+               enet0: ethernet@24000 {
+                       tbi-handle = <&tbi0>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@24520 {
+                       phy0: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+                       phy1: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+                       phy2: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+                       phy3: ethernet-phy@2 {
+                               reg = <2>;
+                       };
+                       tbi0: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet1: ethernet@25000 {
+                       tbi-handle = <&tbi1>;
+                       phy-handle = <&phy1>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@25520 {
+                       tbi1: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet2: ethernet@26000 {
+                       tbi-handle = <&tbi2>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@26520 {
+                       tbi2: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+
+               enet3: ethernet@27000 {
+                       tbi-handle = <&tbi3>;
+                       phy-handle = <&phy3>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               mdio@27520 {
+                       tbi3: tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
+               };
+       };
+
+       pci0: pcie@f8008000 {
+               reg = <0xf8008000 0x1000>;
+               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+               interrupt-map-mask = <0xff00 0 0 7>;
+
+               pcie@0 {
+                       ranges = <0x02000000 0x0 0x80000000
+                                 0x02000000 0x0 0x80000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00100000>;
+               };
+
+       };
+
+       pci1: pcie@f8009000 {
+               compatible = "fsl,mpc8641-pcie";
+               device_type = "pci";
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xf8009000 0x1000>;
+               bus-range = <0 0xff>;
+               ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
+                         0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
+               clock-frequency = <100000000>;
+               interrupts = <25 2 0 0>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0x0000 0 0 1 &mpic 4 1
+                       0x0000 0 0 2 &mpic 5 1
+                       0x0000 0 0 3 &mpic 6 1
+                       0x0000 0 0 4 &mpic 7 1
+                       >;
+
+               pcie@0 {
+                       reg = <0 0 0 0 0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x02000000 0x0 0xa0000000
+                                 0x02000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x01000000 0x0 0x00000000
+                                 0x01000000 0x0 0x00000000
+                                 0x0 0x00100000>;
+               };
+       };
+};
+
+/include/ "mpc8641si-post.dtsi"
index 6bd842b..2975762 100644 (file)
@@ -79,7 +79,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "spansion,s25fl512s";
+                               compatible = "spansion,s25fl512s", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>; /* input clk */
                        };
                                shunt-resistor = <1000>;
                        };
                };
+
+               fman@400000 {
+                       fm1mac1: ethernet@e0000 {
+                               phy-handle = <&sgmii_rtk_phy2>;
+                               phy-connection-type = "sgmii";
+                               sleep = <&rcpm 0x80000000>;
+                       };
+
+                       fm1mac2: ethernet@e2000 {
+                               sleep = <&rcpm 0x40000000>;
+                       };
+
+                       fm1mac3: ethernet@e4000 {
+                               phy-handle = <&sgmii_aqr_phy3>;
+                               phy-connection-type = "sgmii-2500";
+                               sleep = <&rcpm 0x20000000>;
+                       };
+
+                       fm1mac4: ethernet@e6000 {
+                               phy-handle = <&rgmii_rtk_phy1>;
+                               phy-connection-type = "rgmii";
+                               sleep = <&rcpm 0x10000000>;
+                       };
+
+
+                       mdio0: mdio@fc000 {
+                               rgmii_rtk_phy1: ethernet-phy@1 {
+                                       reg = <0x1>;
+                               };
+                               sgmii_rtk_phy2: ethernet-phy@3 {
+                                       reg = <0x3>;
+                               };
+                       };
+
+                       xmdio0: mdio@fd000 {
+                               sgmii_aqr_phy3: ethernet-phy@2 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x2>;
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
index 6a3581b..772143d 100644 (file)
@@ -87,7 +87,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q128a11";  /* 16MB */
+                               compatible = "micron,n25q128a11", "jedec,spi-nor";  /* 16MB */
                                reg = <0>;
                                spi-max-frequency = <10000000>;
                        };
@@ -95,7 +95,7 @@
                        flash@1 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "sst,sst25wf040";  /* 512KB */
+                               compatible = "sst,sst25wf040", "jedec,spi-nor";  /* 512KB */
                                reg = <1>;
                                spi-max-frequency = <10000000>;
                        };
                        flash@2 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "eon,en25s64";   /* 8MB */
+                               compatible = "eon,en25s64", "jedec,spi-nor";   /* 8MB */
                                reg = <2>;
                                spi-max-frequency = <10000000>;
                        };
index 0ccc7d0..302cdd2 100644 (file)
@@ -89,7 +89,7 @@
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q512ax3";
+                               compatible = "micron,n25q512ax3", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>; /* input clk */
                        };
                                #size-cells = <0>;
                        };
                };
+
+               fman@400000 {
+                       fm1mac1: ethernet@e0000 {
+                               phy-handle = <&xg_aqr105_phy3>;
+                               phy-connection-type = "xgmii";
+                               sleep = <&rcpm 0x80000000>;
+                       };
+
+                       fm1mac2: ethernet@e2000 {
+                               sleep = <&rcpm 0x40000000>;
+                       };
+
+                       fm1mac3: ethernet@e4000 {
+                               phy-handle = <&rgmii_phy2>;
+                               phy-connection-type = "rgmii";
+                               sleep = <&rcpm 0x20000000>;
+                       };
+
+                       fm1mac4: ethernet@e6000 {
+                               phy-handle = <&rgmii_phy1>;
+                               phy-connection-type = "rgmii";
+                               sleep = <&rcpm 0x10000000>;
+                       };
+
+
+                       mdio0: mdio@fc000 {
+                               rgmii_phy1: ethernet-phy@2 {
+                                       reg = <0x2>;
+                               };
+                               rgmii_phy2: ethernet-phy@6 {
+                                       reg = <0x6>;
+                               };
+                       };
+
+                       xmdio0: mdio@fd000 {
+                               xg_aqr105_phy3: ethernet-phy@1 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x1>;
+                               };
+                               sg_2500_aqr105_phy4: ethernet-phy@2 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x2>;
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
index cf19415..621f2c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T1040RDB Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 / {
        model = "fsl,T1040RDB";
        compatible = "fsl,T1040RDB";
+
+       aliases {
+               phy_sgmii_2 = &phy_sgmii_2;
+       };
+
+       soc@ffe000000 {
+               fman@400000 {
+                       ethernet@e0000 {
+                               fixed-link = <0 1 1000 0 0>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               fixed-link = <1 1 1000 0 0>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_2>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       mdio@fc000 {
+                               phy_sgmii_2: ethernet-phy@03 {
+                                       reg = <0x03>;
+                               };
+                       };
+               };
+       };
+
        ifc: localbus@ffe124000 {
                cpld@3,0 {
                        compatible = "fsl,t1040rdb-cpld";
index 8d908e7..2c13862 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T1042RDB Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 / {
        model = "fsl,T1042RDB";
        compatible = "fsl,T1042RDB";
+
+       aliases {
+               phy_sgmii_2 = &phy_sgmii_2;
+       };
+
+       soc@ffe000000 {
+               fman@400000 {
+                       ethernet@e0000 {
+                              status = "disabled";
+                       };
+
+                       ethernet@e2000 {
+                              status = "disabled";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_sgmii_2>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       mdio@fc000 {
+                               phy_sgmii_2: ethernet-phy@03 {
+                                       reg = <0x03>;
+                               };
+                       };
+               };
+       };
+
        ifc: localbus@ffe124000 {
                cpld@3,0 {
                        compatible = "fsl,t1042rdb-cpld";
index 98c0010..8ec3ff4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T1042RDB_PI Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 / {
        model = "fsl,T1042RDB_PI";
        compatible = "fsl,T1042RDB_PI";
+
        ifc: localbus@ffe124000 {
                cpld@3,0 {
                        compatible = "fsl,t1042rdb_pi-cpld";
                };
        };
+
        soc: soc@ffe000000 {
                i2c@118000 {
                        rtc@68 {
                                interrupts = <0x2 0x1 0 0>;
                        };
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@e2000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@e4000 {
+                               status = "disabled";
+                       };
+               };
        };
 };
 
index 3f6d7c6..8c7ea6c 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q512ax3";
+                               compatible = "micron,n25q512ax3", "jedec,spi-nor";
                                reg = <0>;
                                /* input clock */
                                spi-max-frequency = <10000000>;
index 1498d1e..977af35 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T104xQDS Device Tree Source
  *
- * Copyright 2013 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2013 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               emi1_rgmii0 = &t1040mdio0;
+               emi1_rgmii1 = &t1040mdio1;
+               emi1_slot3 = &t1040mdio3;
+               emi1_slot5 = &t1040mdio5;
+               emi1_slot6 = &t1040mdio6;
+               emi1_slot7 = &t1040mdio7;
+               rgmii_phy1 = &rgmii_phy1;
+               rgmii_phy2 = &rgmii_phy2;
+               phy_s3_01 = &phy_s3_01;
+               phy_s3_02 = &phy_s3_02;
+               phy_s3_03 = &phy_s3_03;
+               phy_s3_04 = &phy_s3_04;
+               phy_s5_01 = &phy_s5_01;
+               phy_s5_02 = &phy_s5_02;
+               phy_s5_03 = &phy_s5_03;
+               phy_s5_04 = &phy_s5_04;
+               phy_s6_01 = &phy_s6_01;
+               phy_s6_02 = &phy_s6_02;
+               phy_s6_03 = &phy_s6_03;
+               phy_s6_04 = &phy_s6_04;
+               phy_s7_01 = &phy_s7_01;
+               phy_s7_02 = &phy_s7_02;
+               phy_s7_03 = &phy_s7_03;
+               phy_s7_04 = &phy_s7_04;
+       };
+
        reserved-memory {
                #address-cells = <2>;
                #size-cells = <2>;
                        #size-cells = <1>;
                        compatible = "fsl,fpga-qixis";
                        reg = <3 0 0x300>;
+                       ranges = <0 3 0 0x300>;
+
+                       mdio-mux-emi1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&mdio0>;
+                               reg = <0x54 1>;
+                               mux-mask = <0xe0>;
+
+                               t1040mdio0: mdio@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x00>;
+                                       status = "disabled";
+
+                                       rgmii_phy1: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+                               };
+
+                               t1040mdio1: mdio@20 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x20>;
+                                       status = "disabled";
+
+                                       rgmii_phy2: ethernet-phy@2 {
+                                               reg = <0x2>;
+                                       };
+                               };
+
+                               t1040mdio3: mdio@60 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x60>;
+                                       status = "disabled";
+
+                                       phy_s3_01: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_s3_02: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_s3_03: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_s3_04: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               t1040mdio5: mdio@a0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0xa0>;
+
+                                       phy_s5_01: ethernet-phy@1c {
+                                               reg = <0x14>;
+                                       };
+
+                                       phy_s5_02: ethernet-phy@1d {
+                                               reg = <0x15>;
+                                       };
+
+                                       phy_s5_03: ethernet-phy@1e {
+                                               reg = <0x16>;
+                                       };
+
+                                       phy_s5_04: ethernet-phy@1f {
+                                               reg = <0x17>;
+                                       };
+                               };
+
+                               t1040mdio6: mdio@c0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0xc0>;
+
+                                       phy_s6_01: ethernet-phy@1c {
+                                               reg = <0x18>;
+                                       };
+
+                                       phy_s6_02: ethernet-phy@1d {
+                                               reg = <0x19>;
+                                       };
+
+                                       phy_s6_03: ethernet-phy@1e {
+                                               reg = <0x1a>;
+                                       };
+
+                                       phy_s6_04: ethernet-phy@1f {
+                                               reg = <0x1b>;
+                                       };
+                               };
+
+                               t1040mdio7: mdio@e0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0xe0>;
+                                       status = "disabled";
+
+                                       phy_s7_01: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       phy_s7_02: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       phy_s7_03: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       phy_s7_04: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                       };
                };
        };
 
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q128a11";
+                               compatible = "micron,n25q128a11", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>; /* input clock */
                        };
                                interrupts = <0x1 0x1 0 0>;
                        };
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               fixed-link = <0 1 1000 0 0>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               fixed-link = <1 1 1000 0 0>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy_s7_03>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&rgmii_phy1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&rgmii_phy2>;
+                               phy-connection-type = "rgmii";
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
index 830ea48..72691ef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T1040RDB/T1042RDB Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  */
 
 / {
+       aliases {
+               phy_rgmii_0 = &phy_rgmii_0;
+               phy_rgmii_1 = &phy_rgmii_1;
+               phy_sgmii_2 = &phy_sgmii_2;
+       };
+
        reserved-memory {
                #address-cells = <2>;
                #size-cells = <2>;
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q512a";
+                               compatible = "micron,n25q512a", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>; /* input clock */
                        };
+                       slic@3 {
+                               compatible = "maxim,ds26522";
+                               reg = <3>;
+                               spi-max-frequency = <2000000>; /* input clock */
+                       };
                };
 
                i2c@118000 {
                        };
                };
 
+               fman@400000 {
+                       ethernet@e6000 {
+                               phy-handle = <&phy_rgmii_0>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phy_rgmii_1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       mdio0: mdio@fc000 {
+                               phy_sgmii_2: ethernet-phy@03 {
+                                       reg = <0x03>;
+                               };
+
+                               phy_rgmii_0: ethernet-phy@01 {
+                                       reg = <0x01>;
+                               };
+
+                               phy_rgmii_1: ethernet-phy@02 {
+                                       reg = <0x02>;
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
index 9c8e10f..8d190e8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T2080QDS Device Tree Source
  *
- * Copyright 2013 Freescale Semiconductor Inc.
+ * Copyright 2013 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               emi1_slot1 = &t2080mdio2;
+               emi1_slot2 = &t2080mdio3;
+               emi1_slot3 = &t2080mdio4;
+       };
+
        rio: rapidio@ffe0c0000 {
                reg = <0xf 0xfe0c0000 0 0x11000>;
 
        };
 };
 
+&soc {
+       fman@400000 {
+               ethernet@e0000 {
+                       phy-handle = <&phy_sgmii_s3_1e>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@e2000 {
+                       phy-handle = <&phy_sgmii_s3_1f>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@e4000 {
+                       phy-handle = <&rgmii_phy1>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@e6000 {
+                       phy-handle = <&rgmii_phy2>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@e8000 {
+                       phy-handle = <&phy_sgmii_s2_1e>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@ea000 {
+                       phy-handle = <&phy_sgmii_s2_1d>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@f0000 {
+                       phy-handle = <&phy_xaui_slot3>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@f2000 {
+                       phy-handle = <&phy_sgmii_s3_1f>;
+                       phy-connection-type = "xgmii";
+               };
+
+               mdio@fd000 {
+                       phy_xaui_slot3: ethernet-phy@3 {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0x3>;
+                       };
+               };
+       };
+};
+
+&boardctrl {
+       mdio-mux-emi1 {
+               compatible = "mdio-mux-mmioreg", "mdio-mux";
+               mdio-parent-bus = <&mdio0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x54 1>;
+               mux-mask = <0xe0>;
+
+               t2080mdio0: mdio@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       rgmii_phy1: ethernet-phy@1 {
+                               reg = <0x1>;
+                       };
+               };
+
+               t2080mdio1: mdio@20 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x20>;
+
+                       rgmii_phy2: ethernet-phy@2 {
+                               reg = <0x2>;
+                       };
+               };
+
+               t2080mdio2: mdio@40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x40>;
+                       status = "disabled";
+
+                       phy_sgmii_s1_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s1_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s1_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s1_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2080mdio3: mdio@c0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xc0>;
+
+                       phy_sgmii_s2_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s2_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s2_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s2_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2080mdio4: mdio@60 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x60>;
+                       status = "disabled";
+
+                       phy_sgmii_s3_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s3_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s3_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s3_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+       };
+};
+
 /include/ "t2080si-post.dtsi"
index 33205bf..836e4c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T2080PCIe-RDB Board Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        };
 };
 
+&soc {
+       fman@400000 {
+               ethernet@e0000 {
+                       phy-handle = <&xg_aq1202_phy3>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@e2000 {
+                       phy-handle = <&xg_aq1202_phy4>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@e4000 {
+                       phy-handle = <&rgmii_phy1>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@e6000 {
+                       phy-handle = <&rgmii_phy2>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@f0000 {
+                       phy-handle = <&xg_cs4315_phy1>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@f2000 {
+                       phy-handle = <&xg_cs4315_phy2>;
+                       phy-connection-type = "xgmii";
+               };
+
+               mdio@fc000 {
+                       rgmii_phy1: ethernet-phy@1 {
+                               reg = <0x1>;
+                       };
+                       rgmii_phy2: ethernet-phy@2 {
+                               reg = <0x2>;
+                       };
+               };
+
+               mdio@fd000 {
+                       xg_cs4315_phy1: ethernet-phy@c {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0xc>;
+                       };
+
+                       xg_cs4315_phy2: ethernet-phy@d {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0xd>;
+                       };
+
+                       xg_aq1202_phy3: ethernet-phy@0 {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0x0>;
+                       };
+
+                       xg_aq1202_phy4: ethernet-phy@1 {
+                               compatible = "ethernet-phy-ieee802.3-c45";
+                               reg = <0x1>;
+                       };
+               };
+       };
+};
+
 /include/ "t2080si-post.dtsi"
index b812135..fc5c4a3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T2081QDS Device Tree Source
  *
- * Copyright 2013 Freescale Semiconductor Inc.
+ * Copyright 2013 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #address-cells = <2>;
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
+
+       aliases {
+               emi1_slot1 = &t2081mdio2;
+               emi1_slot2 = &t2081mdio3;
+               emi1_slot3 = &t2081mdio4;
+               emi1_slot5 = &t2081mdio5;
+               emi1_slot6 = &t2081mdio6;
+               emi1_slot7 = &t2081mdio7;
+       };
+};
+
+&soc {
+       fman@400000 {
+               ethernet@e0000 {
+                       phy-handle = <&phy_sgmii_s7_1c>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@e2000 {
+                       phy-handle = <&phy_sgmii_s7_1d>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@e4000 {
+                       phy-handle = <&rgmii_phy1>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@e6000 {
+                       phy-handle = <&rgmii_phy2>;
+                       phy-connection-type = "rgmii";
+               };
+
+               ethernet@e8000 {
+                       phy-handle = <&phy_sgmii_s3_1c>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@ea000 {
+                       phy-handle = <&phy_sgmii_s7_1f>;
+                       phy-connection-type = "sgmii";
+               };
+
+               ethernet@f0000 {
+                       phy-handle = <&phy_sgmii_s2_1c>;
+                       phy-connection-type = "xgmii";
+               };
+
+               ethernet@f2000 {
+                       phy-handle = <&phy_sgmii_s7_1e>;
+                       phy-connection-type = "xgmii";
+               };
+       };
+};
+
+&boardctrl {
+       mdio-mux-emi1 {
+               compatible = "mdio-mux-mmioreg", "mdio-mux";
+               mdio-parent-bus = <&mdio0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x54 1>;
+               mux-mask = <0xe0>;
+
+               t2081mdio0: mdio@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       rgmii_phy1: ethernet-phy@1 {
+                               reg = <0x1>;
+                       };
+               };
+
+               t2081mdio1: mdio@20 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x20>;
+
+                       rgmii_phy2: ethernet-phy@2 {
+                               reg = <0x2>;
+                       };
+               };
+
+               t2081mdio2: mdio@40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x40>;
+
+                       phy_sgmii_s1_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s1_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s1_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s1_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2081mdio3: mdio@60 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x60>;
+
+                       phy_sgmii_s2_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s2_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s2_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s2_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2081mdio4: mdio@80 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x80>;
+                       status = "disabled";
+
+                       phy_sgmii_s3_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s3_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s3_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s3_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2081mdio5: mdio@a0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xa0>;
+                       status = "disabled";
+
+                       phy_sgmii_s5_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s5_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s5_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s5_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2081mdio6: mdio@c0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xc0>;
+                       status = "disabled";
+
+                       phy_sgmii_s6_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s6_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s6_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s6_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+
+               t2081mdio7: mdio@e0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xe0>;
+
+                       phy_sgmii_s7_1c: ethernet-phy@1c {
+                               reg = <0x1c>;
+                       };
+
+                       phy_sgmii_s7_1d: ethernet-phy@1d {
+                               reg = <0x1d>;
+                       };
+
+                       phy_sgmii_s7_1e: ethernet-phy@1e {
+                               reg = <0x1e>;
+                       };
+
+                       phy_sgmii_s7_1f: ethernet-phy@1f {
+                               reg = <0x1f>;
+                       };
+               };
+       };
 };
 
 /include/ "t2081si-post.dtsi"
index 869f915..ec080bd 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q128a11"; /* 16MB */
+                               compatible = "micron,n25q128a11", "jedec,spi-nor"; /* 16MB */
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                        };
                        flash@1 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "sst,sst25wf040";
+                               compatible = "sst,sst25wf040", "jedec,spi-nor";
                                reg = <1>;
                                spi-max-frequency = <35000000>;
                        };
                        flash@2 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "eon,en25s64";
+                               compatible = "eon,en25s64", "jedec,spi-nor";
                                reg = <2>;
                                spi-max-frequency = <35000000>;
                        };
index 693d2a8..dc93268 100644 (file)
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "micron,n25q512a";
+                               compatible = "micron,n25q512a", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <10000000>; /* input clock */
                        };
index c067a65..9573cea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T4240QDS Device Tree Source
  *
- * Copyright 2012 - 2014 Freescale Semiconductor Inc.
+ * Copyright 2012 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases{
+               phy_rgmii1 = &phyrgmii1;
+               phy_rgmii2 = &phyrgmii2;
+               phy_sgmii3 = &phy3;
+               phy_sgmii4 = &phy4;
+               phy_sgmii11 = &phy11;
+               phy_sgmii12 = &phy12;
+               sgmii_phy11 = &sgmiiphy11;
+               sgmii_phy12 = &sgmiiphy12;
+               sgmii_phy13 = &sgmiiphy13;
+               sgmii_phy14 = &sgmiiphy14;
+               sgmii_phy21 = &sgmiiphy21;
+               sgmii_phy22 = &sgmiiphy22;
+               sgmii_phy23 = &sgmiiphy23;
+               sgmii_phy24 = &sgmiiphy24;
+               sgmii_phy31 = &sgmiiphy31;
+               sgmii_phy32 = &sgmiiphy32;
+               sgmii_phy33 = &sgmiiphy33;
+               sgmii_phy34 = &sgmiiphy34;
+               sgmii_phy41 = &sgmiiphy41;
+               sgmii_phy42 = &sgmiiphy42;
+               sgmii_phy43 = &sgmiiphy43;
+               sgmii_phy44 = &sgmiiphy44;
+               phy_xfi1 = &xfiphy1;
+               phy_xfi2 = &xfiphy2;
+               phy_xfi3 = &xfiphy3;
+               phy_xfi4 = &xfiphy4;
+               xfi_pcs_mdio1 = &xfimdio0;
+               xfi_pcs_mdio2 = &xfimdio1;
+               xfi_pcs_mdio3 = &xfimdio2;
+               xfi_pcs_mdio4 = &xfimdio3;
+               emi1_rgmii = &t4240mdio0;
+               emi1_slot1 = &t4240mdio1;
+               emi1_slot2 = &t4240mdio2;
+               emi1_slot3 = &t4240mdio3;
+               emi1_slot4 = &t4240mdio4;
+       };
+
        ifc: localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x2000>;
                ranges = <0 0 0xf 0xe8000000 0x08000000
                };
 
                board-control@3,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
                        compatible = "fsl,t4240qds-fpga", "fsl,fpga-qixis";
                        reg = <3 0 0x300>;
+                       ranges = <0 3 0 0x300>;
+
+                       mdio-mux-emi1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "mdio-mux-mmioreg", "mdio-mux";
+                               mdio-parent-bus = <&mdio1>;
+                               reg = <0x54 1>;
+                               mux-mask = <0xe0>;
+
+                               t4240mdio0: mdio@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       phyrgmii1: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+
+                                       phyrgmii2: ethernet-phy@2 {
+                                               reg = <0x2>;
+                                       };
+                               };
+
+                               t4240mdio1: mdio@20 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x20>;
+                                       status = "disabled";
+
+                                       phy1: ethernet-phy@0 {
+                                               reg = <0x0>;
+                                       };
+
+                                       phy2: ethernet-phy@1 {
+                                               reg = <0x1>;
+                                       };
+
+                                       phy3: ethernet-phy@2 {
+                                               reg = <0x2>;
+                                       };
+
+                                       phy4: ethernet-phy@3 {
+                                               reg = <0x3>;
+                                       };
+
+                                       sgmiiphy11: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       sgmiiphy12: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       sgmiiphy13: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       sgmiiphy14: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               t4240mdio2: mdio@40 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x40>;
+                                       status = "disabled";
+
+                                       phy5: ethernet-phy@4 {
+                                               reg = <0x4>;
+                                       };
+
+                                       phy6: ethernet-phy@5 {
+                                               reg = <0x5>;
+                                       };
+
+                                       phy7: ethernet-phy@6 {
+                                               reg = <0x6>;
+                                       };
+
+                                       phy8: ethernet-phy@7 {
+                                               reg = <0x7>;
+                                       };
+
+                                       sgmiiphy21: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       sgmiiphy22: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       sgmiiphy23: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       sgmiiphy24: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               t4240mdio3: mdio@60 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x60>;
+                                       status = "disabled";
+
+                                       phy9: ethernet-phy@8 {
+                                               reg = <0x8>;
+                                       };
+
+                                       phy10: ethernet-phy@9 {
+                                               reg = <0x9>;
+                                       };
+
+                                       phy11: ethernet-phy@a {
+                                               reg = <0xa>;
+                                       };
+
+                                       phy12: ethernet-phy@b {
+                                               reg = <0xb>;
+                                       };
+
+                                       sgmiiphy31: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       sgmiiphy32: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       sgmiiphy33: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       sgmiiphy34: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+
+                               t4240mdio4: mdio@80 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0x80>;
+                                       status = "disabled";
+
+                                       phy13: ethernet-phy@c {
+                                               reg = <0xc>;
+                                       };
+
+                                       phy14: ethernet-phy@d {
+                                               reg = <0xd>;
+                                       };
+
+                                       phy15: ethernet-phy@e {
+                                               reg = <0xe>;
+                                       };
+
+                                       phy16: ethernet-phy@f {
+                                               reg = <0xf>;
+                                       };
+
+                                       sgmiiphy41: ethernet-phy@1c {
+                                               reg = <0x1c>;
+                                       };
+
+                                       sgmiiphy42: ethernet-phy@1d {
+                                               reg = <0x1d>;
+                                       };
+
+                                       sgmiiphy43: ethernet-phy@1e {
+                                               reg = <0x1e>;
+                                       };
+
+                                       sgmiiphy44: ethernet-phy@1f {
+                                               reg = <0x1f>;
+                                       };
+                               };
+                       };
                };
        };
 
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "sst,sst25wf040";
+                               compatible = "sst,sst25wf040", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                        };
                sdhc@114000 {
                        voltage-ranges = <1800 1800 3300 3300>;
                };
+
+               fman@400000 {
+                       port@83000 {
+                               status = "disabled";
+                       };
+
+                       port@84000 {
+                               status = "disabled";
+                       };
+
+                       port@85000 {
+                               status = "disabled";
+                       };
+
+                       port@86000 {
+                               status = "disabled";
+                       };
+
+                       port@87000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@e0000 {
+                               phy-handle = <&phy5>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy6>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy7>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy8>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phyrgmii2>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@ea000 {
+                               phy-handle = <&phy2>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&xauiphy1>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       ethernet@f2000 {
+                               phy-handle = <&xauiphy2>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       xfimdio0: mdio@f1000 {
+                               status = "disabled";
+
+                               xfiphy1: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+
+                       xfimdio1: mdio@f3000 {
+                               status = "disabled";
+
+                               xfiphy2: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+               };
+
+               fman@500000 {
+                       port@84000 {
+                               status = "disabled";
+                       };
+
+                       port@85000 {
+                               status = "disabled";
+                       };
+
+                       port@86000 {
+                               status = "disabled";
+                       };
+
+                       port@87000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@e0000 {
+                               phy-handle = <&phy13>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&phy14>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&phy15>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&phy16>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               phy-handle = <&phyrgmii1>;
+                               phy-connection-type = "rgmii";
+                       };
+
+                       ethernet@ea000 {
+                               phy-handle = <&phy10>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&xauiphy3>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       ethernet@f2000 {
+                               phy-handle = <&xauiphy4>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       xfimdio2: mdio@f1000 {
+                               status = "disabled";
+
+                               xfiphy3: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+
+                       xfimdio3: mdio@f3000 {
+                               status = "disabled";
+
+                               xfiphy4: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+                       };
+
+                       mdio@fd000 {
+                               xauiphy1: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x0>;
+                               };
+
+                               xauiphy2: ethernet-phy@1 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x1>;
+                               };
+
+                               xauiphy3: ethernet-phy@2 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x2>;
+                               };
+
+                               xauiphy4: ethernet-phy@3 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x3>;
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
index 6e820a8..cc0a264 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * T4240RDB Device Tree Source
  *
- * Copyright 2014 Freescale Semiconductor Inc.
+ * Copyright 2014 - 2015 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
        #size-cells = <2>;
        interrupt-parent = <&mpic>;
 
+       aliases {
+               sgmii_phy21 = &sgmiiphy21;
+               sgmii_phy22 = &sgmiiphy22;
+               sgmii_phy23 = &sgmiiphy23;
+               sgmii_phy24 = &sgmiiphy24;
+               sgmii_phy41 = &sgmiiphy41;
+               sgmii_phy42 = &sgmiiphy42;
+               sgmii_phy43 = &sgmiiphy43;
+               sgmii_phy44 = &sgmiiphy44;
+       };
+
        ifc: localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x2000>;
                ranges = <0 0 0xf 0xe8000000 0x08000000
                        flash@0 {
                                #address-cells = <1>;
                                #size-cells = <1>;
-                               compatible = "sst,sst25wf040";
+                               compatible = "sst,sst25wf040", "jedec,spi-nor";
                                reg = <0>;
                                spi-max-frequency = <40000000>; /* input clock */
                        };
                sdhc@114000 {
                        voltage-ranges = <1800 1800 3300 3300>;
                };
+
+               fman@400000 {
+                       ethernet@e0000 {
+                               phy-handle = <&sgmiiphy21>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&sgmiiphy22>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&sgmiiphy23>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&sgmiiphy24>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@ea000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&xfiphy1>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       ethernet@f2000 {
+                               phy-handle = <&xfiphy2>;
+                               phy-connection-type = "xgmii";
+                       };
+               };
+
+               fman@500000 {
+                       ethernet@e0000 {
+                               phy-handle = <&sgmiiphy41>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e2000 {
+                               phy-handle = <&sgmiiphy42>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e4000 {
+                               phy-handle = <&sgmiiphy43>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e6000 {
+                               phy-handle = <&sgmiiphy44>;
+                               phy-connection-type = "sgmii";
+                       };
+
+                       ethernet@e8000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@ea000 {
+                               status = "disabled";
+                       };
+
+                       ethernet@f0000 {
+                               phy-handle = <&xfiphy3>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       ethernet@f2000 {
+                               phy-handle = <&xfiphy4>;
+                               phy-connection-type = "xgmii";
+                       };
+
+                       mdio@fc000 {
+                               sgmiiphy21: ethernet-phy@0 {
+                                       reg = <0x0>;
+                               };
+
+                               sgmiiphy22: ethernet-phy@1 {
+                                       reg = <0x1>;
+                               };
+
+                               sgmiiphy23: ethernet-phy@2 {
+                                       reg = <0x2>;
+                               };
+
+                               sgmiiphy24: ethernet-phy@3 {
+                                       reg = <0x3>;
+                               };
+
+                               sgmiiphy41: ethernet-phy@4 {
+                                       reg = <0x4>;
+                               };
+
+                               sgmiiphy42: ethernet-phy@5 {
+                                       reg = <0x5>;
+                               };
+
+                               sgmiiphy43: ethernet-phy@6 {
+                                       reg = <0x6>;
+                               };
+
+                               sgmiiphy44: ethernet-phy@7 {
+                                       reg = <0x7>;
+                               };
+                       };
+
+                       mdio@fd000 {
+                               xfiphy1: ethernet-phy@10 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x10>;
+                               };
+
+                               xfiphy2: ethernet-phy@11 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x11>;
+                               };
+
+                               xfiphy3: ethernet-phy@13 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x13>;
+                               };
+
+                               xfiphy4: ethernet-phy@12 {
+                                       compatible = "ethernet-phy-ieee802.3-c45";
+                                       reg = <0x12>;
+                               };
+                       };
+               };
        };
 
        pci0: pcie@ffe240000 {
diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts
deleted file mode 100644 (file)
index 83eb0fd..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * GE PPC9A Device Tree Source
- *
- * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Based on: SBS CM6 Device Tree Source
- * Copyright 2007 SBS Technologies GmbH & Co. KG
- * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
- * Copyright 2006 Freescale Semiconductor Inc.
- */
-
-/*
- * Compiled with dtc -I dts -O dtb -o gef_ppc9a.dtb gef_ppc9a.dts
- */
-
-/dts-v1/;
-
-/ {
-       model = "GEF_PPC9A";
-       compatible = "gef,ppc9a";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x40000000>; // set by uboot
-       };
-
-       localbus@fef05000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0xfef05000 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
-                         1 0 0xe8000000 0x08000000     // Paged Flash 0
-                         2 0 0xe0000000 0x08000000     // Paged Flash 1
-                         3 0 0xfc100000 0x00020000     // NVRAM
-                         4 0 0xfc000000 0x00008000     // FPGA
-                         5 0 0xfc008000 0x00008000     // AFIX FPGA
-                         6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
-                         7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
-
-               /* flash@0,0 is a mirror of part of the memory in flash@1,0
-               flash@0,0 {
-                       compatible = "gef,ppc9a-firmware-mirror", "cfi-flash";
-                       reg = <0x0 0x0 0x1000000>;
-                       bank-width = <4>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "firmware";
-                               reg = <0x0 0x1000000>;
-                               read-only;
-                       };
-               };
-               */
-
-               flash@1,0 {
-                       compatible = "gef,ppc9a-paged-flash", "cfi-flash";
-                       reg = <0x1 0x0 0x8000000>;
-                       bank-width = <4>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "user";
-                               reg = <0x0 0x7800000>;
-                       };
-                       partition@7800000 {
-                               label = "firmware";
-                               reg = <0x7800000 0x800000>;
-                               read-only;
-                       };
-               };
-
-               nvram@3,0 {
-                       device_type = "nvram";
-                       compatible = "simtek,stk14ca8";
-                       reg = <0x3 0x0 0x20000>;
-               };
-
-               fpga@4,0 {
-                       compatible = "gef,ppc9a-fpga-regs";
-                       reg = <0x4 0x0 0x40>;
-               };
-
-               wdt@4,2000 {
-                       compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
-                               "gef,fpga-wdt";
-                       reg = <0x4 0x2000 0x8>;
-                       interrupts = <0x1a 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-               /* Second watchdog available, driver currently supports one.
-               wdt@4,2010 {
-                       compatible = "gef,ppc9a-fpga-wdt", "gef,fpga-wdt-1.00",
-                               "gef,fpga-wdt";
-                       reg = <0x4 0x2010 0x8>;
-                       interrupts = <0x1b 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-               */
-               gef_pic: pic@4,4000 {
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       compatible = "gef,ppc9a-fpga-pic", "gef,fpga-pic-1.00";
-                       reg = <0x4 0x4000 0x20>;
-                       interrupts = <0x8
-                                     0x9>;
-                       interrupt-parent = <&mpic>;
-
-               };
-               gef_gpio: gpio@7,14000 {
-                       #gpio-cells = <2>;
-                       compatible = "gef,ppc9a-gpio", "gef,sbc610-gpio";
-                       reg = <0x7 0x14000 0x24>;
-                       gpio-controller;
-               };
-       };
-
-       soc@fef00000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
-               device_type = "soc";
-               compatible = "fsl,mpc8641-soc", "simple-bus";
-               ranges = <0x0 0xfef00000 0x00100000>;
-               bus-frequency = <33333333>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c1: i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-
-                       hwmon@48 {
-                               compatible = "national,lm92";
-                               reg = <0x48>;
-                       };
-
-                       hwmon@4c {
-                               compatible = "adi,adt7461";
-                               reg = <0x4c>;
-                       };
-
-                       rtc@51 {
-                               compatible = "epson,rx8581";
-                               reg = <0x00000051>;
-                       };
-
-                       eti@6b {
-                               compatible = "dallas,ds1682";
-                               reg = <0x6b>;
-                       };
-               };
-
-               i2c2: i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30  2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@0 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x9 0x4>;
-                                       reg = <1>;
-                               };
-                               phy2: ethernet-phy@2 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x8 0x4>;
-                                       reg = <3>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x2a 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x1c 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       clock-frequency = <0>;
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-               };
-
-               msi@41600 {
-                       compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
-                       reg = <0x41600 0x80>;
-                       msi-available-ranges = <0 0x100>;
-                       interrupts = <
-                               0xe0 0
-                               0xe1 0
-                               0xe2 0
-                               0xe3 0
-                               0xe4 0
-                               0xe5 0
-                               0xe6 0
-                               0xe7 0>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@fef08000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xfef08000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
-                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <0x18 0x2>;
-               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-               interrupt-map = <
-                       0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
-                       0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
-                       0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
-                       0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
-               >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0x80000000
-                                 0x02000000 0x0 0x80000000
-                                 0x0 0x40000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00400000>;
-               };
-       };
-};
diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts
deleted file mode 100644 (file)
index d426dd3..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * GE SBC310 Device Tree Source
- *
- * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Based on: SBS CM6 Device Tree Source
- * Copyright 2007 SBS Technologies GmbH & Co. KG
- * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
- * Copyright 2006 Freescale Semiconductor Inc.
- */
-
-/*
- * Compiled with dtc -I dts -O dtb -o gef_sbc310.dtb gef_sbc310.dts
- */
-
-/dts-v1/;
-
-/ {
-       model = "GEF_SBC310";
-       compatible = "gef,sbc310";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-               pci1 = &pci1;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x40000000>; // set by uboot
-       };
-
-       localbus@fef05000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0xfef05000 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
-                         1 0 0xe0000000 0x08000000     // Paged Flash 0
-                         2 0 0xe8000000 0x08000000     // Paged Flash 1
-                         3 0 0xfc100000 0x00020000     // NVRAM
-                         4 0 0xfc000000 0x00010000>;   // FPGA
-
-               /* flash@0,0 is a mirror of part of the memory in flash@1,0
-               flash@0,0 {
-                       compatible = "gef,sbc310-firmware-mirror", "cfi-flash";
-                       reg = <0x0 0x0 0x01000000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "firmware";
-                               reg = <0x0 0x01000000>;
-                               read-only;
-                       };
-               };
-               */
-
-               flash@1,0 {
-                       compatible = "gef,sbc310-paged-flash", "cfi-flash";
-                       reg = <0x1 0x0 0x8000000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "user";
-                               reg = <0x0 0x7800000>;
-                       };
-                       partition@7800000 {
-                               label = "firmware";
-                               reg = <0x7800000 0x800000>;
-                               read-only;
-                       };
-               };
-
-               nvram@3,0 {
-                       device_type = "nvram";
-                       compatible = "simtek,stk14ca8";
-                       reg = <0x3 0x0 0x20000>;
-               };
-
-               fpga@4,0 {
-                       compatible = "gef,fpga-regs";
-                       reg = <0x4 0x0 0x40>;
-               };
-
-               wdt@4,2000 {
-                       compatible = "gef,sbc310-fpga-wdt", "gef,fpga-wdt-1.00",
-                               "gef,fpga-wdt";
-                       reg = <0x4 0x2000 0x8>;
-                       interrupts = <0x1a 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-/*
-               wdt@4,2010 {
-                       compatible = "gef,sbc310-fpga-wdt", "gef,fpga-wdt-1.00",
-                               "gef,fpga-wdt";
-                       reg = <0x4 0x2010 0x8>;
-                       interrupts = <0x1b 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-*/
-               gef_pic: pic@4,4000 {
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       compatible = "gef,sbc310-fpga-pic", "gef,fpga-pic";
-                       reg = <0x4 0x4000 0x20>;
-                       interrupts = <0x8
-                                     0x9>;
-                       interrupt-parent = <&mpic>;
-
-               };
-               gef_gpio: gpio@4,8000 {
-                       #gpio-cells = <2>;
-                       compatible = "gef,sbc310-gpio";
-                       reg = <0x4 0x8000 0x24>;
-                       gpio-controller;
-               };
-       };
-
-       soc@fef00000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
-               device_type = "soc";
-               compatible = "fsl,mpc8641-soc", "simple-bus";
-               ranges = <0x0 0xfef00000 0x00100000>;
-               bus-frequency = <33333333>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c1: i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-
-                       rtc@51 {
-                               compatible = "epson,rx8581";
-                               reg = <0x00000051>;
-                       };
-               };
-
-               i2c2: i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-
-                       hwmon@48 {
-                               compatible = "national,lm92";
-                               reg = <0x48>;
-                       };
-
-                       hwmon@4c {
-                               compatible = "adi,adt7461";
-                               reg = <0x4c>;
-                       };
-
-                       eti@6b {
-                               compatible = "dallas,ds1682";
-                               reg = <0x6b>;
-                       };
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30  2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@0 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x9 0x4>;
-                                       reg = <1>;
-                               };
-                               phy2: ethernet-phy@2 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x8 0x4>;
-                                       reg = <3>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x2a 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x1c 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       clock-frequency = <0>;
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-               };
-
-               msi@41600 {
-                       compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
-                       reg = <0x41600 0x80>;
-                       msi-available-ranges = <0 0x100>;
-                       interrupts = <
-                               0xe0 0
-                               0xe1 0
-                               0xe2 0
-                               0xe3 0
-                               0xe4 0
-                               0xe5 0
-                               0xe6 0
-                               0xe7 0>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@fef08000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xfef08000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
-                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <0x18 0x2>;
-               interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
-               interrupt-map = <
-                       0x0000 0x0 0x0 0x1 &mpic 0x0 0x2
-                       0x0000 0x0 0x0 0x2 &mpic 0x1 0x2
-                       0x0000 0x0 0x0 0x3 &mpic 0x2 0x2
-                       0x0000 0x0 0x0 0x4 &mpic 0x3 0x2
-               >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0x80000000
-                                 0x02000000 0x0 0x80000000
-                                 0x0 0x40000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00400000>;
-               };
-       };
-
-       pci1: pcie@fef09000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xfef09000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xfe400000 0x0 0x00400000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <0x19 0x2>;
-               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-               interrupt-map = <
-                       0x0000 0x0 0x0 0x1 &mpic 0x4 0x2
-                       0x0000 0x0 0x0 0x2 &mpic 0x5 0x2
-                       0x0000 0x0 0x0 0x3 &mpic 0x6 0x2
-                       0x0000 0x0 0x0 0x4 &mpic 0x7 0x2
-                       >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0xc0000000
-                                 0x02000000 0x0 0xc0000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00400000>;
-               };
-       };
-};
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
deleted file mode 100644 (file)
index 5db3399..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * GE SBC610 Device Tree Source
- *
- * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Based on: SBS CM6 Device Tree Source
- * Copyright 2007 SBS Technologies GmbH & Co. KG
- * And: mpc8641_hpcn.dts (MPC8641 HPCN Device Tree Source)
- * Copyright 2006 Freescale Semiconductor Inc.
- */
-
-/*
- * Compiled with dtc -I dts -O dtb -o gef_sbc610.dtb gef_sbc610.dts
- */
-
-/dts-v1/;
-
-/ {
-       model = "GEF_SBC610";
-       compatible = "gef,sbc610";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x40000000>; // set by uboot
-       };
-
-       localbus@fef05000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0xfef05000 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
-                         1 0 0xe8000000 0x08000000     // Paged Flash 0
-                         2 0 0xe0000000 0x08000000     // Paged Flash 1
-                         3 0 0xfc100000 0x00020000     // NVRAM
-                         4 0 0xfc000000 0x00008000     // FPGA
-                         5 0 0xfc008000 0x00008000     // AFIX FPGA
-                         6 0 0xfd000000 0x00800000     // IO FPGA (8-bit)
-                         7 0 0xfd800000 0x00800000>;   // IO FPGA (32-bit)
-
-               /* flash@0,0 is a mirror of part of the memory in flash@1,0
-               flash@0,0 {
-                       compatible = "gef,sbc610-firmware-mirror", "cfi-flash";
-                       reg = <0x0 0x0 0x1000000>;
-                       bank-width = <4>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "firmware";
-                               reg = <0x0 0x1000000>;
-                               read-only;
-                       };
-               };
-               */
-
-               flash@1,0 {
-                       compatible = "gef,sbc610-paged-flash", "cfi-flash";
-                       reg = <0x1 0x0 0x8000000>;
-                       bank-width = <4>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "user";
-                               reg = <0x0 0x7800000>;
-                       };
-                       partition@7800000 {
-                               label = "firmware";
-                               reg = <0x7800000 0x800000>;
-                               read-only;
-                       };
-               };
-
-               nvram@3,0 {
-                       device_type = "nvram";
-                       compatible = "simtek,stk14ca8";
-                       reg = <0x3 0x0 0x20000>;
-               };
-
-               fpga@4,0 {
-                       compatible = "gef,fpga-regs";
-                       reg = <0x4 0x0 0x40>;
-               };
-
-               wdt@4,2000 {
-                       compatible = "gef,fpga-wdt";
-                       reg = <0x4 0x2000 0x8>;
-                       interrupts = <0x1a 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-               /* Second watchdog available, driver currently supports one.
-               wdt@4,2010 {
-                       compatible = "gef,fpga-wdt";
-                       reg = <0x4 0x2010 0x8>;
-                       interrupts = <0x1b 0x4>;
-                       interrupt-parent = <&gef_pic>;
-               };
-               */
-               gef_pic: pic@4,4000 {
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       compatible = "gef,fpga-pic";
-                       reg = <0x4 0x4000 0x20>;
-                       interrupts = <0x8
-                                     0x9>;
-                       interrupt-parent = <&mpic>;
-
-               };
-               gef_gpio: gpio@7,14000 {
-                       #gpio-cells = <2>;
-                       compatible = "gef,sbc610-gpio";
-                       reg = <0x7 0x14000 0x24>;
-                       gpio-controller;
-               };
-       };
-
-       soc@fef00000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               #interrupt-cells = <2>;
-               device_type = "soc";
-               compatible = "simple-bus";
-               ranges = <0x0 0xfef00000 0x00100000>;
-               bus-frequency = <33333333>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c1: i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-
-                       hwmon@48 {
-                               compatible = "national,lm92";
-                               reg = <0x48>;
-                       };
-
-                       hwmon@4c {
-                               compatible = "adi,adt7461";
-                               reg = <0x4c>;
-                       };
-
-                       rtc@51 {
-                               compatible = "epson,rx8581";
-                               reg = <0x00000051>;
-                       };
-
-                       eti@6b {
-                               compatible = "dallas,ds1682";
-                               reg = <0x6b>;
-                       };
-               };
-
-               i2c2: i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                          "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30  2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@0 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x9 0x4>;
-                                       reg = <1>;
-                               };
-                               phy2: ethernet-phy@2 {
-                                       interrupt-parent = <&gef_pic>;
-                                       interrupts = <0x8 0x4>;
-                                       reg = <3>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "gmii";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x2a 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <0x1c 0x2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       clock-frequency = <0>;
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-               };
-
-               msi@41600 {
-                       compatible = "fsl,mpc8641-msi", "fsl,mpic-msi";
-                       reg = <0x41600 0x80>;
-                       msi-available-ranges = <0 0x100>;
-                       interrupts = <
-                               0xe0 0
-                               0xe1 0
-                               0xe2 0
-                               0xe3 0
-                               0xe4 0
-                               0xe5 0
-                               0xe6 0
-                               0xe7 0>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@fef08000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xfef08000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x40000000
-                         0x01000000 0x0 0x00000000 0xfe000000 0x0 0x00400000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <0x18 0x2>;
-               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-               interrupt-map = <
-                       0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
-                       0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
-                       0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
-                       0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
-               >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0x80000000
-                                 0x02000000 0x0 0x80000000
-                                 0x0 0x40000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00400000>;
-               };
-       };
-};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
deleted file mode 100644 (file)
index 1c03060..0000000
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * MPC8641 HPCN Device Tree Source
- *
- * Copyright 2006 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-/dts-v1/;
-
-/ {
-       model = "MPC8641HPCN";
-       compatible = "fsl,mpc8641hpcn";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               ethernet2 = &enet2;
-               ethernet3 = &enet3;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-               pci1 = &pci1;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;
-                       i-cache-line-size = <32>;
-                       d-cache-size = <32768>;         // L1
-                       i-cache-size = <32768>;         // L1
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;
-                       i-cache-line-size = <32>;
-                       d-cache-size = <32768>;
-                       i-cache-size = <32768>;
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x00000000 0x40000000>;  // 1G at 0x0
-       };
-
-       localbus@ffe05000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0xffe05000 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xef800000 0x00800000
-                         2 0 0xffdf8000 0x00008000
-                         3 0 0xffdf0000 0x00008000>;
-
-               flash@0,0 {
-                       compatible = "cfi-flash";
-                       reg = <0 0 0x00800000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "kernel";
-                               reg = <0x00000000 0x00300000>;
-                       };
-                       partition@300000 {
-                               label = "firmware b";
-                               reg = <0x00300000 0x00100000>;
-                               read-only;
-                       };
-                       partition@400000 {
-                               label = "fs";
-                               reg = <0x00400000 0x00300000>;
-                       };
-                       partition@700000 {
-                               label = "firmware a";
-                               reg = <0x00700000 0x00100000>;
-                               read-only;
-                       };
-               };
-       };
-
-       soc8641@ffe00000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               device_type = "soc";
-               compatible = "simple-bus";
-               ranges = <0x00000000 0xffe00000 0x00100000>;
-               bus-frequency = <0>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <1>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30  2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@0 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <0>;
-                               };
-                               phy1: ethernet-phy@1 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <1>;
-                               };
-                               phy2: ethernet-phy@2 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <2>;
-                               };
-                               phy3: ethernet-phy@3 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <3>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <1>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x25000 0x1000>;
-                       ranges = <0x0 0x25000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <35 2 36 2 40 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi1>;
-                       phy-handle = <&phy1>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi1: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-               
-               enet2: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet3: ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <3>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x27000 0x1000>;
-                       ranges = <0x0 0x27000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <37 2 38 2 39 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi3>;
-                       phy-handle = <&phy3>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi3: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <42 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <28 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-               };
-
-               rmu: rmu@d3000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,srio-rmu";
-                       reg = <0xd3000 0x500>;
-                       ranges = <0x0 0xd3000 0x500>;
-
-                       message-unit@0 {
-                               compatible = "fsl,srio-msg-unit";
-                               reg = <0x0 0x100>;
-                               interrupts = <
-                                       53 2 /* msg1_tx_irq */
-                                       54 2>;/* msg1_rx_irq */
-                       };
-                       message-unit@100 {
-                               compatible = "fsl,srio-msg-unit";
-                               reg = <0x100 0x100>;
-                               interrupts = <
-                                       55 2  /* msg2_tx_irq */
-                                       56 2>;/* msg2_rx_irq */
-                       };
-                       doorbell-unit@400 {
-                               compatible = "fsl,srio-dbell-unit";
-                               reg = <0x400 0x80>;
-                               interrupts = <
-                                       49 2  /* bell_outb_irq */
-                                       50 2>;/* bell_inb_irq */
-                       };
-                       port-write-unit@4e0 {
-                               compatible = "fsl,srio-port-write-unit";
-                               reg = <0x4e0 0x20>;
-                               interrupts = <48 2>;
-                       };
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@ffe08000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xffe08000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xffc00000 0x0 0x00010000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <24 2>;
-               interrupt-map-mask = <0xff00 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x11 func 0 - PCI slot 1 */
-                       0x8800 0 0 1 &mpic 2 1
-                       0x8800 0 0 2 &mpic 3 1
-                       0x8800 0 0 3 &mpic 4 1
-                       0x8800 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 1 - PCI slot 1 */
-                       0x8900 0 0 1 &mpic 2 1
-                       0x8900 0 0 2 &mpic 3 1
-                       0x8900 0 0 3 &mpic 4 1
-                       0x8900 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 2 - PCI slot 1 */
-                       0x8a00 0 0 1 &mpic 2 1
-                       0x8a00 0 0 2 &mpic 3 1
-                       0x8a00 0 0 3 &mpic 4 1
-                       0x8a00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 3 - PCI slot 1 */
-                       0x8b00 0 0 1 &mpic 2 1
-                       0x8b00 0 0 2 &mpic 3 1
-                       0x8b00 0 0 3 &mpic 4 1
-                       0x8b00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 4 - PCI slot 1 */
-                       0x8c00 0 0 1 &mpic 2 1
-                       0x8c00 0 0 2 &mpic 3 1
-                       0x8c00 0 0 3 &mpic 4 1
-                       0x8c00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 5 - PCI slot 1 */
-                       0x8d00 0 0 1 &mpic 2 1
-                       0x8d00 0 0 2 &mpic 3 1
-                       0x8d00 0 0 3 &mpic 4 1
-                       0x8d00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 6 - PCI slot 1 */
-                       0x8e00 0 0 1 &mpic 2 1
-                       0x8e00 0 0 2 &mpic 3 1
-                       0x8e00 0 0 3 &mpic 4 1
-                       0x8e00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 7 - PCI slot 1 */
-                       0x8f00 0 0 1 &mpic 2 1
-                       0x8f00 0 0 2 &mpic 3 1
-                       0x8f00 0 0 3 &mpic 4 1
-                       0x8f00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x12 func 0 - PCI slot 2 */
-                       0x9000 0 0 1 &mpic 3 1
-                       0x9000 0 0 2 &mpic 4 1
-                       0x9000 0 0 3 &mpic 1 1
-                       0x9000 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 1 - PCI slot 2 */
-                       0x9100 0 0 1 &mpic 3 1
-                       0x9100 0 0 2 &mpic 4 1
-                       0x9100 0 0 3 &mpic 1 1
-                       0x9100 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 2 - PCI slot 2 */
-                       0x9200 0 0 1 &mpic 3 1
-                       0x9200 0 0 2 &mpic 4 1
-                       0x9200 0 0 3 &mpic 1 1
-                       0x9200 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 3 - PCI slot 2 */
-                       0x9300 0 0 1 &mpic 3 1
-                       0x9300 0 0 2 &mpic 4 1
-                       0x9300 0 0 3 &mpic 1 1
-                       0x9300 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 4 - PCI slot 2 */
-                       0x9400 0 0 1 &mpic 3 1
-                       0x9400 0 0 2 &mpic 4 1
-                       0x9400 0 0 3 &mpic 1 1
-                       0x9400 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 5 - PCI slot 2 */
-                       0x9500 0 0 1 &mpic 3 1
-                       0x9500 0 0 2 &mpic 4 1
-                       0x9500 0 0 3 &mpic 1 1
-                       0x9500 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 6 - PCI slot 2 */
-                       0x9600 0 0 1 &mpic 3 1
-                       0x9600 0 0 2 &mpic 4 1
-                       0x9600 0 0 3 &mpic 1 1
-                       0x9600 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 7 - PCI slot 2 */
-                       0x9700 0 0 1 &mpic 3 1
-                       0x9700 0 0 2 &mpic 4 1
-                       0x9700 0 0 3 &mpic 1 1
-                       0x9700 0 0 4 &mpic 2 1
-
-                       // IDSEL 0x1c  USB
-                       0xe000 0 0 1 &i8259 12 2
-                       0xe100 0 0 2 &i8259 9 2
-                       0xe200 0 0 3 &i8259 10 2
-                       0xe300 0 0 4 &i8259 11 2
-
-                       // IDSEL 0x1d  Audio
-                       0xe800 0 0 1 &i8259 6 2
-
-                       // IDSEL 0x1e Legacy
-                       0xf000 0 0 1 &i8259 7 2
-                       0xf100 0 0 1 &i8259 7 2
-
-                       // IDSEL 0x1f IDE/SATA
-                       0xf800 0 0 1 &i8259 14 2
-                       0xf900 0 0 1 &i8259 5 2
-                       >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0x80000000
-                                 0x02000000 0x0 0x80000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00010000>;
-                       uli1575@0 {
-                               reg = <0 0 0 0 0>;
-                               #size-cells = <2>;
-                               #address-cells = <3>;
-                               ranges = <0x02000000 0x0 0x80000000
-                                         0x02000000 0x0 0x80000000
-                                         0x0 0x20000000
-                                         0x01000000 0x0 0x00000000
-                                         0x01000000 0x0 0x00000000
-                                         0x0 0x00010000>;
-                               isa@1e {
-                                       device_type = "isa";
-                                       #interrupt-cells = <2>;
-                                       #size-cells = <1>;
-                                       #address-cells = <2>;
-                                       reg = <0xf000 0 0 0 0>;
-                                       ranges = <1 0 0x01000000 0 0
-                                                 0x00001000>;
-                                       interrupt-parent = <&i8259>;
-
-                                       i8259: interrupt-controller@20 {
-                                               reg = <1 0x20 2
-                                                      1 0xa0 2
-                                                      1 0x4d0 2>;
-                                               interrupt-controller;
-                                               device_type = "interrupt-controller";
-                                               #address-cells = <0>;
-                                               #interrupt-cells = <2>;
-                                               compatible = "chrp,iic";
-                                               interrupts = <9 2>;
-                                               interrupt-parent = <&mpic>;
-                                       };
-
-                                       i8042@60 {
-                                               #size-cells = <0>;
-                                               #address-cells = <1>;
-                                               reg = <1 0x60 1 1 0x64 1>;
-                                               interrupts = <1 3 12 3>;
-                                               interrupt-parent =
-                                                       <&i8259>;
-
-                                               keyboard@0 {
-                                                       reg = <0>;
-                                                       compatible = "pnpPNP,303";
-                                               };
-
-                                               mouse@1 {
-                                                       reg = <1>;
-                                                       compatible = "pnpPNP,f03";
-                                               };
-                                       };
-
-                                       rtc@70 {
-                                               compatible =
-                                                       "pnpPNP,b00";
-                                               reg = <1 0x70 2>;
-                                       };
-
-                                       gpio@400 {
-                                               reg = <1 0x400 0x80>;
-                                       };
-                               };
-                       };
-               };
-
-       };
-
-       pci1: pcie@ffe09000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xffe09000 0x1000>;
-               bus-range = <0 0xff>;
-               ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xffc10000 0x0 0x00010000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <25 2>;
-               interrupt-map-mask = <0xf800 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0x0000 0 0 1 &mpic 4 1
-                       0x0000 0 0 2 &mpic 5 1
-                       0x0000 0 0 3 &mpic 6 1
-                       0x0000 0 0 4 &mpic 7 1
-                       >;
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0xa0000000
-                                 0x02000000 0x0 0xa0000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00010000>;
-               };
-       };
-/*
- * Only one of Rapid IO or PCI can be present due to HW limitations and
- * due to the fact that the 2 now share address space in the new memory
- * map.  The most likely case is that we have PCI, so comment out the
- * rapidio node.  Leave it here for reference.
-
-       rapidio@ffec0000 {
-               reg = <0xffec0000 0x11000>;
-               compatible = "fsl,srio";
-               interrupt-parent = <&mpic>;
-               interrupts = <48 2>;
-               #address-cells = <2>;
-               #size-cells = <2>;
-               fsl,srio-rmu-handle = <&rmu>;
-               ranges;
-
-               port1 {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       cell-index = <1>;
-                       ranges = <0 0 0x80000000 0 0x20000000>;
-               };
-       };
-*/
-
-};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts b/arch/powerpc/boot/dts/mpc8641_hpcn_36b.dts
deleted file mode 100644 (file)
index bb575e2..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * MPC8641 HPCN Device Tree Source
- *
- * Copyright 2008-2009 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-/dts-v1/;
-
-/ {
-       model = "MPC8641HPCN";
-       compatible = "fsl,mpc8641hpcn";
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               ethernet2 = &enet2;
-               ethernet3 = &enet3;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-               pci1 = &pci1;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // 33 MHz, from uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;       // 32 bytes
-                       i-cache-line-size = <32>;       // 32 bytes
-                       d-cache-size = <32768>;         // L1, 32K
-                       i-cache-size = <32768>;         // L1, 32K
-                       timebase-frequency = <0>;       // 33 MHz, from uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x0 0x00000000 0x0 0x40000000>;  // 1G at 0x0
-       };
-
-       localbus@fffe05000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0x0f 0xffe05000 0x0 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xf 0xef800000 0x00800000
-                         2 0 0xf 0xffdf8000 0x00008000
-                         3 0 0xf 0xffdf0000 0x00008000>;
-
-               flash@0,0 {
-                       compatible = "cfi-flash";
-                       reg = <0 0 0x00800000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "kernel";
-                               reg = <0x00000000 0x00300000>;
-                       };
-                       partition@300000 {
-                               label = "firmware b";
-                               reg = <0x00300000 0x00100000>;
-                               read-only;
-                       };
-                       partition@400000 {
-                               label = "fs";
-                               reg = <0x00400000 0x00300000>;
-                       };
-                       partition@700000 {
-                               label = "firmware a";
-                               reg = <0x00700000 0x00100000>;
-                               read-only;
-                       };
-               };
-       };
-
-       soc8641@fffe00000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               device_type = "soc";
-               compatible = "simple-bus";
-               ranges = <0x00000000 0x0f 0xffe00000 0x00100000>;
-               bus-frequency = <0>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <1>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30 2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@0 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <0>;
-                               };
-                               phy1: ethernet-phy@1 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <1>;
-                               };
-                               phy2: ethernet-phy@2 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <2>;
-                               };
-                               phy3: ethernet-phy@3 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
-                                       reg = <3>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <1>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x25000 0x1000>;
-                       ranges = <0x0 0x25000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <35 2 36 2 40 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi1>;
-                       phy-handle = <&phy1>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi1: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet2: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet3: ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <3>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x27000 0x1000>;
-                       ranges = <0x0 0x27000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <37 2 38 2 39 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi3>;
-                       phy-handle = <&phy3>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi3: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <42 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <28 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@fffe08000 {
-               cell-index = <0>;
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0x0f 0xffe08000 0x0 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0xe0000000 0x0c 0x00000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0x0f 0xffc00000 0x0 0x00010000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <24 2>;
-               interrupt-map-mask = <0xff00 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x11 func 0 - PCI slot 1 */
-                       0x8800 0 0 1 &mpic 2 1
-                       0x8800 0 0 2 &mpic 3 1
-                       0x8800 0 0 3 &mpic 4 1
-                       0x8800 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 1 - PCI slot 1 */
-                       0x8900 0 0 1 &mpic 2 1
-                       0x8900 0 0 2 &mpic 3 1
-                       0x8900 0 0 3 &mpic 4 1
-                       0x8900 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 2 - PCI slot 1 */
-                       0x8a00 0 0 1 &mpic 2 1
-                       0x8a00 0 0 2 &mpic 3 1
-                       0x8a00 0 0 3 &mpic 4 1
-                       0x8a00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 3 - PCI slot 1 */
-                       0x8b00 0 0 1 &mpic 2 1
-                       0x8b00 0 0 2 &mpic 3 1
-                       0x8b00 0 0 3 &mpic 4 1
-                       0x8b00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 4 - PCI slot 1 */
-                       0x8c00 0 0 1 &mpic 2 1
-                       0x8c00 0 0 2 &mpic 3 1
-                       0x8c00 0 0 3 &mpic 4 1
-                       0x8c00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 5 - PCI slot 1 */
-                       0x8d00 0 0 1 &mpic 2 1
-                       0x8d00 0 0 2 &mpic 3 1
-                       0x8d00 0 0 3 &mpic 4 1
-                       0x8d00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 6 - PCI slot 1 */
-                       0x8e00 0 0 1 &mpic 2 1
-                       0x8e00 0 0 2 &mpic 3 1
-                       0x8e00 0 0 3 &mpic 4 1
-                       0x8e00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x11 func 7 - PCI slot 1 */
-                       0x8f00 0 0 1 &mpic 2 1
-                       0x8f00 0 0 2 &mpic 3 1
-                       0x8f00 0 0 3 &mpic 4 1
-                       0x8f00 0 0 4 &mpic 1 1
-
-                       /* IDSEL 0x12 func 0 - PCI slot 2 */
-                       0x9000 0 0 1 &mpic 3 1
-                       0x9000 0 0 2 &mpic 4 1
-                       0x9000 0 0 3 &mpic 1 1
-                       0x9000 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 1 - PCI slot 2 */
-                       0x9100 0 0 1 &mpic 3 1
-                       0x9100 0 0 2 &mpic 4 1
-                       0x9100 0 0 3 &mpic 1 1
-                       0x9100 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 2 - PCI slot 2 */
-                       0x9200 0 0 1 &mpic 3 1
-                       0x9200 0 0 2 &mpic 4 1
-                       0x9200 0 0 3 &mpic 1 1
-                       0x9200 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 3 - PCI slot 2 */
-                       0x9300 0 0 1 &mpic 3 1
-                       0x9300 0 0 2 &mpic 4 1
-                       0x9300 0 0 3 &mpic 1 1
-                       0x9300 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 4 - PCI slot 2 */
-                       0x9400 0 0 1 &mpic 3 1
-                       0x9400 0 0 2 &mpic 4 1
-                       0x9400 0 0 3 &mpic 1 1
-                       0x9400 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 5 - PCI slot 2 */
-                       0x9500 0 0 1 &mpic 3 1
-                       0x9500 0 0 2 &mpic 4 1
-                       0x9500 0 0 3 &mpic 1 1
-                       0x9500 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 6 - PCI slot 2 */
-                       0x9600 0 0 1 &mpic 3 1
-                       0x9600 0 0 2 &mpic 4 1
-                       0x9600 0 0 3 &mpic 1 1
-                       0x9600 0 0 4 &mpic 2 1
-
-                       /* IDSEL 0x12 func 7 - PCI slot 2 */
-                       0x9700 0 0 1 &mpic 3 1
-                       0x9700 0 0 2 &mpic 4 1
-                       0x9700 0 0 3 &mpic 1 1
-                       0x9700 0 0 4 &mpic 2 1
-
-                       // IDSEL 0x1c  USB
-                       0xe000 0 0 1 &i8259 12 2
-                       0xe100 0 0 2 &i8259 9 2
-                       0xe200 0 0 3 &i8259 10 2
-                       0xe300 0 0 4 &i8259 11 2
-
-                       // IDSEL 0x1d  Audio
-                       0xe800 0 0 1 &i8259 6 2
-
-                       // IDSEL 0x1e Legacy
-                       0xf000 0 0 1 &i8259 7 2
-                       0xf100 0 0 1 &i8259 7 2
-
-                       // IDSEL 0x1f IDE/SATA
-                       0xf800 0 0 1 &i8259 14 2
-                       0xf900 0 0 1 &i8259 5 2
-                       >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0xe0000000
-                                 0x02000000 0x0 0xe0000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00010000>;
-                       uli1575@0 {
-                               reg = <0 0 0 0 0>;
-                               #size-cells = <2>;
-                               #address-cells = <3>;
-                               ranges = <0x02000000 0x0 0xe0000000
-                                         0x02000000 0x0 0xe0000000
-                                         0x0 0x20000000
-                                         0x01000000 0x0 0x00000000
-                                         0x01000000 0x0 0x00000000
-                                         0x0 0x00010000>;
-                               isa@1e {
-                                       device_type = "isa";
-                                       #interrupt-cells = <2>;
-                                       #size-cells = <1>;
-                                       #address-cells = <2>;
-                                       reg = <0xf000 0 0 0 0>;
-                                       ranges = <1 0 0x01000000 0 0
-                                                 0x00001000>;
-                                       interrupt-parent = <&i8259>;
-
-                                       i8259: interrupt-controller@20 {
-                                               reg = <1 0x20 2
-                                                      1 0xa0 2
-                                                      1 0x4d0 2>;
-                                               interrupt-controller;
-                                               device_type = "interrupt-controller";
-                                               #address-cells = <0>;
-                                               #interrupt-cells = <2>;
-                                               compatible = "chrp,iic";
-                                               interrupts = <9 2>;
-                                               interrupt-parent = <&mpic>;
-                                       };
-
-                                       i8042@60 {
-                                               #size-cells = <0>;
-                                               #address-cells = <1>;
-                                               reg = <1 0x60 1 1 0x64 1>;
-                                               interrupts = <1 3 12 3>;
-                                               interrupt-parent =
-                                                       <&i8259>;
-
-                                               keyboard@0 {
-                                                       reg = <0>;
-                                                       compatible = "pnpPNP,303";
-                                               };
-
-                                               mouse@1 {
-                                                       reg = <1>;
-                                                       compatible = "pnpPNP,f03";
-                                               };
-                                       };
-
-                                       rtc@70 {
-                                               compatible =
-                                                       "pnpPNP,b00";
-                                               reg = <1 0x70 2>;
-                                       };
-
-                                       gpio@400 {
-                                               reg = <1 0x400 0x80>;
-                                       };
-                               };
-                       };
-               };
-
-       };
-
-       pci1: pcie@fffe09000 {
-               cell-index = <1>;
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0x0f 0xffe09000 0x0 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0xe0000000 0x0c 0x20000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0x0f 0xffc10000 0x0 0x00010000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <25 2>;
-               interrupt-map-mask = <0xf800 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0x0000 0 0 1 &mpic 4 1
-                       0x0000 0 0 2 &mpic 5 1
-                       0x0000 0 0 3 &mpic 6 1
-                       0x0000 0 0 4 &mpic 7 1
-                       >;
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0xe0000000
-                                 0x02000000 0x0 0xe0000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00010000>;
-               };
-       };
-};
diff --git a/arch/powerpc/boot/dts/sbc8641d.dts b/arch/powerpc/boot/dts/sbc8641d.dts
deleted file mode 100644 (file)
index 68f0ed7..0000000
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * SBC8641D Device Tree Source
- *
- * Copyright 2008 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-/dts-v1/;
-
-/ {
-       model = "SBC8641D";
-       compatible = "wind,sbc8641";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               ethernet2 = &enet2;
-               ethernet3 = &enet3;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-               pci1 = &pci1;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8641@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <32>;
-                       i-cache-line-size = <32>;
-                       d-cache-size = <32768>;         // L1
-                       i-cache-size = <32768>;         // L1
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-               PowerPC,8641@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       d-cache-line-size = <32>;
-                       i-cache-line-size = <32>;
-                       d-cache-size = <32768>;
-                       i-cache-size = <32768>;
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;            // From uboot
-                       clock-frequency = <0>;          // From uboot
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x00000000 0x20000000>;  // 512M at 0x0
-       };
-
-       localbus@f8005000 {
-               #address-cells = <2>;
-               #size-cells = <1>;
-               compatible = "fsl,mpc8641-localbus", "simple-bus";
-               reg = <0xf8005000 0x1000>;
-               interrupts = <19 2>;
-               interrupt-parent = <&mpic>;
-
-               ranges = <0 0 0xff000000 0x01000000     // 16MB Boot flash
-                         1 0 0xf0000000 0x00010000     // 64KB EEPROM
-                         2 0 0xf1000000 0x00100000     // EPLD (1MB)
-                         3 0 0xe0000000 0x04000000     // 64MB LB SDRAM (CS3)
-                         4 0 0xe4000000 0x04000000     // 64MB LB SDRAM (CS4)
-                         6 0 0xf4000000 0x00100000     // LCD display (1MB)
-                         7 0 0xe8000000 0x04000000>;   // 64MB OneNAND
-
-               flash@0,0 {
-                       compatible = "cfi-flash";
-                       reg = <0 0 0x01000000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       partition@0 {
-                               label = "dtb";
-                               reg = <0x00000000 0x00100000>;
-                               read-only;
-                       };
-                       partition@300000 {
-                               label = "kernel";
-                               reg = <0x00100000 0x00400000>;
-                               read-only;
-                       };
-                       partition@400000 {
-                               label = "fs";
-                               reg = <0x00500000 0x00a00000>;
-                       };
-                       partition@700000 {
-                               label = "firmware";
-                               reg = <0x00f00000 0x00100000>;
-                               read-only;
-                       };
-               };
-
-               epld@2,0 {
-                       compatible = "wrs,epld-localbus";
-                       #address-cells = <2>;
-                       #size-cells = <1>;
-                       reg = <2 0 0x100000>;
-                       ranges = <0 0 5 0 1     // User switches
-                                 1 0 5 1 1     // Board ID/Rev
-                                 3 0 5 3 1>;   // LEDs
-               };
-       };
-
-       soc@f8000000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               device_type = "soc";
-               compatible = "simple-bus";
-               ranges = <0x00000000 0xf8000000 0x00100000>;
-               bus-frequency = <0>;
-
-               mcm-law@0 {
-                       compatible = "fsl,mcm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <10>;
-               };
-
-               mcm@1000 {
-                       compatible = "fsl,mpc8641-mcm", "fsl,mcm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <1>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <43 2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8641-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8641-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <29 2 30  2 34 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-
-                               phy0: ethernet-phy@1f {
-                                       reg = <0x1f>;
-                               };
-                               phy1: ethernet-phy@0 {
-                                       reg = <0>;
-                               };
-                               phy2: ethernet-phy@1 {
-                                       reg = <1>;
-                               };
-                               phy3: ethernet-phy@2 {
-                                       reg = <2>;
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <1>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x25000 0x1000>;
-                       ranges = <0x0 0x25000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <35 2 36 2 40 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi1>;
-                       phy-handle = <&phy1>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi1: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet2: ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <2>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x26000 0x1000>;
-                       ranges = <0x0 0x26000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <31 2 32 2 33 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi2>;
-                       phy-handle = <&phy2>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi2: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet3: ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <3>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x27000 0x1000>;
-                       ranges = <0x0 0x27000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <37 2 38 2 39 2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi3>;
-                       phy-handle = <&phy3>;
-                       phy-connection-type = "rgmii-id";
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi3: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               serial0: serial@4500 {
-                       cell-index = <0>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4500 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <42 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               serial1: serial@4600 {
-                       cell-index = <1>;
-                       device_type = "serial";
-                       compatible = "fsl,ns16550", "ns16550";
-                       reg = <0x4600 0x100>;
-                       clock-frequency = <0>;
-                       interrupts = <28 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               mpic: pic@40000 {
-                       clock-frequency = <0>;
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       reg = <0x40000 0x40000>;
-                       compatible = "chrp,open-pic";
-                       device_type = "open-pic";
-                       big-endian;
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8641-guts";
-                       reg = <0xe0000 0x1000>;
-                       fsl,has-rstcr;
-               };
-       };
-
-       pci0: pcie@f8008000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xf8008000 0x1000>;
-               bus-range = <0x0 0xff>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <24 2>;
-               interrupt-map-mask = <0xff00 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0x0000 0 0 1 &mpic 0 1
-                       0x0000 0 0 2 &mpic 1 1
-                       0x0000 0 0 3 &mpic 2 1
-                       0x0000 0 0 4 &mpic 3 1
-                       >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0x80000000
-                                 0x02000000 0x0 0x80000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00100000>;
-               };
-
-       };
-
-       pci1: pcie@f8009000 {
-               compatible = "fsl,mpc8641-pcie";
-               device_type = "pci";
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               reg = <0xf8009000 0x1000>;
-               bus-range = <0 0xff>;
-               ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
-               clock-frequency = <33333333>;
-               interrupt-parent = <&mpic>;
-               interrupts = <25 2>;
-               interrupt-map-mask = <0xf800 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0x0000 0 0 1 &mpic 4 1
-                       0x0000 0 0 2 &mpic 5 1
-                       0x0000 0 0 3 &mpic 6 1
-                       0x0000 0 0 4 &mpic 7 1
-                       >;
-
-               pcie@0 {
-                       reg = <0 0 0 0 0>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       device_type = "pci";
-                       ranges = <0x02000000 0x0 0xa0000000
-                                 0x02000000 0x0 0xa0000000
-                                 0x0 0x20000000
-
-                                 0x01000000 0x0 0x00000000
-                                 0x01000000 0x0 0x00000000
-                                 0x0 0x00100000>;
-               };
-       };
-};
index 433f450..d70517c 100644 (file)
@@ -239,5 +239,5 @@ struct external_reloc {
 #define DEFAULT_DATA_SECTION_ALIGNMENT 4
 #define DEFAULT_BSS_SECTION_ALIGNMENT 4
 #define DEFAULT_TEXT_SECTION_ALIGNMENT 4
-/* For new sections we havn't heard of before */
+/* For new sections we haven't heard of before */
 #define DEFAULT_SECTION_ALIGNMENT 4
index b73174c..bcc5902 100644 (file)
@@ -38,7 +38,7 @@
 
 BSS_STACK(4096);
 
-#define SPRN_PIR       0x11E   /* Processor Indentification Register */
+#define SPRN_PIR       0x11E   /* Processor Identification Register */
 #define USERDATA_LEN   256     /* Length of userdata passed in by PIBS */
 #define MAX_RANKS      0x4
 #define DDR3_MR0CF     0x80010011U
index 925ae43..303d207 100644 (file)
@@ -80,7 +80,7 @@ static void ibm_currituck_fixups(void)
        }
 }
 
-#define SPRN_PIR       0x11E   /* Processor Indentification Register */
+#define SPRN_PIR       0x11E   /* Processor Identification Register */
 void platform_init(void)
 {
        unsigned long end_of_ram, avail_ram;
index 329e710..733f8bf 100644 (file)
@@ -59,7 +59,7 @@ static void *iss_4xx_vmlinux_alloc(unsigned long size)
        return (void *)ibm4xx_memstart;
 }
 
-#define SPRN_PIR       0x11E   /* Processor Indentification Register */
+#define SPRN_PIR       0x11E   /* Processor Identification Register */
 void platform_init(void)
 {
        unsigned long end_of_ram = 0x08000000;
index 2a5fdcb..87fc15b 100644 (file)
@@ -35,7 +35,6 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_IDE=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_SPI_ATTRS=y
index 3be85c5..6f753a7 100644 (file)
@@ -34,7 +34,6 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_IDE=y
 CONFIG_NETDEVICES=y
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
index f66d16b..b451905 100644 (file)
@@ -31,8 +31,6 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=m
 CONFIG_SCSI=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_CHR_DEV_ST=m
diff --git a/arch/powerpc/configs/86xx-hw.config b/arch/powerpc/configs/86xx-hw.config
new file mode 100644 (file)
index 0000000..f91f889
--- /dev/null
@@ -0,0 +1,104 @@
+CONFIG_ATA=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BROADCOM_PHY=y
+# CONFIG_CARDBUS is not set
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_DS1682=y
+CONFIG_EEPROM_LEGACY=y
+CONFIG_GEF_WDT=y
+CONFIG_GIANFAR=y
+CONFIG_GPIO_GE_FPGA=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HW_RANDOM=y
+CONFIG_HZ_1000=y
+CONFIG_I2C_MPC=y
+CONFIG_I2C=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_TULIP=y
+CONFIG_NVRAM=y
+CONFIG_PATA_ALI=y
+CONFIG_PCCARD=y
+CONFIG_PCI_DEBUG=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PPC_CHRP is not set
+# CONFIG_PPC_PMAC is not set
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_RX8581=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_SIL24=y
+CONFIG_SATA_SIL=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM92=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SND_INTEL8X0=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND=y
+CONFIG_SOUND=y
+CONFIG_ULI526X=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB=y
+CONFIG_VITESSE_PHY=y
+CONFIG_VME_BUS=y
+CONFIG_VME_TSI148=y
+CONFIG_WATCHDOG=y
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+# CONFIG_YENTA_TOSHIBA is not set
+CONFIG_YENTA=y
diff --git a/arch/powerpc/configs/86xx-smp.config b/arch/powerpc/configs/86xx-smp.config
new file mode 100644 (file)
index 0000000..40ac38d
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_NR_CPUS=2
+CONFIG_SMP=y
diff --git a/arch/powerpc/configs/86xx/gef_ppc9a_defconfig b/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
deleted file mode 100644 (file)
index 9792a2c..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_GEF_PPC9A=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEASPM is not set
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_LOAD_CIS is not set
-# CONFIG_CARDBUS is not set
-CONFIG_YENTA=y
-# CONFIG_YENTA_O2 is not set
-# CONFIG_YENTA_RICOH is not set
-# CONFIG_YENTA_TOSHIBA is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-# CONFIG_INET_XFRM_MODE_BEET is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_DS1682=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_ATA=y
-CONFIG_SATA_SIL=y
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TUN=m
-CONFIG_GIANFAR=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_PCI is not set
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_HW_RANDOM=y
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MPC=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GE_FPGA=y
-CONFIG_SENSORS_LM90=y
-CONFIG_SENSORS_LM92=y
-CONFIG_WATCHDOG=y
-CONFIG_GEF_WDT=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_HCD_PPC_OF is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_INTF_PROC is not set
-CONFIG_RTC_DRV_RX8581=y
-CONFIG_STAGING=y
-CONFIG_VME_BUS=y
-CONFIG_VME_TSI148=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=850
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/configs/86xx/gef_sbc310_defconfig b/arch/powerpc/configs/86xx/gef_sbc310_defconfig
deleted file mode 100644 (file)
index cadc366..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_GEF_SBC310=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEASPM is not set
-CONFIG_PCCARD=y
-# CONFIG_PCMCIA_LOAD_CIS is not set
-# CONFIG_CARDBUS is not set
-CONFIG_YENTA=y
-# CONFIG_YENTA_O2 is not set
-# CONFIG_YENTA_RICOH is not set
-# CONFIG_YENTA_TOSHIBA is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-# CONFIG_INET_XFRM_MODE_BEET is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_DS1682=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_ATA=y
-CONFIG_SATA_SIL24=y
-# CONFIG_ATA_SFF is not set
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TUN=m
-CONFIG_GIANFAR=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_PCI is not set
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_HW_RANDOM=y
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MPC=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GE_FPGA=y
-CONFIG_SENSORS_LM90=y
-CONFIG_SENSORS_LM92=y
-CONFIG_WATCHDOG=y
-CONFIG_GEF_WDT=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_HCD_PPC_OF is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_INTF_PROC is not set
-CONFIG_RTC_DRV_RX8581=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=850
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
deleted file mode 100644 (file)
index 2aa7d97..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_GEF_SBC610=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEASPM is not set
-CONFIG_PCI_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-# CONFIG_INET_LRO is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-CONFIG_IP_SCTP=m
-CONFIG_TIPC=m
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_DS1682=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_ATA=y
-CONFIG_SATA_SIL=y
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TUN=m
-CONFIG_GIANFAR=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOATM=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_PCI is not set
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_HW_RANDOM=y
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MPC=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GE_FPGA=y
-CONFIG_SENSORS_LM90=y
-CONFIG_SENSORS_LM92=y
-CONFIG_WATCHDOG=y
-CONFIG_GEF_WDT=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_HCD_PPC_OF is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_INTF_PROC is not set
-CONFIG_RTC_DRV_RX8581=y
-CONFIG_STAGING=y
-CONFIG_VME_BUS=y
-CONFIG_VME_TSI148=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_DEBUG_INFO=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
deleted file mode 100644 (file)
index e32207d..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-# CONFIG_ELF_CORE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_LDM_PARTITION=y
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_MPC8610_HPCD=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_FORCE_MAX_ZONEORDER=12
-# CONFIG_SECCOMP is not set
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEASPM is not set
-CONFIG_PCI_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_FSL_ELBC=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_IDE=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_PATA_ALI=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_NET_TULIP=y
-CONFIG_ULI526X=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_MPC=y
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_FSL_DIU=y
-CONFIG_VGACON_SOFT_SCROLLBACK=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_POWERPC_SOC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NLS=y
-CONFIG_CRC_T10DIF=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_SHIRQ=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
deleted file mode 100644 (file)
index a36e11d..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_MPC8641_HPCN=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IP_SCTP=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_EEPROM_LEGACY=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_PATA_ALI=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_GIANFAR=y
-CONFIG_VITESSE_PHY=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_MPC=y
-# CONFIG_HWMON is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_INTEL8X0=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
-CONFIG_USB_STORAGE=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_ADFS_FS=m
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=y
-CONFIG_VXFS_FS=m
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_CRC_T10DIF=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig
deleted file mode 100644 (file)
index db79bde..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_SBC8641D=y
-CONFIG_PREEMPT=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEASPM is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=m
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-# CONFIG_INET_LRO is not set
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-CONFIG_IP_SCTP=m
-CONFIG_TIPC=m
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_PKTGEN=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_LE_BYTE_SWAP=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=m
-CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID10=y
-CONFIG_MD_MULTIPATH=y
-CONFIG_MD_FAULTY=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-CONFIG_DM_SNAPSHOT=y
-CONFIG_DM_MIRROR=y
-CONFIG_DM_ZERO=y
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_NETCONSOLE=y
-CONFIG_TUN=m
-CONFIG_GIANFAR=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOATM=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_PCI is not set
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_MPC=y
-CONFIG_WATCHDOG=y
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_MINIX_FS=m
-CONFIG_ROMFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_CIFS=m
-CONFIG_CIFS_XATTR=y
-CONFIG_CIFS_POSIX=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/mpc86xx_basic_defconfig b/arch/powerpc/configs/mpc86xx_basic_defconfig
new file mode 100644 (file)
index 0000000..33af5c5
--- /dev/null
@@ -0,0 +1,10 @@
+CONFIG_HIGHMEM=y
+CONFIG_KEXEC=y
+CONFIG_PPC_86xx=y
+CONFIG_PROC_KCORE=y
+CONFIG_GEF_PPC9A=y
+CONFIG_GEF_SBC310=y
+CONFIG_GEF_SBC610=y
+CONFIG_MPC8610_HPCD=y
+CONFIG_MPC8641_HPCN=y
+CONFIG_SBC8641D=y
diff --git a/arch/powerpc/configs/mpc86xx_defconfig b/arch/powerpc/configs/mpc86xx_defconfig
deleted file mode 100644 (file)
index a457256..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-# CONFIG_PPC_CHRP is not set
-# CONFIG_PPC_PMAC is not set
-CONFIG_PPC_86xx=y
-CONFIG_MPC8641_HPCN=y
-CONFIG_SBC8641D=y
-CONFIG_MPC8610_HPCD=y
-CONFIG_GEF_SBC610=y
-CONFIG_HIGHMEM=y
-CONFIG_HZ_1000=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IP_SCTP=m
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_EEPROM_LEGACY=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_PATA_ALI=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_GIANFAR=y
-CONFIG_VITESSE_PHY=y
-CONFIG_INPUT_FF_MEMLESS=m
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_MPC=y
-# CONFIG_HWMON is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# CONFIG_SND_SUPPORT_OLD_API is not set
-CONFIG_SND_INTEL8X0=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
-CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
-CONFIG_USB_STORAGE=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_NTFS_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_ADFS_FS=m
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=y
-CONFIG_VXFS_FS=m
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_CRC_T10DIF=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_HMAC=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
new file mode 100644 (file)
index 0000000..0450310
--- /dev/null
@@ -0,0 +1,313 @@
+CONFIG_PPC64=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2048
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_CGROUPS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_USER_NS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OPAL_PRD=y
+# CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_HZ_100=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PPC_TRANSACTIONAL_MEM=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_KEXEC=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_NUMA=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_KSM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_PPC_64K_PAGES=y
+CONFIG_PPC_SUBPAGE_PROT=y
+CONFIG_SCHED_SMT=y
+CONFIG_PM=y
+CONFIG_PCI_MSI=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_NET_IPIP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_POWERNV_FLASH=y
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_BLK_DEV_FD=m
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_VIRTIO_BLK=m
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_AMD74XX=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+CONFIG_BE2ISCSI=m
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_IPR=y
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+# CONFIG_ATA_SFF is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_UEVENT=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_NETCONSOLE=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
+CONFIG_VORTEX=y
+CONFIG_ACENIC=m
+CONFIG_ACENIC_OMIT_TIGON_I=y
+CONFIG_PCNET32=y
+CONFIG_TIGON3=y
+CONFIG_BNX2X=m
+CONFIG_CHELSIO_T1=m
+CONFIG_BE2NET=m
+CONFIG_S2IO=m
+CONFIG_E100=y
+CONFIG_E1000=y
+CONFIG_E1000E=y
+CONFIG_IXGB=m
+CONFIG_IXGBE=m
+CONFIG_MLX4_EN=m
+CONFIG_MYRI10GE=m
+CONFIG_QLGE=m
+CONFIG_NETXEN_NIC=m
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_MISC=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DEVICE_INTERFACE=y
+CONFIG_IPMI_POWERNV=y
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=1024
+CONFIG_DRM=y
+CONFIG_DRM_AST=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_OF=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_IBM_GXT4500=y
+CONFIG_LCD_PLATFORM=m
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_LOGO=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_MON=m
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_POWERNV=m
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_CXGB3=m
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_CM=y
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_ISER=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GENERIC=y
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_REISERFS_FS=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_OVERLAY_FS=m
+CONFIG_ISO9660_FS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_PSTORE=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CODE_PATCHING_SELFTEST=y
+CONFIG_FTR_FIXUP_SELFTEST=y
+CONFIG_MSI_BITMAP_SELFTEST=y
+CONFIG_XMON=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_DEV_NX=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=m
index 5dc6bce..bc6ff43 100644 (file)
@@ -61,7 +61,7 @@
  * via bl/blr. It expects that caller has pre-xored input data with first
  * 4 words of encryption key into rD0-rD3. Pointer/counter registers must
  * have also been set up before (rT0, rKP, CTR). Output is stored in rD0-rD3
- * and rW0-rW3 and caller must execute a final xor on the ouput registers.
+ * and rW0-rW3 and caller must execute a final xor on the output registers.
  * All working registers rD0-rD3 & rW0-rW7 are overwritten during processing.
  *
  */
@@ -209,7 +209,7 @@ ppc_encrypt_block_loop:
  * via bl/blr. It expects that caller has pre-xored input data with first
  * 4 words of encryption key into rD0-rD3. Pointer/counter registers must
  * have also been set up before (rT0, rKP, CTR). Output is stored in rD0-rD3
- * and rW0-rW3 and caller must execute a final xor on the ouput registers.
+ * and rW0-rW3 and caller must execute a final xor on the output registers.
  * All working registers rD0-rD3 & rW0-rW7 are overwritten during processing.
  *
  */
index ab11319..748fc00 100644 (file)
@@ -33,7 +33,7 @@
  * 16 byte block block or 25 cycles per byte. Thus 768 bytes of input data
  * will need an estimated maximum of 20,000 cycles. Headroom for cache misses
  * included. Even with the low end model clocked at 667 MHz this equals to a
- * critical time window of less than 30us. The value has been choosen to
+ * critical time window of less than 30us. The value has been chosen to
  * process a 512 byte disk block in one or a large 1400 bytes IPsec network
  * packet in two runs.
  *
index 55f106e..ae0751e 100644 (file)
 
 #define ATOMIC_INIT(i)         { (i) }
 
+/*
+ * Since *_return_relaxed and {cmp}xchg_relaxed are implemented with
+ * a "bne-" instruction at the end, so an isync is enough as a acquire barrier
+ * on the platform without lwsync.
+ */
+#define __atomic_op_acquire(op, args...)                               \
+({                                                                     \
+       typeof(op##_relaxed(args)) __ret  = op##_relaxed(args);         \
+       __asm__ __volatile__(PPC_ACQUIRE_BARRIER "" : : : "memory");    \
+       __ret;                                                          \
+})
+
+#define __atomic_op_release(op, args...)                               \
+({                                                                     \
+       __asm__ __volatile__(PPC_RELEASE_BARRIER "" : : : "memory");    \
+       op##_relaxed(args);                                             \
+})
+
 static __inline__ int atomic_read(const atomic_t *v)
 {
        int t;
@@ -42,27 +60,27 @@ static __inline__ void atomic_##op(int a, atomic_t *v)                      \
        : "cc");                                                        \
 }                                                                      \
 
-#define ATOMIC_OP_RETURN(op, asm_op)                                   \
-static __inline__ int atomic_##op##_return(int a, atomic_t *v)         \
+#define ATOMIC_OP_RETURN_RELAXED(op, asm_op)                           \
+static inline int atomic_##op##_return_relaxed(int a, atomic_t *v)     \
 {                                                                      \
        int t;                                                          \
                                                                        \
        __asm__ __volatile__(                                           \
-       PPC_ATOMIC_ENTRY_BARRIER                                        \
-"1:    lwarx   %0,0,%2         # atomic_" #op "_return\n"              \
-       #asm_op " %0,%1,%0\n"                                           \
-       PPC405_ERR77(0,%2)                                              \
-"      stwcx.  %0,0,%2 \n"                                             \
+"1:    lwarx   %0,0,%3         # atomic_" #op "_return_relaxed\n"      \
+       #asm_op " %0,%2,%0\n"                                           \
+       PPC405_ERR77(0, %3)                                             \
+"      stwcx.  %0,0,%3\n"                                              \
 "      bne-    1b\n"                                                   \
-       PPC_ATOMIC_EXIT_BARRIER                                         \
-       : "=&r" (t)                                                     \
+       : "=&r" (t), "+m" (v->counter)                                  \
        : "r" (a), "r" (&v->counter)                                    \
-       : "cc", "memory");                                              \
+       : "cc");                                                        \
                                                                        \
        return t;                                                       \
 }
 
-#define ATOMIC_OPS(op, asm_op) ATOMIC_OP(op, asm_op) ATOMIC_OP_RETURN(op, asm_op)
+#define ATOMIC_OPS(op, asm_op)                                         \
+       ATOMIC_OP(op, asm_op)                                           \
+       ATOMIC_OP_RETURN_RELAXED(op, asm_op)
 
 ATOMIC_OPS(add, add)
 ATOMIC_OPS(sub, subf)
@@ -71,8 +89,11 @@ ATOMIC_OP(and, and)
 ATOMIC_OP(or, or)
 ATOMIC_OP(xor, xor)
 
+#define atomic_add_return_relaxed atomic_add_return_relaxed
+#define atomic_sub_return_relaxed atomic_sub_return_relaxed
+
 #undef ATOMIC_OPS
-#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP_RETURN_RELAXED
 #undef ATOMIC_OP
 
 #define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
@@ -92,21 +113,19 @@ static __inline__ void atomic_inc(atomic_t *v)
        : "cc", "xer");
 }
 
-static __inline__ int atomic_inc_return(atomic_t *v)
+static __inline__ int atomic_inc_return_relaxed(atomic_t *v)
 {
        int t;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
-"1:    lwarx   %0,0,%1         # atomic_inc_return\n\
-       addic   %0,%0,1\n"
-       PPC405_ERR77(0,%1)
-"      stwcx.  %0,0,%1 \n\
-       bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
-       : "=&r" (t)
+"1:    lwarx   %0,0,%2         # atomic_inc_return_relaxed\n"
+"      addic   %0,%0,1\n"
+       PPC405_ERR77(0, %2)
+"      stwcx.  %0,0,%2\n"
+"      bne-    1b"
+       : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc", "xer", "memory");
+       : "cc", "xer");
 
        return t;
 }
@@ -136,27 +155,34 @@ static __inline__ void atomic_dec(atomic_t *v)
        : "cc", "xer");
 }
 
-static __inline__ int atomic_dec_return(atomic_t *v)
+static __inline__ int atomic_dec_return_relaxed(atomic_t *v)
 {
        int t;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
-"1:    lwarx   %0,0,%1         # atomic_dec_return\n\
-       addic   %0,%0,-1\n"
-       PPC405_ERR77(0,%1)
-"      stwcx.  %0,0,%1\n\
-       bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
-       : "=&r" (t)
+"1:    lwarx   %0,0,%2         # atomic_dec_return_relaxed\n"
+"      addic   %0,%0,-1\n"
+       PPC405_ERR77(0, %2)
+"      stwcx.  %0,0,%2\n"
+"      bne-    1b"
+       : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc", "xer", "memory");
+       : "cc", "xer");
 
        return t;
 }
 
+#define atomic_inc_return_relaxed atomic_inc_return_relaxed
+#define atomic_dec_return_relaxed atomic_dec_return_relaxed
+
 #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_cmpxchg_relaxed(v, o, n) \
+       cmpxchg_relaxed(&((v)->counter), (o), (n))
+#define atomic_cmpxchg_acquire(v, o, n) \
+       cmpxchg_acquire(&((v)->counter), (o), (n))
+
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic_xchg_relaxed(v, new) xchg_relaxed(&((v)->counter), (new))
 
 /**
  * __atomic_add_unless - add unless the number is a given value
@@ -285,26 +311,27 @@ static __inline__ void atomic64_##op(long a, atomic64_t *v)               \
        : "cc");                                                        \
 }
 
-#define ATOMIC64_OP_RETURN(op, asm_op)                                 \
-static __inline__ long atomic64_##op##_return(long a, atomic64_t *v)   \
+#define ATOMIC64_OP_RETURN_RELAXED(op, asm_op)                         \
+static inline long                                                     \
+atomic64_##op##_return_relaxed(long a, atomic64_t *v)                  \
 {                                                                      \
        long t;                                                         \
                                                                        \
        __asm__ __volatile__(                                           \
-       PPC_ATOMIC_ENTRY_BARRIER                                        \
-"1:    ldarx   %0,0,%2         # atomic64_" #op "_return\n"            \
-       #asm_op " %0,%1,%0\n"                                           \
-"      stdcx.  %0,0,%2 \n"                                             \
+"1:    ldarx   %0,0,%3         # atomic64_" #op "_return_relaxed\n"    \
+       #asm_op " %0,%2,%0\n"                                           \
+"      stdcx.  %0,0,%3\n"                                              \
 "      bne-    1b\n"                                                   \
-       PPC_ATOMIC_EXIT_BARRIER                                         \
-       : "=&r" (t)                                                     \
+       : "=&r" (t), "+m" (v->counter)                                  \
        : "r" (a), "r" (&v->counter)                                    \
-       : "cc", "memory");                                              \
+       : "cc");                                                        \
                                                                        \
        return t;                                                       \
 }
 
-#define ATOMIC64_OPS(op, asm_op) ATOMIC64_OP(op, asm_op) ATOMIC64_OP_RETURN(op, asm_op)
+#define ATOMIC64_OPS(op, asm_op)                                       \
+       ATOMIC64_OP(op, asm_op)                                         \
+       ATOMIC64_OP_RETURN_RELAXED(op, asm_op)
 
 ATOMIC64_OPS(add, add)
 ATOMIC64_OPS(sub, subf)
@@ -312,8 +339,11 @@ ATOMIC64_OP(and, and)
 ATOMIC64_OP(or, or)
 ATOMIC64_OP(xor, xor)
 
-#undef ATOMIC64_OPS
-#undef ATOMIC64_OP_RETURN
+#define atomic64_add_return_relaxed atomic64_add_return_relaxed
+#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
+
+#undef ATOPIC64_OPS
+#undef ATOMIC64_OP_RETURN_RELAXED
 #undef ATOMIC64_OP
 
 #define atomic64_add_negative(a, v)    (atomic64_add_return((a), (v)) < 0)
@@ -332,20 +362,18 @@ static __inline__ void atomic64_inc(atomic64_t *v)
        : "cc", "xer");
 }
 
-static __inline__ long atomic64_inc_return(atomic64_t *v)
+static __inline__ long atomic64_inc_return_relaxed(atomic64_t *v)
 {
        long t;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
-"1:    ldarx   %0,0,%1         # atomic64_inc_return\n\
-       addic   %0,%0,1\n\
-       stdcx.  %0,0,%1 \n\
-       bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
-       : "=&r" (t)
+"1:    ldarx   %0,0,%2         # atomic64_inc_return_relaxed\n"
+"      addic   %0,%0,1\n"
+"      stdcx.  %0,0,%2\n"
+"      bne-    1b"
+       : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc", "xer", "memory");
+       : "cc", "xer");
 
        return t;
 }
@@ -374,24 +402,25 @@ static __inline__ void atomic64_dec(atomic64_t *v)
        : "cc", "xer");
 }
 
-static __inline__ long atomic64_dec_return(atomic64_t *v)
+static __inline__ long atomic64_dec_return_relaxed(atomic64_t *v)
 {
        long t;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
-"1:    ldarx   %0,0,%1         # atomic64_dec_return\n\
-       addic   %0,%0,-1\n\
-       stdcx.  %0,0,%1\n\
-       bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
-       : "=&r" (t)
+"1:    ldarx   %0,0,%2         # atomic64_dec_return_relaxed\n"
+"      addic   %0,%0,-1\n"
+"      stdcx.  %0,0,%2\n"
+"      bne-    1b"
+       : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc", "xer", "memory");
+       : "cc", "xer");
 
        return t;
 }
 
+#define atomic64_inc_return_relaxed atomic64_inc_return_relaxed
+#define atomic64_dec_return_relaxed atomic64_dec_return_relaxed
+
 #define atomic64_sub_and_test(a, v)    (atomic64_sub_return((a), (v)) == 0)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
 
@@ -420,7 +449,13 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
 }
 
 #define atomic64_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_cmpxchg_relaxed(v, o, n) \
+       cmpxchg_relaxed(&((v)->counter), (o), (n))
+#define atomic64_cmpxchg_acquire(v, o, n) \
+       cmpxchg_acquire(&((v)->counter), (o), (n))
+
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic64_xchg_relaxed(v, new) xchg_relaxed(&((v)->counter), (new))
 
 /**
  * atomic64_add_unless - add unless the number is a given value
diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
new file mode 100644 (file)
index 0000000..16f513e
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef _ASM_POWERPC_MMU_HASH32_H_
+#define _ASM_POWERPC_MMU_HASH32_H_
+/*
+ * 32-bit hash table MMU support
+ */
+
+/*
+ * BATs
+ */
+
+/* Block size masks */
+#define BL_128K        0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M   0x007
+#define BL_2M   0x00F
+#define BL_4M   0x01F
+#define BL_8M   0x03F
+#define BL_16M  0x07F
+#define BL_32M  0x0FF
+#define BL_64M  0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX 0x00            /* No access */
+#define BPP_RX 0x01            /* Read only */
+#define BPP_RW 0x02            /* Read/write */
+
+#ifndef __ASSEMBLY__
+/* Contort a phys_addr_t into the right format/bits for a BAT */
+#ifdef CONFIG_PHYS_64BIT
+#define BAT_PHYS_ADDR(x) ((u32)((x & 0x00000000fffe0000ULL) | \
+                               ((x & 0x0000000e00000000ULL) >> 24) | \
+                               ((x & 0x0000000100000000ULL) >> 30)))
+#else
+#define BAT_PHYS_ADDR(x) (x)
+#endif
+
+struct ppc_bat {
+       u32 batu;
+       u32 batl;
+};
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Hash table
+ */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX        0       /* Supervisor read/write, User none */
+#define PP_RWRX 1      /* Supervisor read/write, User read */
+#define PP_RWRW 2      /* Supervisor read/write, User read/write */
+#define PP_RXRX 3      /* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Hardware Page Table Entry
+ * Note that the xpn and x bitfields are used only by processors that
+ * support extended addressing; otherwise, those bits are reserved.
+ */
+struct hash_pte {
+       unsigned long v:1;      /* Entry is valid */
+       unsigned long vsid:24;  /* Virtual segment identifier */
+       unsigned long h:1;      /* Hash algorithm indicator */
+       unsigned long api:6;    /* Abbreviated page index */
+       unsigned long rpn:20;   /* Real (physical) page number */
+       unsigned long xpn:3;    /* Real page number bits 0-2, optional */
+       unsigned long r:1;      /* Referenced */
+       unsigned long c:1;      /* Changed */
+       unsigned long w:1;      /* Write-thru cache mode */
+       unsigned long i:1;      /* Cache inhibited */
+       unsigned long m:1;      /* Memory coherence */
+       unsigned long g:1;      /* Guarded */
+       unsigned long x:1;      /* Real page number bit 3, optional */
+       unsigned long pp:2;     /* Page protection */
+};
+
+typedef struct {
+       unsigned long id;
+       unsigned long vdso_base;
+} mm_context_t;
+
+#endif /* !__ASSEMBLY__ */
+
+/* We happily ignore the smaller BATs on 601, we don't actually use
+ * those definitions on hash32 at the moment anyway
+ */
+#define mmu_virtual_psize      MMU_PAGE_4K
+#define mmu_linear_psize       MMU_PAGE_256M
+
+#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
index ea0414d..5f08a08 100644 (file)
                         _PAGE_F_SECOND | _PAGE_F_GIX)
 
 /* shift to put page number into pte */
-#define PTE_RPN_SHIFT  (18)
+#define PTE_RPN_SHIFT  (12)
+#define PTE_RPN_SIZE   (45)    /* gives 57-bit real addresses */
 
 #define _PAGE_4K_PFN           0
 #ifndef __ASSEMBLY__
 /*
- * 4-level page tables related bits
+ * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range()
  */
-
-#define pgd_none(pgd)          (!pgd_val(pgd))
-#define pgd_bad(pgd)           (pgd_val(pgd) == 0)
-#define pgd_present(pgd)       (pgd_val(pgd) != 0)
-#define pgd_page_vaddr(pgd)    (pgd_val(pgd) & ~PGD_MASKED_BITS)
-
-static inline void pgd_clear(pgd_t *pgdp)
-{
-       *pgdp = __pgd(0);
-}
-
-static inline pte_t pgd_pte(pgd_t pgd)
-{
-       return __pte(pgd_val(pgd));
-}
-
-static inline pgd_t pte_pgd(pte_t pte)
-{
-       return __pgd(pte_val(pte));
-}
-extern struct page *pgd_page(pgd_t pgd);
-
-#define pud_offset(pgdp, addr) \
-  (((pud_t *) pgd_page_vaddr(*(pgdp))) + \
-    (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)))
-
-#define pud_ERROR(e) \
-       pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
-
-/*
- * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range() */
 #define remap_4k_pfn(vma, addr, pfn, prot)     \
        remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
 
index 849bbec..0a7956a 100644 (file)
@@ -1,15 +1,14 @@
 #ifndef _ASM_POWERPC_BOOK3S_64_HASH_64K_H
 #define _ASM_POWERPC_BOOK3S_64_HASH_64K_H
 
-#include <asm-generic/pgtable-nopud.h>
-
 #define PTE_INDEX_SIZE  8
-#define PMD_INDEX_SIZE  10
-#define PUD_INDEX_SIZE 0
+#define PMD_INDEX_SIZE  5
+#define PUD_INDEX_SIZE 5
 #define PGD_INDEX_SIZE  12
 
 #define PTRS_PER_PTE   (1 << PTE_INDEX_SIZE)
 #define PTRS_PER_PMD   (1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD   (1 << PUD_INDEX_SIZE)
 #define PTRS_PER_PGD   (1 << PGD_INDEX_SIZE)
 
 /* With 4k base page size, hugepage PTEs go at the PMD level */
 #define PMD_SIZE       (1UL << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
 
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT    (PMD_SHIFT + PMD_INDEX_SIZE)
+/* PUD_SHIFT determines what a third-level page table entry can map */
+#define PUD_SHIFT      (PMD_SHIFT + PMD_INDEX_SIZE)
+#define PUD_SIZE       (1UL << PUD_SHIFT)
+#define PUD_MASK       (~(PUD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
+#define PGDIR_SHIFT    (PUD_SHIFT + PUD_INDEX_SIZE)
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
-#define _PAGE_COMBO    0x00040000 /* this is a combo 4k page */
-#define _PAGE_4K_PFN   0x00080000 /* PFN is for a single 4k page */
+#define _PAGE_COMBO    0x00001000 /* this is a combo 4k page */
+#define _PAGE_4K_PFN   0x00002000 /* PFN is for a single 4k page */
 /*
  * Used to track subpage group valid if _PAGE_COMBO is set
  * This overloads _PAGE_F_GIX and _PAGE_F_SECOND
 
 /* Shift to put page number into pte.
  *
- * That gives us a max RPN of 34 bits, which means a max of 50 bits
- * of addressable physical space, or 46 bits for the special 4k PFNs.
+ * That gives us a max RPN of 41 bits, which means a max of 57 bits
+ * of addressable physical space, or 53 bits for the special 4k PFNs.
  */
-#define PTE_RPN_SHIFT  (30)
+#define PTE_RPN_SHIFT  (16)
+#define PTE_RPN_SIZE   (41)
+
 /*
  * we support 16 fragments per PTE page of 64K size.
  */
 #define PTE_FRAG_SIZE_SHIFT  12
 #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT)
 
-/*
- * Bits to mask out from a PMD to get to the PTE page
- * PMDs point to PTE table fragments which are PTE_FRAG_SIZE aligned.
- */
-#define PMD_MASKED_BITS                (PTE_FRAG_SIZE - 1)
-/* Bits to mask out from a PGD/PUD to get to the PMD page */
-#define PUD_MASKED_BITS                0x1ff
+/* Bits to mask out from a PMD to get to the PTE page */
+#define PMD_MASKED_BITS                0xc0000000000000ffUL
+/* Bits to mask out from a PUD to get to the PMD page */
+#define PUD_MASKED_BITS                0xc0000000000000ffUL
+/* Bits to mask out from a PGD to get to the PUD page */
+#define PGD_MASKED_BITS                0xc0000000000000ffUL
 
 #ifndef __ASSEMBLY__
 
@@ -120,7 +125,7 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
        (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
 #define remap_4k_pfn(vma, addr, pfn, prot)                             \
-       (WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL :  \
+       (WARN_ON(((pfn) >= (1UL << PTE_RPN_SIZE))) ? -EINVAL :  \
                remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,        \
                        __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)))
 
@@ -130,11 +135,9 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
 #else
 #define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE)
 #endif
+#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE)
 #define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
 
-#define pgd_pte(pgd)   (pud_pte(((pud_t){ pgd })))
-#define pte_pgd(pte)   ((pgd_t)pte_pud(pte))
-
 #ifdef CONFIG_HUGETLB_PAGE
 /*
  * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have
@@ -208,30 +211,30 @@ static inline char *get_hpte_slot_array(pmd_t *pmdp)
 /*
  * The linux hugepage PMD now include the pmd entries followed by the address
  * to the stashed pgtable_t. The stashed pgtable_t contains the hpte bits.
- * [ 1 bit secondary | 3 bit hidx | 1 bit valid | 000]. We use one byte per
+ * [ 000 | 1 bit secondary | 3 bit hidx | 1 bit valid]. We use one byte per
  * each HPTE entry. With 16MB hugepage and 64K HPTE we need 256 entries and
  * with 4K HPTE we need 4096 entries. Both will fit in a 4K pgtable_t.
  *
- * The last three bits are intentionally left to zero. This memory location
+ * The top three bits are intentionally left as zero. This memory location
  * are also used as normal page PTE pointers. So if we have any pointers
  * left around while we collapse a hugepage, we need to make sure
  * _PAGE_PRESENT bit of that is zero when we look at them
  */
 static inline unsigned int hpte_valid(unsigned char *hpte_slot_array, int index)
 {
-       return (hpte_slot_array[index] >> 3) & 0x1;
+       return hpte_slot_array[index] & 0x1;
 }
 
 static inline unsigned int hpte_hash_index(unsigned char *hpte_slot_array,
                                           int index)
 {
-       return hpte_slot_array[index] >> 4;
+       return hpte_slot_array[index] >> 1;
 }
 
 static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
                                        unsigned int index, unsigned int hidx)
 {
-       hpte_slot_array[index] = hidx << 4 | 0x1 << 3;
+       hpte_slot_array[index] = (hidx << 1) | 0x1;
 }
 
 /*
index 8d1c816..d0ee6fc 100644 (file)
@@ -4,8 +4,7 @@
 
 /*
  * Common bits between 4K and 64K pages in a linux-style PTE.
- * These match the bits in the (hardware-defined) PowerPC PTE as closely
- * as possible. Additional bits may be defined in pgtable-hash64-*.h
+ * Additional bits may be defined in pgtable-hash64-*.h
  *
  * Note: We only support user read/write permissions. Supervisor always
  * have full read/write to pages above PAGE_OFFSET (pages below that
  * We could create separate kernel read-only if we used the 3 PP bits
  * combinations that newer processors provide but we currently don't.
  */
-#define _PAGE_PTE              0x00001
-#define _PAGE_PRESENT          0x00002 /* software: pte contains a translation */
-#define _PAGE_BIT_SWAP_TYPE    2
-#define _PAGE_USER             0x00004 /* matches one of the PP bits */
-#define _PAGE_EXEC             0x00008 /* No execute on POWER4 and newer (we invert) */
-#define _PAGE_GUARDED          0x00010
-/* We can derive Memory coherence from _PAGE_NO_CACHE */
+#define _PAGE_BIT_SWAP_TYPE    0
+
+#define _PAGE_EXEC             0x00001 /* execute permission */
+#define _PAGE_RW               0x00002 /* read & write access allowed */
+#define _PAGE_READ             0x00004 /* read access allowed */
+#define _PAGE_USER             0x00008 /* page may be accessed by userspace */
+#define _PAGE_GUARDED          0x00010 /* G: guarded (side-effect) page */
+/* M (memory coherence) is always set in the HPTE, so we don't need it here */
 #define _PAGE_COHERENT         0x0
 #define _PAGE_NO_CACHE         0x00020 /* I: cache inhibit */
 #define _PAGE_WRITETHRU                0x00040 /* W: cache write-through */
 #define _PAGE_DIRTY            0x00080 /* C: page changed */
 #define _PAGE_ACCESSED         0x00100 /* R: page referenced */
-#define _PAGE_RW               0x00200 /* software: user write access allowed */
-#define _PAGE_HASHPTE          0x00400 /* software: pte has an associated HPTE */
+#define _PAGE_SPECIAL          0x00400 /* software: special page */
 #define _PAGE_BUSY             0x00800 /* software: PTE & hash are busy */
-#define _PAGE_F_GIX            0x07000 /* full page: hidx bits */
-#define _PAGE_F_GIX_SHIFT      12
-#define _PAGE_F_SECOND         0x08000 /* Whether to use secondary hash or not */
-#define _PAGE_SPECIAL          0x10000 /* software: special page */
 
 #ifdef CONFIG_MEM_SOFT_DIRTY
-#define _PAGE_SOFT_DIRTY       0x20000 /* software: software dirty tracking */
+#define _PAGE_SOFT_DIRTY       0x200 /* software: software dirty tracking */
 #else
-#define _PAGE_SOFT_DIRTY       0x00000
+#define _PAGE_SOFT_DIRTY       0x000
 #endif
 
+#define _PAGE_F_GIX_SHIFT      57
+#define _PAGE_F_GIX            (7ul << 57)     /* HPTE index within HPTEG */
+#define _PAGE_F_SECOND         (1ul << 60)     /* HPTE is in 2ndary HPTEG */
+#define _PAGE_HASHPTE          (1ul << 61)     /* PTE has associated HPTE */
+#define _PAGE_PTE              (1ul << 62)     /* distinguishes PTEs from pointers */
+#define _PAGE_PRESENT          (1ul << 63)     /* pte contains a translation */
+
 /*
  * We need to differentiate between explicit huge page and THP huge
  * page, since THP huge page also need to track real subpage details
  * The mask convered by the RPN must be a ULL on 32-bit platforms with
  * 64-bit PTEs
  */
-#define PTE_RPN_MASK   (~((1UL << PTE_RPN_SHIFT) - 1))
+#define PTE_RPN_MASK   (((1UL << PTE_RPN_SIZE) - 1) << PTE_RPN_SHIFT)
 /*
  * _PAGE_CHG_MASK masks of bits that are to be preserved across
  * pgprot changes
 #define PUD_BAD_BITS           (PMD_TABLE_SIZE-1)
 
 #ifndef __ASSEMBLY__
-#define        pmd_bad(pmd)            (!is_kernel_addr(pmd_val(pmd)) \
-                                || (pmd_val(pmd) & PMD_BAD_BITS))
-#define pmd_page_vaddr(pmd)    (pmd_val(pmd) & ~PMD_MASKED_BITS)
+#define        pmd_bad(pmd)            (pmd_val(pmd) & PMD_BAD_BITS)
+#define pmd_page_vaddr(pmd)    __va(pmd_val(pmd) & ~PMD_MASKED_BITS)
+
+#define        pud_bad(pud)            (pud_val(pud) & PUD_BAD_BITS)
+#define pud_page_vaddr(pud)    __va(pud_val(pud) & ~PUD_MASKED_BITS)
 
-#define        pud_bad(pud)            (!is_kernel_addr(pud_val(pud)) \
-                                || (pud_val(pud) & PUD_BAD_BITS))
-#define pud_page_vaddr(pud)    (pud_val(pud) & ~PUD_MASKED_BITS)
+/* Pointers in the page table tree are physical addresses */
+#define __pgtable_ptr_val(ptr) __pa(ptr)
 
 #define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1))
+#define pud_index(address) (((address) >> (PUD_SHIFT)) & (PTRS_PER_PUD - 1))
 #define pmd_index(address) (((address) >> (PMD_SHIFT)) & (PTRS_PER_PMD - 1))
 #define pte_index(address) (((address) >> (PAGE_SHIFT)) & (PTRS_PER_PTE - 1))
 
@@ -360,8 +364,18 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
        :"cc");
 }
 
+static inline int pgd_bad(pgd_t pgd)
+{
+       return (pgd_val(pgd) == 0);
+}
+
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)  (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
+static inline unsigned long pgd_page_vaddr(pgd_t pgd)
+{
+       return (unsigned long)__va(pgd_val(pgd) & ~PGD_MASKED_BITS);
+}
+
 
 /* Generic accessors to PTE bits */
 static inline int pte_write(pte_t pte)         { return !!(pte_val(pte) & _PAGE_RW);}
@@ -402,7 +416,7 @@ static inline int pte_protnone(pte_t pte)
 
 static inline int pte_present(pte_t pte)
 {
-       return pte_val(pte) & _PAGE_PRESENT;
+       return !!(pte_val(pte) & _PAGE_PRESENT);
 }
 
 /* Conversion functions: convert a page and protection to a page entry,
@@ -413,13 +427,13 @@ static inline int pte_present(pte_t pte)
  */
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
 {
-       return __pte(((pte_basic_t)(pfn) << PTE_RPN_SHIFT) |
+       return __pte((((pte_basic_t)(pfn) << PTE_RPN_SHIFT) & PTE_RPN_MASK) |
                     pgprot_val(pgprot));
 }
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-       return pte_val(pte) >> PTE_RPN_SHIFT;
+       return (pte_val(pte) & PTE_RPN_MASK) >> PTE_RPN_SHIFT;
 }
 
 /* Generic modifiers for PTE bits */
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
new file mode 100644 (file)
index 0000000..0cea480
--- /dev/null
@@ -0,0 +1,616 @@
+#ifndef _ASM_POWERPC_MMU_HASH64_H_
+#define _ASM_POWERPC_MMU_HASH64_H_
+/*
+ * PowerPC64 memory management structures
+ *
+ * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
+ *   PPC64 rework.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/asm-compat.h>
+#include <asm/page.h>
+#include <asm/bug.h>
+
+/*
+ * This is necessary to get the definition of PGTABLE_RANGE which we
+ * need for various slices related matters. Note that this isn't the
+ * complete pgtable.h but only a portion of it.
+ */
+#include <asm/book3s/64/pgtable.h>
+#include <asm/bug.h>
+#include <asm/processor.h>
+
+/*
+ * SLB
+ */
+
+#define SLB_NUM_BOLTED         3
+#define SLB_CACHE_ENTRIES      8
+#define SLB_MIN_SIZE           32
+
+/* Bits in the SLB ESID word */
+#define SLB_ESID_V             ASM_CONST(0x0000000008000000) /* valid */
+
+/* Bits in the SLB VSID word */
+#define SLB_VSID_SHIFT         12
+#define SLB_VSID_SHIFT_1T      24
+#define SLB_VSID_SSIZE_SHIFT   62
+#define SLB_VSID_B             ASM_CONST(0xc000000000000000)
+#define SLB_VSID_B_256M                ASM_CONST(0x0000000000000000)
+#define SLB_VSID_B_1T          ASM_CONST(0x4000000000000000)
+#define SLB_VSID_KS            ASM_CONST(0x0000000000000800)
+#define SLB_VSID_KP            ASM_CONST(0x0000000000000400)
+#define SLB_VSID_N             ASM_CONST(0x0000000000000200) /* no-execute */
+#define SLB_VSID_L             ASM_CONST(0x0000000000000100)
+#define SLB_VSID_C             ASM_CONST(0x0000000000000080) /* class */
+#define SLB_VSID_LP            ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LP_00         ASM_CONST(0x0000000000000000)
+#define SLB_VSID_LP_01         ASM_CONST(0x0000000000000010)
+#define SLB_VSID_LP_10         ASM_CONST(0x0000000000000020)
+#define SLB_VSID_LP_11         ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LLP           (SLB_VSID_L|SLB_VSID_LP)
+
+#define SLB_VSID_KERNEL                (SLB_VSID_KP)
+#define SLB_VSID_USER          (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
+
+#define SLBIE_C                        (0x08000000)
+#define SLBIE_SSIZE_SHIFT      25
+
+/*
+ * Hash table
+ */
+
+#define HPTES_PER_GROUP 8
+
+#define HPTE_V_SSIZE_SHIFT     62
+#define HPTE_V_AVPN_SHIFT      7
+#define HPTE_V_AVPN            ASM_CONST(0x3fffffffffffff80)
+#define HPTE_V_AVPN_VAL(x)     (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
+#define HPTE_V_COMPARE(x,y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
+#define HPTE_V_BOLTED          ASM_CONST(0x0000000000000010)
+#define HPTE_V_LOCK            ASM_CONST(0x0000000000000008)
+#define HPTE_V_LARGE           ASM_CONST(0x0000000000000004)
+#define HPTE_V_SECONDARY       ASM_CONST(0x0000000000000002)
+#define HPTE_V_VALID           ASM_CONST(0x0000000000000001)
+
+#define HPTE_R_PP0             ASM_CONST(0x8000000000000000)
+#define HPTE_R_TS              ASM_CONST(0x4000000000000000)
+#define HPTE_R_KEY_HI          ASM_CONST(0x3000000000000000)
+#define HPTE_R_RPN_SHIFT       12
+#define HPTE_R_RPN             ASM_CONST(0x0ffffffffffff000)
+#define HPTE_R_PP              ASM_CONST(0x0000000000000003)
+#define HPTE_R_N               ASM_CONST(0x0000000000000004)
+#define HPTE_R_G               ASM_CONST(0x0000000000000008)
+#define HPTE_R_M               ASM_CONST(0x0000000000000010)
+#define HPTE_R_I               ASM_CONST(0x0000000000000020)
+#define HPTE_R_W               ASM_CONST(0x0000000000000040)
+#define HPTE_R_WIMG            ASM_CONST(0x0000000000000078)
+#define HPTE_R_C               ASM_CONST(0x0000000000000080)
+#define HPTE_R_R               ASM_CONST(0x0000000000000100)
+#define HPTE_R_KEY_LO          ASM_CONST(0x0000000000000e00)
+
+#define HPTE_V_1TB_SEG         ASM_CONST(0x4000000000000000)
+#define HPTE_V_VRMA_MASK       ASM_CONST(0x4001ffffff000000)
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX        0       /* Supervisor read/write, User none */
+#define PP_RWRX 1      /* Supervisor read/write, User read */
+#define PP_RWRW 2      /* Supervisor read/write, User read/write */
+#define PP_RXRX 3      /* Supervisor read,       User read */
+#define PP_RXXX        (HPTE_R_PP0 | 2)        /* Supervisor read, user none */
+
+/* Fields for tlbiel instruction in architecture 2.06 */
+#define TLBIEL_INVAL_SEL_MASK  0xc00   /* invalidation selector */
+#define  TLBIEL_INVAL_PAGE     0x000   /* invalidate a single page */
+#define  TLBIEL_INVAL_SET_LPID 0x800   /* invalidate a set for current LPID */
+#define  TLBIEL_INVAL_SET      0xc00   /* invalidate a set for all LPIDs */
+#define TLBIEL_INVAL_SET_MASK  0xfff000        /* set number to inval. */
+#define TLBIEL_INVAL_SET_SHIFT 12
+
+#define POWER7_TLB_SETS                128     /* # sets in POWER7 TLB */
+#define POWER8_TLB_SETS                512     /* # sets in POWER8 TLB */
+#define POWER9_TLB_SETS_HASH   256     /* # sets in POWER9 TLB Hash mode */
+
+#ifndef __ASSEMBLY__
+
+struct hash_pte {
+       __be64 v;
+       __be64 r;
+};
+
+extern struct hash_pte *htab_address;
+extern unsigned long htab_size_bytes;
+extern unsigned long htab_hash_mask;
+
+/*
+ * Page size definition
+ *
+ *    shift : is the "PAGE_SHIFT" value for that page size
+ *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
+ *            directly to a slbmte "vsid" value
+ *    penc  : is the HPTE encoding mask for the "LP" field:
+ *
+ */
+struct mmu_psize_def
+{
+       unsigned int    shift;  /* number of bits */
+       int             penc[MMU_PAGE_COUNT];   /* HPTE encoding */
+       unsigned int    tlbiel; /* tlbiel supported for that page size */
+       unsigned long   avpnm;  /* bits to mask out in AVPN in the HPTE */
+       unsigned long   sllp;   /* SLB L||LP (exact mask to use in slbmte) */
+};
+extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+
+static inline int shift_to_mmu_psize(unsigned int shift)
+{
+       int psize;
+
+       for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
+               if (mmu_psize_defs[psize].shift == shift)
+                       return psize;
+       return -1;
+}
+
+static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+{
+       if (mmu_psize_defs[mmu_psize].shift)
+               return mmu_psize_defs[mmu_psize].shift;
+       BUG();
+}
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Segment sizes.
+ * These are the values used by hardware in the B field of
+ * SLB entries and the first dword of MMU hashtable entries.
+ * The B field is 2 bits; the values 2 and 3 are unused and reserved.
+ */
+#define MMU_SEGSIZE_256M       0
+#define MMU_SEGSIZE_1T         1
+
+/*
+ * encode page number shift.
+ * in order to fit the 78 bit va in a 64 bit variable we shift the va by
+ * 12 bits. This enable us to address upto 76 bit va.
+ * For hpt hash from a va we can ignore the page size bits of va and for
+ * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
+ * we work in all cases including 4k page size.
+ */
+#define VPN_SHIFT      12
+
+/*
+ * HPTE Large Page (LP) details
+ */
+#define LP_SHIFT       12
+#define LP_BITS                8
+#define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+static inline int slb_vsid_shift(int ssize)
+{
+       if (ssize == MMU_SEGSIZE_256M)
+               return SLB_VSID_SHIFT;
+       return SLB_VSID_SHIFT_1T;
+}
+
+static inline int segment_shift(int ssize)
+{
+       if (ssize == MMU_SEGSIZE_256M)
+               return SID_SHIFT;
+       return SID_SHIFT_1T;
+}
+
+/*
+ * The current system page and segment sizes
+ */
+extern int mmu_linear_psize;
+extern int mmu_virtual_psize;
+extern int mmu_vmalloc_psize;
+extern int mmu_vmemmap_psize;
+extern int mmu_io_psize;
+extern int mmu_kernel_ssize;
+extern int mmu_highuser_ssize;
+extern u16 mmu_slb_size;
+extern unsigned long tce_alloc_start, tce_alloc_end;
+
+/*
+ * If the processor supports 64k normal pages but not 64k cache
+ * inhibited pages, we have to be prepared to switch processes
+ * to use 4k pages when they create cache-inhibited mappings.
+ * If this is the case, mmu_ci_restrictions will be set to 1.
+ */
+extern int mmu_ci_restrictions;
+
+/*
+ * This computes the AVPN and B fields of the first dword of a HPTE,
+ * for use when we want to match an existing PTE.  The bottom 7 bits
+ * of the returned value are zero.
+ */
+static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
+                                            int ssize)
+{
+       unsigned long v;
+       /*
+        * The AVA field omits the low-order 23 bits of the 78 bits VA.
+        * These bits are not needed in the PTE, because the
+        * low-order b of these bits are part of the byte offset
+        * into the virtual page and, if b < 23, the high-order
+        * 23-b of these bits are always used in selecting the
+        * PTEGs to be searched
+        */
+       v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
+       v <<= HPTE_V_AVPN_SHIFT;
+       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+       return v;
+}
+
+/*
+ * This function sets the AVPN and L fields of the HPTE  appropriately
+ * using the base page size and actual page size.
+ */
+static inline unsigned long hpte_encode_v(unsigned long vpn, int base_psize,
+                                         int actual_psize, int ssize)
+{
+       unsigned long v;
+       v = hpte_encode_avpn(vpn, base_psize, ssize);
+       if (actual_psize != MMU_PAGE_4K)
+               v |= HPTE_V_LARGE;
+       return v;
+}
+
+/*
+ * This function sets the ARPN, and LP fields of the HPTE appropriately
+ * for the page size. We assume the pa is already "clean" that is properly
+ * aligned for the requested page size
+ */
+static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize,
+                                         int actual_psize)
+{
+       /* A 4K page needs no special encoding */
+       if (actual_psize == MMU_PAGE_4K)
+               return pa & HPTE_R_RPN;
+       else {
+               unsigned int penc = mmu_psize_defs[base_psize].penc[actual_psize];
+               unsigned int shift = mmu_psize_defs[actual_psize].shift;
+               return (pa & ~((1ul << shift) - 1)) | (penc << LP_SHIFT);
+       }
+}
+
+/*
+ * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
+ */
+static inline unsigned long hpt_vpn(unsigned long ea,
+                                   unsigned long vsid, int ssize)
+{
+       unsigned long mask;
+       int s_shift = segment_shift(ssize);
+
+       mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
+       return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
+}
+
+/*
+ * This hashes a virtual address
+ */
+static inline unsigned long hpt_hash(unsigned long vpn,
+                                    unsigned int shift, int ssize)
+{
+       int mask;
+       unsigned long hash, vsid;
+
+       /* VPN_SHIFT can be atmost 12 */
+       if (ssize == MMU_SEGSIZE_256M) {
+               mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
+               hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT));
+       } else {
+               mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
+               vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
+               hash = vsid ^ (vsid << 25) ^
+                       ((vpn & mask) >> (shift - VPN_SHIFT)) ;
+       }
+       return hash & 0x7fffffffffUL;
+}
+
+#define HPTE_LOCAL_UPDATE      0x1
+#define HPTE_NOHPTE_UPDATE     0x2
+
+extern int __hash_page_4K(unsigned long ea, unsigned long access,
+                         unsigned long vsid, pte_t *ptep, unsigned long trap,
+                         unsigned long flags, int ssize, int subpage_prot);
+extern int __hash_page_64K(unsigned long ea, unsigned long access,
+                          unsigned long vsid, pte_t *ptep, unsigned long trap,
+                          unsigned long flags, int ssize);
+struct mm_struct;
+unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap);
+extern int hash_page_mm(struct mm_struct *mm, unsigned long ea,
+                       unsigned long access, unsigned long trap,
+                       unsigned long flags);
+extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
+                    unsigned long dsisr);
+int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
+                    pte_t *ptep, unsigned long trap, unsigned long flags,
+                    int ssize, unsigned int shift, unsigned int mmu_psize);
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+extern int __hash_page_thp(unsigned long ea, unsigned long access,
+                          unsigned long vsid, pmd_t *pmdp, unsigned long trap,
+                          unsigned long flags, int ssize, unsigned int psize);
+#else
+static inline int __hash_page_thp(unsigned long ea, unsigned long access,
+                                 unsigned long vsid, pmd_t *pmdp,
+                                 unsigned long trap, unsigned long flags,
+                                 int ssize, unsigned int psize)
+{
+       BUG();
+       return -1;
+}
+#endif
+extern void hash_failure_debug(unsigned long ea, unsigned long access,
+                              unsigned long vsid, unsigned long trap,
+                              int ssize, int psize, int lpsize,
+                              unsigned long pte);
+extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
+                            unsigned long pstart, unsigned long prot,
+                            int psize, int ssize);
+int htab_remove_mapping(unsigned long vstart, unsigned long vend,
+                       int psize, int ssize);
+extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
+extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
+
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
+extern void hpte_init_beat(void);
+extern void hpte_init_beat_v3(void);
+
+extern void slb_initialize(void);
+extern void slb_flush_and_rebolt(void);
+
+extern void slb_vmalloc_update(void);
+extern void slb_set_size(u16 size);
+#endif /* __ASSEMBLY__ */
+
+/*
+ * VSID allocation (256MB segment)
+ *
+ * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
+ * from mmu context id and effective segment id of the address.
+ *
+ * For user processes max context id is limited to ((1ul << 19) - 5)
+ * for kernel space, we use the top 4 context ids to map address as below
+ * NOTE: each context only support 64TB now.
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ *     VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ * VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below). The scramble function gives
+ * robust scattering in the hash table (at least based on some initial
+ * results).
+ *
+ * We also consider VSID 0 special. We use VSID 0 for slb entries mapping
+ * bad address. This enables us to consolidate bad address handling in
+ * hash_page.
+ *
+ * We also need to avoid the last segment of the last context, because that
+ * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
+ * because of the modulo operation in vsid scramble. But the vmemmap
+ * (which is what uses region 0xf) will never be close to 64TB in size
+ * (it's 56 bytes per page of system memory).
+ */
+
+#define CONTEXT_BITS           19
+#define ESID_BITS              18
+#define ESID_BITS_1T           6
+
+/*
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments
+ * available for user + kernel mapping. The top 4 contexts are used for
+ * kernel mapping. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
+ */
+#define MAX_USER_CONTEXT       ((ASM_CONST(1) << CONTEXT_BITS) - 5)
+
+/*
+ * This should be computed such that protovosid * vsid_mulitplier
+ * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
+ */
+#define VSID_MULTIPLIER_256M   ASM_CONST(12538073)     /* 24-bit prime */
+#define VSID_BITS_256M         (CONTEXT_BITS + ESID_BITS)
+#define VSID_MODULUS_256M      ((1UL<<VSID_BITS_256M)-1)
+
+#define VSID_MULTIPLIER_1T     ASM_CONST(12538073)     /* 24-bit prime */
+#define VSID_BITS_1T           (CONTEXT_BITS + ESID_BITS_1T)
+#define VSID_MODULUS_1T                ((1UL<<VSID_BITS_1T)-1)
+
+
+#define USER_VSID_RANGE        (1UL << (ESID_BITS + SID_SHIFT))
+
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function.  Used in slb_allocate() and do_stab_bolted.  The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ *     rt = register continaing the proto-VSID and into which the
+ *             VSID will be stored
+ *     rx = scratch register (clobbered)
+ *
+ *     - rt and rx must be different registers
+ *     - The answer will end up in the low VSID_BITS bits of rt.  The higher
+ *       bits may contain other garbage, so you may need to mask the
+ *       result.
+ */
+#define ASM_VSID_SCRAMBLE(rt, rx, size)                                        \
+       lis     rx,VSID_MULTIPLIER_##size@h;                            \
+       ori     rx,rx,VSID_MULTIPLIER_##size@l;                         \
+       mulld   rt,rt,rx;               /* rt = rt * MULTIPLIER */      \
+                                                                       \
+       srdi    rx,rt,VSID_BITS_##size;                                 \
+       clrldi  rt,rt,(64-VSID_BITS_##size);                            \
+       add     rt,rt,rx;               /* add high and low bits */     \
+       /* NOTE: explanation based on VSID_BITS_##size = 36             \
+        * Now, r3 == VSID (mod 2^36-1), and lies between 0 and         \
+        * 2^36-1+2^28-1.  That in particular means that if r3 >=       \
+        * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has     \
+        * the bit clear, r3 already has the answer we want, if it      \
+        * doesn't, the answer is the low 36 bits of r3+1.  So in all   \
+        * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+       addi    rx,rt,1;                                                \
+       srdi    rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */   \
+       add     rt,rt,rx
+
+/* 4 bits per slice and we have one slice per 1TB */
+#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_PPC_SUBPAGE_PROT
+/*
+ * For the sub-page protection option, we extend the PGD with one of
+ * these.  Basically we have a 3-level tree, with the top level being
+ * the protptrs array.  To optimize speed and memory consumption when
+ * only addresses < 4GB are being protected, pointers to the first
+ * four pages of sub-page protection words are stored in the low_prot
+ * array.
+ * Each page of sub-page protection words protects 1GB (4 bytes
+ * protects 64k).  For the 3-level tree, each page of pointers then
+ * protects 8TB.
+ */
+struct subpage_prot_table {
+       unsigned long maxaddr;  /* only addresses < this are protected */
+       unsigned int **protptrs[(TASK_SIZE_USER64 >> 43)];
+       unsigned int *low_prot[4];
+};
+
+#define SBP_L1_BITS            (PAGE_SHIFT - 2)
+#define SBP_L2_BITS            (PAGE_SHIFT - 3)
+#define SBP_L1_COUNT           (1 << SBP_L1_BITS)
+#define SBP_L2_COUNT           (1 << SBP_L2_BITS)
+#define SBP_L2_SHIFT           (PAGE_SHIFT + SBP_L1_BITS)
+#define SBP_L3_SHIFT           (SBP_L2_SHIFT + SBP_L2_BITS)
+
+extern void subpage_prot_free(struct mm_struct *mm);
+extern void subpage_prot_init_new_context(struct mm_struct *mm);
+#else
+static inline void subpage_prot_free(struct mm_struct *mm) {}
+static inline void subpage_prot_init_new_context(struct mm_struct *mm) { }
+#endif /* CONFIG_PPC_SUBPAGE_PROT */
+
+typedef unsigned long mm_context_id_t;
+struct spinlock;
+
+typedef struct {
+       mm_context_id_t id;
+       u16 user_psize;         /* page size index */
+
+#ifdef CONFIG_PPC_MM_SLICES
+       u64 low_slices_psize;   /* SLB page size encodings */
+       unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
+#else
+       u16 sllp;               /* SLB page size encoding */
+#endif
+       unsigned long vdso_base;
+#ifdef CONFIG_PPC_SUBPAGE_PROT
+       struct subpage_prot_table spt;
+#endif /* CONFIG_PPC_SUBPAGE_PROT */
+#ifdef CONFIG_PPC_ICSWX
+       struct spinlock *cop_lockp; /* guard acop and cop_pid */
+       unsigned long acop;     /* mask of enabled coprocessor types */
+       unsigned int cop_pid;   /* pid value used with coprocessors */
+#endif /* CONFIG_PPC_ICSWX */
+#ifdef CONFIG_PPC_64K_PAGES
+       /* for 4K PTE fragment support */
+       void *pte_frag;
+#endif
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+       struct list_head iommu_group_mem_list;
+#endif
+} mm_context_t;
+
+
+#if 0
+/*
+ * The code below is equivalent to this function for arguments
+ * < 2^VSID_BITS, which is all this should ever be called
+ * with.  However gcc is not clever enough to compute the
+ * modulus (2^n-1) without a second multiply.
+ */
+#define vsid_scramble(protovsid, size) \
+       ((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size))
+
+#else /* 1 */
+#define vsid_scramble(protovsid, size) \
+       ({                                                               \
+               unsigned long x;                                         \
+               x = (protovsid) * VSID_MULTIPLIER_##size;                \
+               x = (x >> VSID_BITS_##size) + (x & VSID_MODULUS_##size); \
+               (x + ((x+1) >> VSID_BITS_##size)) & VSID_MODULUS_##size; \
+       })
+#endif /* 1 */
+
+/* Returns the segment size indicator for a user address */
+static inline int user_segment_size(unsigned long addr)
+{
+       /* Use 1T segments if possible for addresses >= 1T */
+       if (addr >= (1UL << SID_SHIFT_1T))
+               return mmu_highuser_ssize;
+       return MMU_SEGSIZE_256M;
+}
+
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
+                                    int ssize)
+{
+       /*
+        * Bad address. We return VSID 0 for that
+        */
+       if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
+               return 0;
+
+       if (ssize == MMU_SEGSIZE_256M)
+               return vsid_scramble((context << ESID_BITS)
+                                    | (ea >> SID_SHIFT), 256M);
+       return vsid_scramble((context << ESID_BITS_1T)
+                            | (ea >> SID_SHIFT_1T), 1T);
+}
+
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ *
+ * For kernel space, we use the top 4 context ids to map address as below
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
+ */
+static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
+{
+       unsigned long context;
+
+       /*
+        * kernel take the top 4 context from the available range
+        */
+       context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1;
+       return get_vsid(context, ea, ssize);
+}
+
+unsigned htab_shift_for_mem_size(unsigned long mem_size);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
index ac07a30..77d3ce0 100644 (file)
  */
 #ifndef __real_pte
 
-#ifdef CONFIG_STRICT_MM_TYPECHECKS
 #define __real_pte(e,p)                ((real_pte_t){(e)})
 #define __rpte_to_pte(r)       ((r).pte)
-#else
-#define __real_pte(e,p)                (e)
-#define __rpte_to_pte(r)       (__pte(r))
-#endif
 #define __rpte_to_hidx(r,index)        (pte_val(__rpte_to_pte(r)) >>_PAGE_F_GIX_SHIFT)
 
 #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
@@ -111,6 +106,26 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val)
        *pgdp = __pgd(val);
 }
 
+static inline void pgd_clear(pgd_t *pgdp)
+{
+       *pgdp = __pgd(0);
+}
+
+#define pgd_none(pgd)          (!pgd_val(pgd))
+#define pgd_present(pgd)       (!pgd_none(pgd))
+
+static inline pte_t pgd_pte(pgd_t pgd)
+{
+       return __pte(pgd_val(pgd));
+}
+
+static inline pgd_t pte_pgd(pte_t pte)
+{
+       return __pgd(pte_val(pte));
+}
+
+extern struct page *pgd_page(pgd_t pgd);
+
 /*
  * Find an entry in a page-table-directory.  We combine the address region
  * (the high order N bits) and the pgd portion of the address.
@@ -118,9 +133,10 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val)
 
 #define pgd_offset(mm, address)         ((mm)->pgd + pgd_index(address))
 
+#define pud_offset(pgdp, addr) \
+       (((pud_t *) pgd_page_vaddr(*(pgdp))) + pud_index(addr))
 #define pmd_offset(pudp,addr) \
        (((pmd_t *) pud_page_vaddr(*(pudp))) + pmd_index(addr))
-
 #define pte_offset_kernel(dir,addr) \
        (((pte_t *) pmd_page_vaddr(*(dir))) + pte_index(addr))
 
@@ -135,6 +151,8 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val)
        pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
 #define pmd_ERROR(e) \
        pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pud_ERROR(e) \
+       pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
 #define pgd_ERROR(e) \
        pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
@@ -154,10 +172,10 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val)
 #define SWP_TYPE_BITS 5
 #define __swp_type(x)          (((x).val >> _PAGE_BIT_SWAP_TYPE) \
                                & ((1UL << SWP_TYPE_BITS) - 1))
-#define __swp_offset(x)                ((x).val >> PTE_RPN_SHIFT)
+#define __swp_offset(x)                (((x).val & PTE_RPN_MASK) >> PTE_RPN_SHIFT)
 #define __swp_entry(type, offset)      ((swp_entry_t) { \
-                                       ((type) << _PAGE_BIT_SWAP_TYPE) \
-                                       | ((offset) << PTE_RPN_SHIFT) })
+                               ((type) << _PAGE_BIT_SWAP_TYPE) \
+                               | (((offset) << PTE_RPN_SHIFT) & PTE_RPN_MASK)})
 /*
  * swp_entry_t must be independent of pte bits. We build a swp_entry_t from
  * swap type and offset we get from swap and convert that to pte to find a
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
new file mode 100644 (file)
index 0000000..1b753f9
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
+#define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
+
+#define MMU_NO_CONTEXT         0
+
+/*
+ * TLB flushing for 64-bit hash-MMU CPUs
+ */
+
+#include <linux/percpu.h>
+#include <asm/page.h>
+
+#define PPC64_TLB_BATCH_NR 192
+
+struct ppc64_tlb_batch {
+       int                     active;
+       unsigned long           index;
+       struct mm_struct        *mm;
+       real_pte_t              pte[PPC64_TLB_BATCH_NR];
+       unsigned long           vpn[PPC64_TLB_BATCH_NR];
+       unsigned int            psize;
+       int                     ssize;
+};
+DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
+
+extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+
+static inline void arch_enter_lazy_mmu_mode(void)
+{
+       struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
+
+       batch->active = 1;
+}
+
+static inline void arch_leave_lazy_mmu_mode(void)
+{
+       struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
+
+       if (batch->index)
+               __flush_tlb_pending(batch);
+       batch->active = 0;
+}
+
+#define arch_flush_lazy_mmu_mode()      do {} while (0)
+
+
+extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
+                           int ssize, unsigned long flags);
+extern void flush_hash_range(unsigned long number, int local);
+extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
+                               pmd_t *pmdp, unsigned int psize, int ssize,
+                               unsigned long flags);
+
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+}
+
+static inline void local_flush_tlb_page(struct vm_area_struct *vma,
+                                       unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                                 unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
+                                        unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+                                  unsigned long start, unsigned long end)
+{
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+                                         unsigned long end)
+{
+}
+
+/* Private function for use by PCI IO mapping code */
+extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
+                                    unsigned long end);
+extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd,
+                               unsigned long addr);
+#endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H */
index 5f8229e..ffbafbf 100644 (file)
@@ -69,6 +69,25 @@ extern void _set_L3CR(unsigned long);
 #define _set_L3CR(val) do { } while(0)
 #endif
 
+static inline void dcbz(void *addr)
+{
+       __asm__ __volatile__ ("dcbz 0, %0" : : "r"(addr) : "memory");
+}
+
+static inline void dcbi(void *addr)
+{
+       __asm__ __volatile__ ("dcbi 0, %0" : : "r"(addr) : "memory");
+}
+
+static inline void dcbf(void *addr)
+{
+       __asm__ __volatile__ ("dcbf 0, %0" : : "r"(addr) : "memory");
+}
+
+static inline void dcbst(void *addr)
+{
+       __asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory");
+}
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
index 6229e6b..69fb16d 100644 (file)
@@ -30,8 +30,6 @@ extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void __flush_disable_L1(void);
-
 extern void flush_icache_range(unsigned long, unsigned long);
 extern void flush_icache_user_range(struct vm_area_struct *vma,
                                    struct page *page, unsigned long addr,
@@ -47,12 +45,58 @@ static inline void __flush_dcache_icache_phys(unsigned long physaddr)
 }
 #endif
 
-extern void flush_dcache_range(unsigned long start, unsigned long stop);
 #ifdef CONFIG_PPC32
-extern void clean_dcache_range(unsigned long start, unsigned long stop);
-extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+/*
+ * Write any modified data cache blocks out to memory and invalidate them.
+ * Does not invalidate the corresponding instruction cache blocks.
+ */
+static inline void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+       void *addr = (void *)(start & ~(L1_CACHE_BYTES - 1));
+       unsigned long size = stop - (unsigned long)addr + (L1_CACHE_BYTES - 1);
+       unsigned long i;
+
+       for (i = 0; i < size >> L1_CACHE_SHIFT; i++, addr += L1_CACHE_BYTES)
+               dcbf(addr);
+       mb();   /* sync */
+}
+
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ */
+static inline void clean_dcache_range(unsigned long start, unsigned long stop)
+{
+       void *addr = (void *)(start & ~(L1_CACHE_BYTES - 1));
+       unsigned long size = stop - (unsigned long)addr + (L1_CACHE_BYTES - 1);
+       unsigned long i;
+
+       for (i = 0; i < size >> L1_CACHE_SHIFT; i++, addr += L1_CACHE_BYTES)
+               dcbst(addr);
+       mb();   /* sync */
+}
+
+/*
+ * Like above, but invalidate the D-cache.  This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ */
+static inline void invalidate_dcache_range(unsigned long start,
+                                          unsigned long stop)
+{
+       void *addr = (void *)(start & ~(L1_CACHE_BYTES - 1));
+       unsigned long size = stop - (unsigned long)addr + (L1_CACHE_BYTES - 1);
+       unsigned long i;
+
+       for (i = 0; i < size >> L1_CACHE_SHIFT; i++, addr += L1_CACHE_BYTES)
+               dcbi(addr);
+       mb();   /* sync */
+}
+
 #endif /* CONFIG_PPC32 */
 #ifdef CONFIG_PPC64
+extern void flush_dcache_range(unsigned long start, unsigned long stop);
 extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
 extern void flush_dcache_phys_range(unsigned long start, unsigned long stop);
 #endif
index e8d9ef4..ee655ed 100644 (file)
@@ -9,30 +9,9 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.  ihl is the number
- * of 32-bit words and is always >= 5.
- */
 #ifdef CONFIG_GENERIC_CSUM
 #include <asm-generic/checksum.h>
 #else
-extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
 /*
  * Computes the checksum of a memory block at src, length len,
  * and adds in "sum" (32-bit), while copying the block to dst.
@@ -47,21 +26,12 @@ extern __wsum csum_partial_copy_generic(const void *src, void *dst,
                                              int len, __wsum sum,
                                              int *src_err, int *dst_err);
 
-#ifdef __powerpc64__
 #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
 extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
                                      int len, __wsum sum, int *err_ptr);
 #define HAVE_CSUM_COPY_USER
 extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
                                    int len, __wsum sum, int *err_ptr);
-#else
-/*
- * the same as csum_partial, but copies from src to dst while it
- * checksums.
- */
-#define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
-        csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
-#endif
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
         csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
@@ -83,15 +53,6 @@ static inline __sum16 csum_fold(__wsum sum)
        return (__force __sum16)(~((__force u32)sum + tmp) >> 16);
 }
 
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-       return csum_fold(csum_partial(buff, len, 0));
-}
-
 static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
                                      unsigned short len,
                                      unsigned short proto,
@@ -135,17 +96,117 @@ static inline __wsum csum_add(__wsum csum, __wsum addend)
 {
 #ifdef __powerpc64__
        u64 res = (__force u64)csum;
+#endif
+       if (__builtin_constant_p(csum) && csum == 0)
+               return addend;
+       if (__builtin_constant_p(addend) && addend == 0)
+               return csum;
 
+#ifdef __powerpc64__
        res += (__force u64)addend;
        return (__force __wsum)((u32)res + (res >> 32));
 #else
        asm("addc %0,%0,%1;"
            "addze %0,%0;"
-           : "+r" (csum) : "r" (addend));
+           : "+r" (csum) : "r" (addend) : "xer");
        return csum;
 #endif
 }
 
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.  ihl is the number
+ * of 32-bit words and is always >= 5.
+ */
+static inline __wsum ip_fast_csum_nofold(const void *iph, unsigned int ihl)
+{
+       const u32 *ptr = (const u32 *)iph + 1;
+#ifdef __powerpc64__
+       unsigned int i;
+       u64 s = *(const u32 *)iph;
+
+       for (i = 0; i < ihl - 1; i++, ptr++)
+               s += *ptr;
+       s += (s >> 32);
+       return (__force __wsum)s;
+#else
+       __wsum sum, tmp;
+
+       asm("mtctr %3;"
+           "addc %0,%4,%5;"
+           "1: lwzu %1, 4(%2);"
+           "adde %0,%0,%1;"
+           "bdnz 1b;"
+           "addze %0,%0;"
+           : "=r" (sum), "=r" (tmp), "+b" (ptr)
+           : "r" (ihl - 2), "r" (*(const u32 *)iph), "r" (*ptr)
+           : "ctr", "xer", "memory");
+
+       return sum;
+#endif
+}
+
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+       return csum_fold(ip_fast_csum_nofold(iph, ihl));
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum __csum_partial(const void *buff, int len, __wsum sum);
+
+static inline __wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+       if (__builtin_constant_p(len) && len <= 16 && (len & 1) == 0) {
+               if (len == 2)
+                       sum = csum_add(sum, (__force __wsum)*(const u16 *)buff);
+               if (len >= 4)
+                       sum = csum_add(sum, (__force __wsum)*(const u32 *)buff);
+               if (len == 6)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u16 *)(buff + 4));
+               if (len >= 8)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u32 *)(buff + 4));
+               if (len == 10)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u16 *)(buff + 8));
+               if (len >= 12)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u32 *)(buff + 8));
+               if (len == 14)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u16 *)(buff + 12));
+               if (len >= 16)
+                       sum = csum_add(sum, (__force __wsum)
+                                           *(const u32 *)(buff + 12));
+       } else if (__builtin_constant_p(len) && (len & 3) == 0) {
+               sum = csum_add(sum, ip_fast_csum_nofold(buff, len >> 2));
+       } else {
+               sum = __csum_partial(buff, len, sum);
+       }
+       return sum;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+       return csum_fold(csum_partial(buff, len, 0));
+}
+
 #endif
 #endif /* __KERNEL__ */
 #endif
index d1a8d93..44efe73 100644 (file)
@@ -5,25 +5,25 @@
 #include <linux/compiler.h>
 #include <asm/synch.h>
 #include <asm/asm-compat.h>
+#include <linux/bug.h>
 
 /*
  * Atomic exchange
  *
- * Changes the memory location '*ptr' to be val and returns
+ * Changes the memory location '*p' to be val and returns
  * the previous value stored there.
  */
+
 static __always_inline unsigned long
-__xchg_u32(volatile void *p, unsigned long val)
+__xchg_u32_local(volatile void *p, unsigned long val)
 {
        unsigned long prev;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%2 \n"
        PPC405_ERR77(0,%2)
 "      stwcx.  %3,0,%2 \n\
        bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
        : "r" (p), "r" (val)
        : "cc", "memory");
@@ -31,42 +31,34 @@ __xchg_u32(volatile void *p, unsigned long val)
        return prev;
 }
 
-/*
- * Atomic exchange
- *
- * Changes the memory location '*ptr' to be val and returns
- * the previous value stored there.
- */
 static __always_inline unsigned long
-__xchg_u32_local(volatile void *p, unsigned long val)
+__xchg_u32_relaxed(u32 *p, unsigned long val)
 {
        unsigned long prev;
 
        __asm__ __volatile__(
-"1:    lwarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stwcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+"1:    lwarx   %0,0,%2\n"
+       PPC405_ERR77(0, %2)
+"      stwcx.  %3,0,%2\n"
+"      bne-    1b"
+       : "=&r" (prev), "+m" (*p)
        : "r" (p), "r" (val)
-       : "cc", "memory");
+       : "cc");
 
        return prev;
 }
 
 #ifdef CONFIG_PPC64
 static __always_inline unsigned long
-__xchg_u64(volatile void *p, unsigned long val)
+__xchg_u64_local(volatile void *p, unsigned long val)
 {
        unsigned long prev;
 
        __asm__ __volatile__(
-       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%2 \n"
        PPC405_ERR77(0,%2)
 "      stdcx.  %3,0,%2 \n\
        bne-    1b"
-       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
        : "r" (p), "r" (val)
        : "cc", "memory");
@@ -75,64 +67,52 @@ __xchg_u64(volatile void *p, unsigned long val)
 }
 
 static __always_inline unsigned long
-__xchg_u64_local(volatile void *p, unsigned long val)
+__xchg_u64_relaxed(u64 *p, unsigned long val)
 {
        unsigned long prev;
 
        __asm__ __volatile__(
-"1:    ldarx   %0,0,%2 \n"
-       PPC405_ERR77(0,%2)
-"      stdcx.  %3,0,%2 \n\
-       bne-    1b"
-       : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+"1:    ldarx   %0,0,%2\n"
+       PPC405_ERR77(0, %2)
+"      stdcx.  %3,0,%2\n"
+"      bne-    1b"
+       : "=&r" (prev), "+m" (*p)
        : "r" (p), "r" (val)
-       : "cc", "memory");
+       : "cc");
 
        return prev;
 }
 #endif
 
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid xchg().
- */
-extern void __xchg_called_with_bad_pointer(void);
-
 static __always_inline unsigned long
-__xchg(volatile void *ptr, unsigned long x, unsigned int size)
+__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
 {
        switch (size) {
        case 4:
-               return __xchg_u32(ptr, x);
+               return __xchg_u32_local(ptr, x);
 #ifdef CONFIG_PPC64
        case 8:
-               return __xchg_u64(ptr, x);
+               return __xchg_u64_local(ptr, x);
 #endif
        }
-       __xchg_called_with_bad_pointer();
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg");
        return x;
 }
 
 static __always_inline unsigned long
-__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+__xchg_relaxed(void *ptr, unsigned long x, unsigned int size)
 {
        switch (size) {
        case 4:
-               return __xchg_u32_local(ptr, x);
+               return __xchg_u32_relaxed(ptr, x);
 #ifdef CONFIG_PPC64
        case 8:
-               return __xchg_u64_local(ptr, x);
+               return __xchg_u64_relaxed(ptr, x);
 #endif
        }
-       __xchg_called_with_bad_pointer();
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_local");
        return x;
 }
-#define xchg(ptr,x)                                                         \
-  ({                                                                        \
-     __typeof__(*(ptr)) _x_ = (x);                                          \
-     (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
-  })
-
 #define xchg_local(ptr,x)                                                   \
   ({                                                                        \
      __typeof__(*(ptr)) _x_ = (x);                                          \
@@ -140,6 +120,12 @@ __xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
                (unsigned long)_x_, sizeof(*(ptr)));                         \
   })
 
+#define xchg_relaxed(ptr, x)                                           \
+({                                                                     \
+       __typeof__(*(ptr)) _x_ = (x);                                   \
+       (__typeof__(*(ptr))) __xchg_relaxed((ptr),                      \
+                       (unsigned long)_x_, sizeof(*(ptr)));            \
+})
 /*
  * Compare and exchange - if *p == old, set it to new,
  * and return the old value of *p.
@@ -190,6 +176,56 @@ __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old,
        return prev;
 }
 
+static __always_inline unsigned long
+__cmpxchg_u32_relaxed(u32 *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32_relaxed\n"
+"      cmpw    0,%0,%3\n"
+"      bne-    2f\n"
+       PPC405_ERR77(0, %2)
+"      stwcx.  %4,0,%2\n"
+"      bne-    1b\n"
+"2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc");
+
+       return prev;
+}
+
+/*
+ * cmpxchg family don't have order guarantee if cmp part fails, therefore we
+ * can avoid superfluous barriers if we use assembly code to implement
+ * cmpxchg() and cmpxchg_acquire(), however we don't do the similar for
+ * cmpxchg_release() because that will result in putting a barrier in the
+ * middle of a ll/sc loop, which is probably a bad idea. For example, this
+ * might cause the conditional store more likely to fail.
+ */
+static __always_inline unsigned long
+__cmpxchg_u32_acquire(u32 *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%2         # __cmpxchg_u32_acquire\n"
+"      cmpw    0,%0,%3\n"
+"      bne-    2f\n"
+       PPC405_ERR77(0, %2)
+"      stwcx.  %4,0,%2\n"
+"      bne-    1b\n"
+       PPC_ACQUIRE_BARRIER
+       "\n"
+"2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+
 #ifdef CONFIG_PPC64
 static __always_inline unsigned long
 __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
@@ -233,11 +269,47 @@ __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old,
 
        return prev;
 }
-#endif
 
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
+static __always_inline unsigned long
+__cmpxchg_u64_relaxed(u64 *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64_relaxed\n"
+"      cmpd    0,%0,%3\n"
+"      bne-    2f\n"
+"      stdcx.  %4,0,%2\n"
+"      bne-    1b\n"
+"2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc");
+
+       return prev;
+}
+
+static __always_inline unsigned long
+__cmpxchg_u64_acquire(u64 *p, unsigned long old, unsigned long new)
+{
+       unsigned long prev;
+
+       __asm__ __volatile__ (
+"1:    ldarx   %0,0,%2         # __cmpxchg_u64_acquire\n"
+"      cmpd    0,%0,%3\n"
+"      bne-    2f\n"
+"      stdcx.  %4,0,%2\n"
+"      bne-    1b\n"
+       PPC_ACQUIRE_BARRIER
+       "\n"
+"2:"
+       : "=&r" (prev), "+m" (*p)
+       : "r" (p), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return prev;
+}
+#endif
 
 static __always_inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
@@ -251,7 +323,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
                return __cmpxchg_u64(ptr, old, new);
 #endif
        }
-       __cmpxchg_called_with_bad_pointer();
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg");
        return old;
 }
 
@@ -267,10 +339,41 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
                return __cmpxchg_u64_local(ptr, old, new);
 #endif
        }
-       __cmpxchg_called_with_bad_pointer();
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_local");
+       return old;
+}
+
+static __always_inline unsigned long
+__cmpxchg_relaxed(void *ptr, unsigned long old, unsigned long new,
+                 unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_relaxed(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64_relaxed(ptr, old, new);
+#endif
+       }
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_relaxed");
        return old;
 }
 
+static __always_inline unsigned long
+__cmpxchg_acquire(void *ptr, unsigned long old, unsigned long new,
+                 unsigned int size)
+{
+       switch (size) {
+       case 4:
+               return __cmpxchg_u32_acquire(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64_acquire(ptr, old, new);
+#endif
+       }
+       BUILD_BUG_ON_MSG(1, "Unsupported size for __cmpxchg_acquire");
+       return old;
+}
 #define cmpxchg(ptr, o, n)                                              \
   ({                                                                    \
      __typeof__(*(ptr)) _o_ = (o);                                      \
@@ -288,6 +391,23 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
                                    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
+#define cmpxchg_relaxed(ptr, o, n)                                     \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr),                   \
+                       (unsigned long)_o_, (unsigned long)_n_,         \
+                       sizeof(*(ptr)));                                \
+})
+
+#define cmpxchg_acquire(ptr, o, n)                                     \
+({                                                                     \
+       __typeof__(*(ptr)) _o_ = (o);                                   \
+       __typeof__(*(ptr)) _n_ = (n);                                   \
+       (__typeof__(*(ptr))) __cmpxchg_acquire((ptr),                   \
+                       (unsigned long)_o_, (unsigned long)_n_,         \
+                       sizeof(*(ptr)));                                \
+})
 #ifdef CONFIG_PPC64
 #define cmpxchg64(ptr, o, n)                                           \
   ({                                                                   \
@@ -299,7 +419,16 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
        BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
        cmpxchg_local((ptr), (o), (n));                                 \
   })
-#define cmpxchg64_relaxed      cmpxchg64_local
+#define cmpxchg64_relaxed(ptr, o, n)                                   \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_relaxed((ptr), (o), (n));                               \
+})
+#define cmpxchg64_acquire(ptr, o, n)                                   \
+({                                                                     \
+       BUILD_BUG_ON(sizeof(*(ptr)) != 8);                              \
+       cmpxchg_acquire((ptr), (o), (n));                               \
+})
 #else
 #include <asm-generic/cmpxchg-local.h>
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
index 840a550..994c60a 100644 (file)
@@ -99,4 +99,25 @@ static inline unsigned long ppc_global_function_entry(void *func)
 #endif
 }
 
+#ifdef CONFIG_PPC64
+/*
+ * Some instruction encodings commonly used in dynamic ftracing
+ * and function live patching.
+ */
+
+/* This must match the definition of STK_GOT in <asm/ppc_asm.h> */
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+#define R2_STACK_OFFSET         24
+#else
+#define R2_STACK_OFFSET         40
+#endif
+
+#define PPC_INST_LD_TOC                (PPC_INST_LD  | ___PPC_RT(__REG_R2) | \
+                                ___PPC_RA(__REG_R1) | R2_STACK_OFFSET)
+
+/* usually preceded by a mflr r0 */
+#define PPC_INST_STD_LR                (PPC_INST_STD | ___PPC_RS(__REG_R0) | \
+                                ___PPC_RA(__REG_R1) | PPC_LR_STKOFF)
+#endif /* CONFIG_PPC64 */
+
 #endif /* _ASM_POWERPC_CODE_PATCHING_H */
index b118072..df4fb5f 100644 (file)
@@ -43,6 +43,11 @@ extern int machine_check_e500(struct pt_regs *regs);
 extern int machine_check_e200(struct pt_regs *regs);
 extern int machine_check_47x(struct pt_regs *regs);
 
+extern void cpu_down_flush_e500v2(void);
+extern void cpu_down_flush_e500mc(void);
+extern void cpu_down_flush_e5500(void);
+extern void cpu_down_flush_e6500(void);
+
 /* NOTE WELL: Update identify_cpu() if fields are added or removed! */
 struct cpu_spec {
        /* CPU is matched via (PVR & pvr_mask) == pvr_value */
@@ -59,6 +64,9 @@ struct cpu_spec {
        unsigned int    icache_bsize;
        unsigned int    dcache_bsize;
 
+       /* flush caches inside the current cpu */
+       void (*cpu_down_flush)(void);
+
        /* number of performance monitor counters */
        unsigned int    num_pmcs;
        enum powerpc_pmc_type pmc_type;
@@ -171,7 +179,7 @@ enum {
 #define CPU_FTR_ARCH_201               LONG_ASM_CONST(0x0000000200000000)
 #define CPU_FTR_ARCH_206               LONG_ASM_CONST(0x0000000400000000)
 #define CPU_FTR_ARCH_207S              LONG_ASM_CONST(0x0000000800000000)
-/* Free                                        LONG_ASM_CONST(0x0000001000000000) */
+#define CPU_FTR_ARCH_300               LONG_ASM_CONST(0x0000001000000000)
 #define CPU_FTR_MMCRA                  LONG_ASM_CONST(0x0000002000000000)
 #define CPU_FTR_CTRL                   LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_SMT                    LONG_ASM_CONST(0x0000008000000000)
@@ -196,6 +204,7 @@ enum {
 #define CPU_FTR_DAWR                   LONG_ASM_CONST(0x0400000000000000)
 #define CPU_FTR_DABRX                  LONG_ASM_CONST(0x0800000000000000)
 #define CPU_FTR_PMAO_BUG               LONG_ASM_CONST(0x1000000000000000)
+#define CPU_FTR_SUBCORE                        LONG_ASM_CONST(0x2000000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -443,9 +452,19 @@ enum {
            CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
            CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
            CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
-           CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP)
+           CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_SUBCORE)
 #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG)
 #define CPU_FTRS_POWER8_DD1 (CPU_FTRS_POWER8 & ~CPU_FTR_DBELL)
+#define CPU_FTRS_POWER9 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
+           CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\
+           CPU_FTR_MMCRA | CPU_FTR_SMT | \
+           CPU_FTR_COHERENT_ICACHE | \
+           CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
+           CPU_FTR_DSCR | CPU_FTR_SAO  | \
+           CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
+           CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
+           CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
+           CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300)
 #define CPU_FTRS_CELL  (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -464,7 +483,7 @@ enum {
            (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \
             CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \
             CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \
-            CPU_FTRS_PA6T | CPU_FTR_VSX)
+            CPU_FTRS_PA6T | CPU_FTR_VSX | CPU_FTRS_POWER9)
 #endif
 #else
 enum {
@@ -515,7 +534,8 @@ enum {
            (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \
             CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \
             CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \
-            CPU_FTRS_POWER8_DD1 & ~CPU_FTR_HVMODE & CPU_FTRS_POSSIBLE)
+            CPU_FTRS_POWER8_DD1 & ~CPU_FTR_HVMODE & CPU_FTRS_POSSIBLE & \
+            CPU_FTRS_POWER9)
 #endif
 #else
 enum {
index ba42e46..666bef4 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_POWERPC_CPUTHREADS_H
 #define _ASM_POWERPC_CPUTHREADS_H
 
+#ifndef __ASSEMBLY__
 #include <linux/cpumask.h>
 
 /*
@@ -94,7 +95,21 @@ static inline int cpu_last_thread_sibling(int cpu)
        return cpu | (threads_per_core - 1);
 }
 
+static inline u32 get_tensr(void)
+{
+#ifdef CONFIG_BOOKE
+       if (cpu_has_feature(CPU_FTR_SMT))
+               return mfspr(SPRN_TENSR);
+#endif
+       return 1;
+}
+
+void book3e_start_thread(int thread, unsigned long addr);
+void book3e_stop_thread(int thread);
+
+#endif /* __ASSEMBLY__ */
 
+#define INVALID_THREAD_HWID    0x0fff
 
 #endif /* _ASM_POWERPC_CPUTHREADS_H */
 
index 867c39b..fb9f376 100644 (file)
@@ -72,6 +72,7 @@ struct pci_dn;
 #define EEH_PE_PHB     (1 << 1)        /* PHB PE    */
 #define EEH_PE_DEVICE  (1 << 2)        /* Device PE */
 #define EEH_PE_BUS     (1 << 3)        /* Bus PE    */
+#define EEH_PE_VF      (1 << 4)        /* VF PE     */
 
 #define EEH_PE_ISOLATED                (1 << 0)        /* Isolated PE          */
 #define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
@@ -136,11 +137,15 @@ struct eeh_dev {
        int pcix_cap;                   /* Saved PCIx capability        */
        int pcie_cap;                   /* Saved PCIe capability        */
        int aer_cap;                    /* Saved AER capability         */
+       int af_cap;                     /* Saved AF capability          */
        struct eeh_pe *pe;              /* Associated PE                */
        struct list_head list;          /* Form link list in the PE     */
+       struct list_head rmv_list;      /* Record the removed edevs     */
        struct pci_controller *phb;     /* Associated PHB               */
        struct pci_dn *pdn;             /* Associated PCI device node   */
        struct pci_dev *pdev;           /* Associated PCI device        */
+       bool in_error;                  /* Error flag for edev          */
+       struct pci_dev *physfn;         /* Associated SRIOV PF          */
        struct pci_bus *bus;            /* PCI bus for partial hotplug  */
 };
 
diff --git a/arch/powerpc/include/asm/fsl_pm.h b/arch/powerpc/include/asm/fsl_pm.h
new file mode 100644 (file)
index 0000000..47df55e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Support Power Management
+ *
+ * Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __PPC_FSL_PM_H
+#define __PPC_FSL_PM_H
+
+#define E500_PM_PH10   1
+#define E500_PM_PH15   2
+#define E500_PM_PH20   3
+#define E500_PM_PH30   4
+#define E500_PM_DOZE   E500_PM_PH10
+#define E500_PM_NAP    E500_PM_PH15
+
+#define PLAT_PM_SLEEP  20
+#define PLAT_PM_LPM20  30
+
+#define FSL_PM_SLEEP           (1 << 0)
+#define FSL_PM_DEEP_SLEEP      (1 << 1)
+
+struct fsl_pm_ops {
+       /* mask pending interrupts to the RCPM from MPIC */
+       void (*irq_mask)(int cpu);
+
+       /* unmask pending interrupts to the RCPM from MPIC */
+       void (*irq_unmask)(int cpu);
+       void (*cpu_enter_state)(int cpu, int state);
+       void (*cpu_exit_state)(int cpu, int state);
+       void (*cpu_up_prepare)(int cpu);
+       void (*cpu_die)(int cpu);
+       int (*plat_enter_sleep)(void);
+       void (*freeze_time_base)(bool freeze);
+
+       /* keep the power of IP blocks during sleep/deep sleep */
+       void (*set_ip_power)(bool enable, u32 mask);
+
+       /* get platform supported power management modes */
+       unsigned int (*get_pm_modes)(void);
+};
+
+extern const struct fsl_pm_ops *qoriq_pm_ops;
+
+int __init fsl_rcpm_init(void);
+
+#endif /* __PPC_FSL_PM_H */
index ef89b14..50ca758 100644 (file)
@@ -46,6 +46,8 @@
 extern void _mcount(void);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+# define FTRACE_ADDR ((unsigned long)ftrace_caller)
+# define FTRACE_REGS_ADDR FTRACE_ADDR
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
        /* reloction of mcount call site is the same as the address */
@@ -58,6 +60,9 @@ struct dyn_arch_ftrace {
 #endif /*  CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
 #endif
 
 #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__)
index 7eac89b..42814f0 100644 (file)
@@ -19,7 +19,7 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
         * We have only four bits to encode, MMU page size
         */
        BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
-       return (pte_t *)(hpd.pd & ~HUGEPD_SHIFT_MASK);
+       return __va(hpd.pd & HUGEPD_ADDR_MASK);
 }
 
 static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
index e3b54dd..0bc9c28 100644 (file)
@@ -94,6 +94,7 @@
 #define H_SG_LIST      -72
 #define H_OP_MODE      -73
 #define H_COP_HW       -74
+#define H_STATE                -75
 #define H_UNSUPPORTED_FLAG_START       -256
 #define H_UNSUPPORTED_FLAG_END         -511
 #define H_MULTI_THREADS_ACTIVE -9005
index 1cb39c9..b3b0f2d 100644 (file)
@@ -89,7 +89,7 @@ extern volatile struct Hydra __iomem *Hydra;
 #define HYDRA_INT_EXT2         13      /* PCI IRQX */
 #define HYDRA_INT_EXT3         14      /* PCI IRQY */
 #define HYDRA_INT_EXT4         15      /* PCI IRQZ */
-#define HYDRA_INT_EXT5         16      /* IDE Primay/Secondary */
+#define HYDRA_INT_EXT5         16      /* IDE Primary/Secondary */
 #define HYDRA_INT_EXT6         17      /* IDE Secondary */
 #define HYDRA_INT_EXT7         18      /* Power Off Request */
 #define HYDRA_INT_SPARE                19
index 6c1297e..2fd1690 100644 (file)
@@ -300,7 +300,7 @@ extern void _memcpy_toio(volatile void __iomem *dest, const void *src,
  * When CONFIG_PPC_INDIRECT_MMIO is set, the platform can provide hooks
  * on all MMIOs. (Note that this is all 64 bits only for now)
  *
- * To help platforms who may need to differenciate MMIO addresses in
+ * To help platforms who may need to differentiate MMIO addresses in
  * their hooks, a bitfield is reserved for use by the platform near the
  * top of MMIO addresses (not PIO, those have to cope the hard way).
  *
index 3f191f5..fd22442 100644 (file)
@@ -54,7 +54,7 @@ struct machdep_calls {
                                       int psize, int apsize,
                                       int ssize);
        long            (*hpte_remove)(unsigned long hpte_group);
-       void            (*hpte_removebolted)(unsigned long ea,
+       int             (*hpte_removebolted)(unsigned long ea,
                                             int psize, int ssize);
        void            (*flush_hash_range)(unsigned long number, int local);
        void            (*hugepage_invalidate)(unsigned long vsid,
@@ -174,11 +174,11 @@ struct machdep_calls {
           platform, called once per cpu. */
        void            (*enable_pmcs)(void);
 
-       /* Set DABR for this platform, leave empty for default implemenation */
+       /* Set DABR for this platform, leave empty for default implementation */
        int             (*set_dabr)(unsigned long dabr,
                                    unsigned long dabrx);
 
-       /* Set DAWR for this platform, leave empty for default implemenation */
+       /* Set DAWR for this platform, leave empty for default implementation */
        int             (*set_dawr)(unsigned long dawr,
                                    unsigned long dawrx);
 
index f05500a..0a566f1 100644 (file)
@@ -171,9 +171,9 @@ typedef struct {
 } mm_context_t;
 #endif /* !__ASSEMBLY__ */
 
-#if (PAGE_SHIFT == 12)
+#if defined(CONFIG_PPC_4K_PAGES)
 #define mmu_virtual_psize      MMU_PAGE_4K
-#elif (PAGE_SHIFT == 14)
+#elif defined(CONFIG_PPC_16K_PAGES)
 #define mmu_virtual_psize      MMU_PAGE_16K
 #else
 #error "Unsupported PAGE_SIZE"
diff --git a/arch/powerpc/include/asm/mmu-hash32.h b/arch/powerpc/include/asm/mmu-hash32.h
deleted file mode 100644 (file)
index 16f513e..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef _ASM_POWERPC_MMU_HASH32_H_
-#define _ASM_POWERPC_MMU_HASH32_H_
-/*
- * 32-bit hash table MMU support
- */
-
-/*
- * BATs
- */
-
-/* Block size masks */
-#define BL_128K        0x000
-#define BL_256K 0x001
-#define BL_512K 0x003
-#define BL_1M   0x007
-#define BL_2M   0x00F
-#define BL_4M   0x01F
-#define BL_8M   0x03F
-#define BL_16M  0x07F
-#define BL_32M  0x0FF
-#define BL_64M  0x1FF
-#define BL_128M 0x3FF
-#define BL_256M 0x7FF
-
-/* BAT Access Protection */
-#define BPP_XX 0x00            /* No access */
-#define BPP_RX 0x01            /* Read only */
-#define BPP_RW 0x02            /* Read/write */
-
-#ifndef __ASSEMBLY__
-/* Contort a phys_addr_t into the right format/bits for a BAT */
-#ifdef CONFIG_PHYS_64BIT
-#define BAT_PHYS_ADDR(x) ((u32)((x & 0x00000000fffe0000ULL) | \
-                               ((x & 0x0000000e00000000ULL) >> 24) | \
-                               ((x & 0x0000000100000000ULL) >> 30)))
-#else
-#define BAT_PHYS_ADDR(x) (x)
-#endif
-
-struct ppc_bat {
-       u32 batu;
-       u32 batl;
-};
-#endif /* !__ASSEMBLY__ */
-
-/*
- * Hash table
- */
-
-/* Values for PP (assumes Ks=0, Kp=1) */
-#define PP_RWXX        0       /* Supervisor read/write, User none */
-#define PP_RWRX 1      /* Supervisor read/write, User read */
-#define PP_RWRW 2      /* Supervisor read/write, User read/write */
-#define PP_RXRX 3      /* Supervisor read,       User read */
-
-#ifndef __ASSEMBLY__
-
-/*
- * Hardware Page Table Entry
- * Note that the xpn and x bitfields are used only by processors that
- * support extended addressing; otherwise, those bits are reserved.
- */
-struct hash_pte {
-       unsigned long v:1;      /* Entry is valid */
-       unsigned long vsid:24;  /* Virtual segment identifier */
-       unsigned long h:1;      /* Hash algorithm indicator */
-       unsigned long api:6;    /* Abbreviated page index */
-       unsigned long rpn:20;   /* Real (physical) page number */
-       unsigned long xpn:3;    /* Real page number bits 0-2, optional */
-       unsigned long r:1;      /* Referenced */
-       unsigned long c:1;      /* Changed */
-       unsigned long w:1;      /* Write-thru cache mode */
-       unsigned long i:1;      /* Cache inhibited */
-       unsigned long m:1;      /* Memory coherence */
-       unsigned long g:1;      /* Guarded */
-       unsigned long x:1;      /* Real page number bit 3, optional */
-       unsigned long pp:2;     /* Page protection */
-};
-
-typedef struct {
-       unsigned long id;
-       unsigned long vdso_base;
-} mm_context_t;
-
-#endif /* !__ASSEMBLY__ */
-
-/* We happily ignore the smaller BATs on 601, we don't actually use
- * those definitions on hash32 at the moment anyway
- */
-#define mmu_virtual_psize      MMU_PAGE_4K
-#define mmu_linear_psize       MMU_PAGE_256M
-
-#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
deleted file mode 100644 (file)
index 7352d3f..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-#ifndef _ASM_POWERPC_MMU_HASH64_H_
-#define _ASM_POWERPC_MMU_HASH64_H_
-/*
- * PowerPC64 memory management structures
- *
- * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
- *   PPC64 rework.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/asm-compat.h>
-#include <asm/page.h>
-#include <asm/bug.h>
-
-/*
- * This is necessary to get the definition of PGTABLE_RANGE which we
- * need for various slices related matters. Note that this isn't the
- * complete pgtable.h but only a portion of it.
- */
-#include <asm/book3s/64/pgtable.h>
-#include <asm/bug.h>
-#include <asm/processor.h>
-
-/*
- * SLB
- */
-
-#define SLB_NUM_BOLTED         3
-#define SLB_CACHE_ENTRIES      8
-#define SLB_MIN_SIZE           32
-
-/* Bits in the SLB ESID word */
-#define SLB_ESID_V             ASM_CONST(0x0000000008000000) /* valid */
-
-/* Bits in the SLB VSID word */
-#define SLB_VSID_SHIFT         12
-#define SLB_VSID_SHIFT_1T      24
-#define SLB_VSID_SSIZE_SHIFT   62
-#define SLB_VSID_B             ASM_CONST(0xc000000000000000)
-#define SLB_VSID_B_256M                ASM_CONST(0x0000000000000000)
-#define SLB_VSID_B_1T          ASM_CONST(0x4000000000000000)
-#define SLB_VSID_KS            ASM_CONST(0x0000000000000800)
-#define SLB_VSID_KP            ASM_CONST(0x0000000000000400)
-#define SLB_VSID_N             ASM_CONST(0x0000000000000200) /* no-execute */
-#define SLB_VSID_L             ASM_CONST(0x0000000000000100)
-#define SLB_VSID_C             ASM_CONST(0x0000000000000080) /* class */
-#define SLB_VSID_LP            ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LP_00         ASM_CONST(0x0000000000000000)
-#define SLB_VSID_LP_01         ASM_CONST(0x0000000000000010)
-#define SLB_VSID_LP_10         ASM_CONST(0x0000000000000020)
-#define SLB_VSID_LP_11         ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LLP           (SLB_VSID_L|SLB_VSID_LP)
-
-#define SLB_VSID_KERNEL                (SLB_VSID_KP)
-#define SLB_VSID_USER          (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
-
-#define SLBIE_C                        (0x08000000)
-#define SLBIE_SSIZE_SHIFT      25
-
-/*
- * Hash table
- */
-
-#define HPTES_PER_GROUP 8
-
-#define HPTE_V_SSIZE_SHIFT     62
-#define HPTE_V_AVPN_SHIFT      7
-#define HPTE_V_AVPN            ASM_CONST(0x3fffffffffffff80)
-#define HPTE_V_AVPN_VAL(x)     (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
-#define HPTE_V_COMPARE(x,y)    (!(((x) ^ (y)) & 0xffffffffffffff80UL))
-#define HPTE_V_BOLTED          ASM_CONST(0x0000000000000010)
-#define HPTE_V_LOCK            ASM_CONST(0x0000000000000008)
-#define HPTE_V_LARGE           ASM_CONST(0x0000000000000004)
-#define HPTE_V_SECONDARY       ASM_CONST(0x0000000000000002)
-#define HPTE_V_VALID           ASM_CONST(0x0000000000000001)
-
-#define HPTE_R_PP0             ASM_CONST(0x8000000000000000)
-#define HPTE_R_TS              ASM_CONST(0x4000000000000000)
-#define HPTE_R_KEY_HI          ASM_CONST(0x3000000000000000)
-#define HPTE_R_RPN_SHIFT       12
-#define HPTE_R_RPN             ASM_CONST(0x0ffffffffffff000)
-#define HPTE_R_PP              ASM_CONST(0x0000000000000003)
-#define HPTE_R_N               ASM_CONST(0x0000000000000004)
-#define HPTE_R_G               ASM_CONST(0x0000000000000008)
-#define HPTE_R_M               ASM_CONST(0x0000000000000010)
-#define HPTE_R_I               ASM_CONST(0x0000000000000020)
-#define HPTE_R_W               ASM_CONST(0x0000000000000040)
-#define HPTE_R_WIMG            ASM_CONST(0x0000000000000078)
-#define HPTE_R_C               ASM_CONST(0x0000000000000080)
-#define HPTE_R_R               ASM_CONST(0x0000000000000100)
-#define HPTE_R_KEY_LO          ASM_CONST(0x0000000000000e00)
-
-#define HPTE_V_1TB_SEG         ASM_CONST(0x4000000000000000)
-#define HPTE_V_VRMA_MASK       ASM_CONST(0x4001ffffff000000)
-
-/* Values for PP (assumes Ks=0, Kp=1) */
-#define PP_RWXX        0       /* Supervisor read/write, User none */
-#define PP_RWRX 1      /* Supervisor read/write, User read */
-#define PP_RWRW 2      /* Supervisor read/write, User read/write */
-#define PP_RXRX 3      /* Supervisor read,       User read */
-#define PP_RXXX        (HPTE_R_PP0 | 2)        /* Supervisor read, user none */
-
-/* Fields for tlbiel instruction in architecture 2.06 */
-#define TLBIEL_INVAL_SEL_MASK  0xc00   /* invalidation selector */
-#define  TLBIEL_INVAL_PAGE     0x000   /* invalidate a single page */
-#define  TLBIEL_INVAL_SET_LPID 0x800   /* invalidate a set for current LPID */
-#define  TLBIEL_INVAL_SET      0xc00   /* invalidate a set for all LPIDs */
-#define TLBIEL_INVAL_SET_MASK  0xfff000        /* set number to inval. */
-#define TLBIEL_INVAL_SET_SHIFT 12
-
-#define POWER7_TLB_SETS                128     /* # sets in POWER7 TLB */
-#define POWER8_TLB_SETS                512     /* # sets in POWER8 TLB */
-
-#ifndef __ASSEMBLY__
-
-struct hash_pte {
-       __be64 v;
-       __be64 r;
-};
-
-extern struct hash_pte *htab_address;
-extern unsigned long htab_size_bytes;
-extern unsigned long htab_hash_mask;
-
-/*
- * Page size definition
- *
- *    shift : is the "PAGE_SHIFT" value for that page size
- *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
- *            directly to a slbmte "vsid" value
- *    penc  : is the HPTE encoding mask for the "LP" field:
- *
- */
-struct mmu_psize_def
-{
-       unsigned int    shift;  /* number of bits */
-       int             penc[MMU_PAGE_COUNT];   /* HPTE encoding */
-       unsigned int    tlbiel; /* tlbiel supported for that page size */
-       unsigned long   avpnm;  /* bits to mask out in AVPN in the HPTE */
-       unsigned long   sllp;   /* SLB L||LP (exact mask to use in slbmte) */
-};
-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-
-static inline int shift_to_mmu_psize(unsigned int shift)
-{
-       int psize;
-
-       for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
-               if (mmu_psize_defs[psize].shift == shift)
-                       return psize;
-       return -1;
-}
-
-static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
-{
-       if (mmu_psize_defs[mmu_psize].shift)
-               return mmu_psize_defs[mmu_psize].shift;
-       BUG();
-}
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * Segment sizes.
- * These are the values used by hardware in the B field of
- * SLB entries and the first dword of MMU hashtable entries.
- * The B field is 2 bits; the values 2 and 3 are unused and reserved.
- */
-#define MMU_SEGSIZE_256M       0
-#define MMU_SEGSIZE_1T         1
-
-/*
- * encode page number shift.
- * in order to fit the 78 bit va in a 64 bit variable we shift the va by
- * 12 bits. This enable us to address upto 76 bit va.
- * For hpt hash from a va we can ignore the page size bits of va and for
- * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
- * we work in all cases including 4k page size.
- */
-#define VPN_SHIFT      12
-
-/*
- * HPTE Large Page (LP) details
- */
-#define LP_SHIFT       12
-#define LP_BITS                8
-#define LP_MASK(i)     ((0xFF >> (i)) << LP_SHIFT)
-
-#ifndef __ASSEMBLY__
-
-static inline int slb_vsid_shift(int ssize)
-{
-       if (ssize == MMU_SEGSIZE_256M)
-               return SLB_VSID_SHIFT;
-       return SLB_VSID_SHIFT_1T;
-}
-
-static inline int segment_shift(int ssize)
-{
-       if (ssize == MMU_SEGSIZE_256M)
-               return SID_SHIFT;
-       return SID_SHIFT_1T;
-}
-
-/*
- * The current system page and segment sizes
- */
-extern int mmu_linear_psize;
-extern int mmu_virtual_psize;
-extern int mmu_vmalloc_psize;
-extern int mmu_vmemmap_psize;
-extern int mmu_io_psize;
-extern int mmu_kernel_ssize;
-extern int mmu_highuser_ssize;
-extern u16 mmu_slb_size;
-extern unsigned long tce_alloc_start, tce_alloc_end;
-
-/*
- * If the processor supports 64k normal pages but not 64k cache
- * inhibited pages, we have to be prepared to switch processes
- * to use 4k pages when they create cache-inhibited mappings.
- * If this is the case, mmu_ci_restrictions will be set to 1.
- */
-extern int mmu_ci_restrictions;
-
-/*
- * This computes the AVPN and B fields of the first dword of a HPTE,
- * for use when we want to match an existing PTE.  The bottom 7 bits
- * of the returned value are zero.
- */
-static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
-                                            int ssize)
-{
-       unsigned long v;
-       /*
-        * The AVA field omits the low-order 23 bits of the 78 bits VA.
-        * These bits are not needed in the PTE, because the
-        * low-order b of these bits are part of the byte offset
-        * into the virtual page and, if b < 23, the high-order
-        * 23-b of these bits are always used in selecting the
-        * PTEGs to be searched
-        */
-       v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
-       v <<= HPTE_V_AVPN_SHIFT;
-       v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
-       return v;
-}
-
-/*
- * This function sets the AVPN and L fields of the HPTE  appropriately
- * using the base page size and actual page size.
- */
-static inline unsigned long hpte_encode_v(unsigned long vpn, int base_psize,
-                                         int actual_psize, int ssize)
-{
-       unsigned long v;
-       v = hpte_encode_avpn(vpn, base_psize, ssize);
-       if (actual_psize != MMU_PAGE_4K)
-               v |= HPTE_V_LARGE;
-       return v;
-}
-
-/*
- * This function sets the ARPN, and LP fields of the HPTE appropriately
- * for the page size. We assume the pa is already "clean" that is properly
- * aligned for the requested page size
- */
-static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize,
-                                         int actual_psize)
-{
-       /* A 4K page needs no special encoding */
-       if (actual_psize == MMU_PAGE_4K)
-               return pa & HPTE_R_RPN;
-       else {
-               unsigned int penc = mmu_psize_defs[base_psize].penc[actual_psize];
-               unsigned int shift = mmu_psize_defs[actual_psize].shift;
-               return (pa & ~((1ul << shift) - 1)) | (penc << LP_SHIFT);
-       }
-}
-
-/*
- * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
- */
-static inline unsigned long hpt_vpn(unsigned long ea,
-                                   unsigned long vsid, int ssize)
-{
-       unsigned long mask;
-       int s_shift = segment_shift(ssize);
-
-       mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
-       return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
-}
-
-/*
- * This hashes a virtual address
- */
-static inline unsigned long hpt_hash(unsigned long vpn,
-                                    unsigned int shift, int ssize)
-{
-       int mask;
-       unsigned long hash, vsid;
-
-       /* VPN_SHIFT can be atmost 12 */
-       if (ssize == MMU_SEGSIZE_256M) {
-               mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
-               hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
-                       ((vpn & mask) >> (shift - VPN_SHIFT));
-       } else {
-               mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
-               vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
-               hash = vsid ^ (vsid << 25) ^
-                       ((vpn & mask) >> (shift - VPN_SHIFT)) ;
-       }
-       return hash & 0x7fffffffffUL;
-}
-
-#define HPTE_LOCAL_UPDATE      0x1
-#define HPTE_NOHPTE_UPDATE     0x2
-
-extern int __hash_page_4K(unsigned long ea, unsigned long access,
-                         unsigned long vsid, pte_t *ptep, unsigned long trap,
-                         unsigned long flags, int ssize, int subpage_prot);
-extern int __hash_page_64K(unsigned long ea, unsigned long access,
-                          unsigned long vsid, pte_t *ptep, unsigned long trap,
-                          unsigned long flags, int ssize);
-struct mm_struct;
-unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap);
-extern int hash_page_mm(struct mm_struct *mm, unsigned long ea,
-                       unsigned long access, unsigned long trap,
-                       unsigned long flags);
-extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
-                    unsigned long dsisr);
-int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
-                    pte_t *ptep, unsigned long trap, unsigned long flags,
-                    int ssize, unsigned int shift, unsigned int mmu_psize);
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-extern int __hash_page_thp(unsigned long ea, unsigned long access,
-                          unsigned long vsid, pmd_t *pmdp, unsigned long trap,
-                          unsigned long flags, int ssize, unsigned int psize);
-#else
-static inline int __hash_page_thp(unsigned long ea, unsigned long access,
-                                 unsigned long vsid, pmd_t *pmdp,
-                                 unsigned long trap, unsigned long flags,
-                                 int ssize, unsigned int psize)
-{
-       BUG();
-       return -1;
-}
-#endif
-extern void hash_failure_debug(unsigned long ea, unsigned long access,
-                              unsigned long vsid, unsigned long trap,
-                              int ssize, int psize, int lpsize,
-                              unsigned long pte);
-extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
-                            unsigned long pstart, unsigned long prot,
-                            int psize, int ssize);
-int htab_remove_mapping(unsigned long vstart, unsigned long vend,
-                       int psize, int ssize);
-extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages);
-extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr);
-
-extern void hpte_init_native(void);
-extern void hpte_init_lpar(void);
-extern void hpte_init_beat(void);
-extern void hpte_init_beat_v3(void);
-
-extern void slb_initialize(void);
-extern void slb_flush_and_rebolt(void);
-
-extern void slb_vmalloc_update(void);
-extern void slb_set_size(u16 size);
-#endif /* __ASSEMBLY__ */
-
-/*
- * VSID allocation (256MB segment)
- *
- * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
- * from mmu context id and effective segment id of the address.
- *
- * For user processes max context id is limited to ((1ul << 19) - 5)
- * for kernel space, we use the top 4 context ids to map address as below
- * NOTE: each context only support 64TB now.
- * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
- * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
- * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
- * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
- *
- * The proto-VSIDs are then scrambled into real VSIDs with the
- * multiplicative hash:
- *
- *     VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *
- * VSID_MULTIPLIER is prime, so in particular it is
- * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
- * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below). The scramble function gives
- * robust scattering in the hash table (at least based on some initial
- * results).
- *
- * We also consider VSID 0 special. We use VSID 0 for slb entries mapping
- * bad address. This enables us to consolidate bad address handling in
- * hash_page.
- *
- * We also need to avoid the last segment of the last context, because that
- * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
- * because of the modulo operation in vsid scramble. But the vmemmap
- * (which is what uses region 0xf) will never be close to 64TB in size
- * (it's 56 bytes per page of system memory).
- */
-
-#define CONTEXT_BITS           19
-#define ESID_BITS              18
-#define ESID_BITS_1T           6
-
-/*
- * 256MB segment
- * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments
- * available for user + kernel mapping. The top 4 contexts are used for
- * kernel mapping. Each segment contains 2^28 bytes. Each
- * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
- * (19 == 37 + 28 - 46).
- */
-#define MAX_USER_CONTEXT       ((ASM_CONST(1) << CONTEXT_BITS) - 5)
-
-/*
- * This should be computed such that protovosid * vsid_mulitplier
- * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
- */
-#define VSID_MULTIPLIER_256M   ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_256M         (CONTEXT_BITS + ESID_BITS)
-#define VSID_MODULUS_256M      ((1UL<<VSID_BITS_256M)-1)
-
-#define VSID_MULTIPLIER_1T     ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_1T           (CONTEXT_BITS + ESID_BITS_1T)
-#define VSID_MODULUS_1T                ((1UL<<VSID_BITS_1T)-1)
-
-
-#define USER_VSID_RANGE        (1UL << (ESID_BITS + SID_SHIFT))
-
-/*
- * This macro generates asm code to compute the VSID scramble
- * function.  Used in slb_allocate() and do_stab_bolted.  The function
- * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
- *
- *     rt = register continaing the proto-VSID and into which the
- *             VSID will be stored
- *     rx = scratch register (clobbered)
- *
- *     - rt and rx must be different registers
- *     - The answer will end up in the low VSID_BITS bits of rt.  The higher
- *       bits may contain other garbage, so you may need to mask the
- *       result.
- */
-#define ASM_VSID_SCRAMBLE(rt, rx, size)                                        \
-       lis     rx,VSID_MULTIPLIER_##size@h;                            \
-       ori     rx,rx,VSID_MULTIPLIER_##size@l;                         \
-       mulld   rt,rt,rx;               /* rt = rt * MULTIPLIER */      \
-                                                                       \
-       srdi    rx,rt,VSID_BITS_##size;                                 \
-       clrldi  rt,rt,(64-VSID_BITS_##size);                            \
-       add     rt,rt,rx;               /* add high and low bits */     \
-       /* NOTE: explanation based on VSID_BITS_##size = 36             \
-        * Now, r3 == VSID (mod 2^36-1), and lies between 0 and         \
-        * 2^36-1+2^28-1.  That in particular means that if r3 >=       \
-        * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has     \
-        * the bit clear, r3 already has the answer we want, if it      \
-        * doesn't, the answer is the low 36 bits of r3+1.  So in all   \
-        * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
-       addi    rx,rt,1;                                                \
-       srdi    rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */   \
-       add     rt,rt,rx
-
-/* 4 bits per slice and we have one slice per 1TB */
-#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
-
-#ifndef __ASSEMBLY__
-
-#ifdef CONFIG_PPC_SUBPAGE_PROT
-/*
- * For the sub-page protection option, we extend the PGD with one of
- * these.  Basically we have a 3-level tree, with the top level being
- * the protptrs array.  To optimize speed and memory consumption when
- * only addresses < 4GB are being protected, pointers to the first
- * four pages of sub-page protection words are stored in the low_prot
- * array.
- * Each page of sub-page protection words protects 1GB (4 bytes
- * protects 64k).  For the 3-level tree, each page of pointers then
- * protects 8TB.
- */
-struct subpage_prot_table {
-       unsigned long maxaddr;  /* only addresses < this are protected */
-       unsigned int **protptrs[(TASK_SIZE_USER64 >> 43)];
-       unsigned int *low_prot[4];
-};
-
-#define SBP_L1_BITS            (PAGE_SHIFT - 2)
-#define SBP_L2_BITS            (PAGE_SHIFT - 3)
-#define SBP_L1_COUNT           (1 << SBP_L1_BITS)
-#define SBP_L2_COUNT           (1 << SBP_L2_BITS)
-#define SBP_L2_SHIFT           (PAGE_SHIFT + SBP_L1_BITS)
-#define SBP_L3_SHIFT           (SBP_L2_SHIFT + SBP_L2_BITS)
-
-extern void subpage_prot_free(struct mm_struct *mm);
-extern void subpage_prot_init_new_context(struct mm_struct *mm);
-#else
-static inline void subpage_prot_free(struct mm_struct *mm) {}
-static inline void subpage_prot_init_new_context(struct mm_struct *mm) { }
-#endif /* CONFIG_PPC_SUBPAGE_PROT */
-
-typedef unsigned long mm_context_id_t;
-struct spinlock;
-
-typedef struct {
-       mm_context_id_t id;
-       u16 user_psize;         /* page size index */
-
-#ifdef CONFIG_PPC_MM_SLICES
-       u64 low_slices_psize;   /* SLB page size encodings */
-       unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
-#else
-       u16 sllp;               /* SLB page size encoding */
-#endif
-       unsigned long vdso_base;
-#ifdef CONFIG_PPC_SUBPAGE_PROT
-       struct subpage_prot_table spt;
-#endif /* CONFIG_PPC_SUBPAGE_PROT */
-#ifdef CONFIG_PPC_ICSWX
-       struct spinlock *cop_lockp; /* guard acop and cop_pid */
-       unsigned long acop;     /* mask of enabled coprocessor types */
-       unsigned int cop_pid;   /* pid value used with coprocessors */
-#endif /* CONFIG_PPC_ICSWX */
-#ifdef CONFIG_PPC_64K_PAGES
-       /* for 4K PTE fragment support */
-       void *pte_frag;
-#endif
-#ifdef CONFIG_SPAPR_TCE_IOMMU
-       struct list_head iommu_group_mem_list;
-#endif
-} mm_context_t;
-
-
-#if 0
-/*
- * The code below is equivalent to this function for arguments
- * < 2^VSID_BITS, which is all this should ever be called
- * with.  However gcc is not clever enough to compute the
- * modulus (2^n-1) without a second multiply.
- */
-#define vsid_scramble(protovsid, size) \
-       ((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size))
-
-#else /* 1 */
-#define vsid_scramble(protovsid, size) \
-       ({                                                               \
-               unsigned long x;                                         \
-               x = (protovsid) * VSID_MULTIPLIER_##size;                \
-               x = (x >> VSID_BITS_##size) + (x & VSID_MODULUS_##size); \
-               (x + ((x+1) >> VSID_BITS_##size)) & VSID_MODULUS_##size; \
-       })
-#endif /* 1 */
-
-/* Returns the segment size indicator for a user address */
-static inline int user_segment_size(unsigned long addr)
-{
-       /* Use 1T segments if possible for addresses >= 1T */
-       if (addr >= (1UL << SID_SHIFT_1T))
-               return mmu_highuser_ssize;
-       return MMU_SEGSIZE_256M;
-}
-
-static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
-                                    int ssize)
-{
-       /*
-        * Bad address. We return VSID 0 for that
-        */
-       if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
-               return 0;
-
-       if (ssize == MMU_SEGSIZE_256M)
-               return vsid_scramble((context << ESID_BITS)
-                                    | (ea >> SID_SHIFT), 256M);
-       return vsid_scramble((context << ESID_BITS_1T)
-                            | (ea >> SID_SHIFT_1T), 1T);
-}
-
-/*
- * This is only valid for addresses >= PAGE_OFFSET
- *
- * For kernel space, we use the top 4 context ids to map address as below
- * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
- * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
- * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
- * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
- */
-static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
-{
-       unsigned long context;
-
-       /*
-        * kernel take the top 4 context from the available range
-        */
-       context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1;
-       return get_vsid(context, ea, ssize);
-}
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
index 3d5abfe..8ca1c98 100644 (file)
@@ -97,6 +97,7 @@
 #define MMU_FTRS_POWER6                MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_POWER7                MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_POWER8                MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
+#define MMU_FTRS_POWER9                MMU_FTRS_POWER4 | MMU_FTR_LOCKLESS_TLBIE
 #define MMU_FTRS_CELL          MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
                                MMU_FTR_CI_LARGE_PAGE
 #define MMU_FTRS_PA6T          MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
@@ -182,10 +183,10 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
-#  include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #elif defined(CONFIG_PPC_STD_MMU_32)
 /* 32-bit classic hash table MMU */
-#  include <asm/mmu-hash32.h>
+#include <asm/book3s/32/mmu-hash.h>
 #elif defined(CONFIG_40x)
 /* 40x-style software loaded TLB */
 #  include <asm/mmu-40x.h>
index dcfcad1..cd4ffd8 100644 (file)
@@ -19,7 +19,7 @@
  * Thanks to Paul M for explaining this.
  *
  * PPC can only do rel jumps += 32MB, and often the kernel and other
- * modules are furthur away than this.  So, we jump to a table of
+ * modules are further away than this.  So, we jump to a table of
  * trampolines attached to the module (the Procedure Linkage Table)
  * whenever that happens.
  */
@@ -78,10 +78,18 @@ struct mod_arch_specific {
 #    endif     /* MODULE */
 #endif
 
-bool is_module_trampoline(u32 *insns);
-int module_trampoline_target(struct module *mod, u32 *trampoline,
+int module_trampoline_target(struct module *mod, unsigned long trampoline,
                             unsigned long *target);
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs);
+#else
+static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
+{
+       return 0;
+}
+#endif
+
 struct exception_table_entry;
 void sort_ex_table(struct exception_table_entry *start,
                   struct exception_table_entry *finish);
index c82cbf5..7808475 100644 (file)
@@ -86,7 +86,7 @@ extern int icache_44x_need_flush;
  * We no longer map larger than phys RAM with the BATs so we don't have
  * to worry about the VMALLOC_OFFSET causing problems.  We do have to worry
  * about clashes between our early calls to ioremap() that start growing down
- * from ioremap_base being run into the VM area allocations (growing upwards
+ * from IOREMAP_TOP being run into the VM area allocations (growing upwards
  * from VMALLOC_START).  For this reason we have ioremap_bot to check when
  * we actually run into our mappings setup in the early boot with the VM
  * system.  This really does become a problem for machines with good amounts
@@ -309,7 +309,8 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
 #define pte_index(address)             \
        (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, addr)   \
-       ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
+       (pmd_bad(*(dir)) ? NULL : (pte_t *)pmd_page_vaddr(*(dir)) + \
+                                 pte_index(addr))
 #define pte_offset_map(dir, addr)              \
        ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr))
 #define pte_unmap(pte)         kunmap_atomic(pte)
index b9f734d..10debb9 100644 (file)
 #ifndef __ASSEMBLY__
 /* pte_clear moved to later in this file */
 
+/* Pointers in the page table tree are virtual addresses */
+#define __pgtable_ptr_val(ptr) ((unsigned long)(ptr))
+
 #define PMD_BAD_BITS           (PTE_TABLE_SIZE-1)
 #define PUD_BAD_BITS           (PMD_TABLE_SIZE-1)
 
index 07a99e6..9d86c66 100644 (file)
@@ -248,6 +248,7 @@ extern int opal_elog_init(void);
 extern void opal_platform_dump_init(void);
 extern void opal_sys_param_init(void);
 extern void opal_msglog_init(void);
+extern void opal_msglog_sysfs_init(void);
 extern int opal_async_comp_init(void);
 extern int opal_sensor_init(void);
 extern int opal_hmi_handler_init(void);
@@ -273,6 +274,8 @@ void opal_free_sg_list(struct opal_sg_list *sg);
 
 extern int opal_error_code(int rc);
 
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
index e34124f..ab3d897 100644 (file)
@@ -271,6 +271,13 @@ extern long long virt_phys_offset;
 #else
 #define PD_HUGE 0x80000000
 #endif
+
+#else  /* CONFIG_PPC_BOOK3S_64 */
+/*
+ * Book3S 64 stores real addresses in the hugepd entries to
+ * avoid overlaps with _PAGE_PRESENT and _PAGE_PTE.
+ */
+#define HUGEPD_ADDR_MASK       (0x0ffffffffffffffful & ~HUGEPD_SHIFT_MASK)
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
 /*
@@ -281,109 +288,7 @@ extern long long virt_phys_offset;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_STRICT_MM_TYPECHECKS
-/* These are used to make use of C type-checking. */
-
-/* PTE level */
-typedef struct { pte_basic_t pte; } pte_t;
-#define __pte(x)       ((pte_t) { (x) })
-static inline pte_basic_t pte_val(pte_t x)
-{
-       return x.pte;
-}
-
-/* 64k pages additionally define a bigger "real PTE" type that gathers
- * the "second half" part of the PTE for pseudo 64k pages
- */
-#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
-typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
-#else
-typedef struct { pte_t pte; } real_pte_t;
-#endif
-
-/* PMD level */
-#ifdef CONFIG_PPC64
-typedef struct { unsigned long pmd; } pmd_t;
-#define __pmd(x)       ((pmd_t) { (x) })
-static inline unsigned long pmd_val(pmd_t x)
-{
-       return x.pmd;
-}
-
-/* PUD level exusts only on 4k pages */
-#ifndef CONFIG_PPC_64K_PAGES
-typedef struct { unsigned long pud; } pud_t;
-#define __pud(x)       ((pud_t) { (x) })
-static inline unsigned long pud_val(pud_t x)
-{
-       return x.pud;
-}
-#endif /* !CONFIG_PPC_64K_PAGES */
-#endif /* CONFIG_PPC64 */
-
-/* PGD level */
-typedef struct { unsigned long pgd; } pgd_t;
-#define __pgd(x)       ((pgd_t) { (x) })
-static inline unsigned long pgd_val(pgd_t x)
-{
-       return x.pgd;
-}
-
-/* Page protection bits */
-typedef struct { unsigned long pgprot; } pgprot_t;
-#define pgprot_val(x)  ((x).pgprot)
-#define __pgprot(x)    ((pgprot_t) { (x) })
-
-#else
-
-/*
- * .. while these make it easier on the compiler
- */
-
-typedef pte_basic_t pte_t;
-#define __pte(x)       (x)
-static inline pte_basic_t pte_val(pte_t pte)
-{
-       return pte;
-}
-
-#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
-typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
-#else
-typedef pte_t real_pte_t;
-#endif
-
-
-#ifdef CONFIG_PPC64
-typedef unsigned long pmd_t;
-#define __pmd(x)       (x)
-static inline unsigned long pmd_val(pmd_t pmd)
-{
-       return pmd;
-}
-
-#ifndef CONFIG_PPC_64K_PAGES
-typedef unsigned long pud_t;
-#define __pud(x)       (x)
-static inline unsigned long pud_val(pud_t pud)
-{
-       return pud;
-}
-#endif /* !CONFIG_PPC_64K_PAGES */
-#endif /* CONFIG_PPC64 */
-
-typedef unsigned long pgd_t;
-#define __pgd(x)       (x)
-static inline unsigned long pgd_val(pgd_t pgd)
-{
-       return pgd;
-}
-
-typedef unsigned long pgprot_t;
-#define pgprot_val(x)  (x)
-#define __pgprot(x)    (x)
-
-#endif
+#include <asm/pgtable-types.h>
 
 typedef struct { signed long pd; } hugepd_t;
 
index 68d73b2..6a8e179 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_POWERPC_PAGE_32_H
 #define _ASM_POWERPC_PAGE_32_H
 
+#include <asm/cache.h>
+
 #if defined(CONFIG_PHYSICAL_ALIGN) && (CONFIG_PHYSICAL_START != 0)
 #if (CONFIG_PHYSICAL_START % CONFIG_PHYSICAL_ALIGN) != 0
 #error "CONFIG_PHYSICAL_START must be a multiple of CONFIG_PHYSICAL_ALIGN"
@@ -36,9 +38,18 @@ typedef unsigned long long pte_basic_t;
 typedef unsigned long pte_basic_t;
 #endif
 
-struct page;
-extern void clear_pages(void *page, int order);
-static inline void clear_page(void *page) { clear_pages(page, 0); }
+/*
+ * Clear page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced).  This only works on cacheable memory.
+ */
+static inline void clear_page(void *addr)
+{
+       unsigned int i;
+
+       for (i = 0; i < PAGE_SIZE / L1_CACHE_BYTES; i++, addr += L1_CACHE_BYTES)
+               dcbz(addr);
+}
 extern void copy_page(void *to, void *from);
 
 #include <asm-generic/getorder.h>
index 78968c1..f5056e3 100644 (file)
@@ -211,15 +211,16 @@ struct pci_dn {
 #define IODA_INVALID_PE                (-1)
 #ifdef CONFIG_PPC_POWERNV
        int     pe_number;
+       int     vf_index;               /* VF index in the PF */
 #ifdef CONFIG_PCI_IOV
        u16     vfs_expanded;           /* number of VFs IOV BAR expanded */
        u16     num_vfs;                /* number of VFs enabled*/
-       int     offset;                 /* PE# for the first VF PE */
-#define M64_PER_IOV 4
-       int     m64_per_iov;
+       int     *pe_num_map;            /* PE# for the first VF PE or array */
+       bool    m64_single_mode;        /* Use M64 BAR in Single Mode */
 #define IODA_INVALID_M64        (-1)
-       int     m64_wins[PCI_SRIOV_NUM_BARS][M64_PER_IOV];
+       int     (*m64_map)[PCI_SRIOV_NUM_BARS];
 #endif /* CONFIG_PCI_IOV */
+       int     mps;                    /* Maximum Payload Size */
 #endif
        struct list_head child_list;
        struct list_head list;
index 8146221..e157489 100644 (file)
@@ -136,16 +136,24 @@ extern ssize_t power_events_sysfs_show(struct device *dev,
  * event 'cpu-cycles' can have two entries in sysfs: 'cpu-cycles' and
  * 'PM_CYC' where the latter is the name by which the event is known in
  * POWER CPU specification.
+ *
+ * Similarly, some hardware and cache events use the same event code. Eg.
+ * on POWER8, both "cache-references" and "L1-dcache-loads" events refer
+ * to the same event, PM_LD_REF_L1.  The suffix, allows us to have two
+ * sysfs objects for the same event and thus two entries/aliases in sysfs.
  */
 #define        EVENT_VAR(_id, _suffix)         event_attr_##_id##_suffix
 #define        EVENT_PTR(_id, _suffix)         &EVENT_VAR(_id, _suffix).attr.attr
 
 #define        EVENT_ATTR(_name, _id, _suffix)                                 \
-       PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_##_id,       \
+       PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), _id,             \
                        power_events_sysfs_show)
 
 #define        GENERIC_EVENT_ATTR(_name, _id)  EVENT_ATTR(_name, _id, _g)
 #define        GENERIC_EVENT_PTR(_id)          EVENT_PTR(_id, _g)
 
+#define        CACHE_EVENT_ATTR(_name, _id)    EVENT_ATTR(_name, _id, _c)
+#define        CACHE_EVENT_PTR(_id)            EVENT_PTR(_id, _c)
+
 #define        POWER_EVENT_ATTR(_name, _id)    EVENT_ATTR(_name, _id, _p)
 #define        POWER_EVENT_PTR(_id)            EVENT_PTR(_id, _p)
index 69ef28a..8d5fc3a 100644 (file)
@@ -53,7 +53,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 
 #ifndef CONFIG_PPC_64K_PAGES
 
-#define pgd_populate(MM, PGD, PUD)     pgd_set(PGD, (unsigned long)PUD)
+#define pgd_populate(MM, PGD, PUD)     pgd_set(PGD, __pgtable_ptr_val(PUD))
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
@@ -68,19 +68,19 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
 
 static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 {
-       pud_set(pud, (unsigned long)pmd);
+       pud_set(pud, __pgtable_ptr_val(pmd));
 }
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
                                       pte_t *pte)
 {
-       pmd_set(pmd, (unsigned long)pte);
+       pmd_set(pmd, __pgtable_ptr_val(pte));
 }
 
 static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
                                pgtable_t pte_page)
 {
-       pmd_set(pmd, (unsigned long)page_address(pte_page));
+       pmd_set(pmd, __pgtable_ptr_val(page_address(pte_page)));
 }
 
 #define pmd_pgtable(pmd) pmd_page(pmd)
@@ -171,23 +171,45 @@ extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
 extern void __tlb_remove_table(void *_table);
 #endif
 
-#define pud_populate(mm, pud, pmd)     pud_set(pud, (unsigned long)pmd)
+#ifndef __PAGETABLE_PUD_FOLDED
+/* book3s 64 is 4 level page table */
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+       pgd_set(pgd, __pgtable_ptr_val(pud));
+}
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+       return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
+                               GFP_KERNEL|__GFP_REPEAT);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+       kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
+}
+#endif
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+       pud_set(pud, __pgtable_ptr_val(pmd));
+}
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
                                       pte_t *pte)
 {
-       pmd_set(pmd, (unsigned long)pte);
+       pmd_set(pmd, __pgtable_ptr_val(pte));
 }
 
 static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
                                pgtable_t pte_page)
 {
-       pmd_set(pmd, (unsigned long)pte_page);
+       pmd_set(pmd, __pgtable_ptr_val(pte_page));
 }
 
 static inline pgtable_t pmd_pgtable(pmd_t pmd)
 {
-       return (pgtable_t)(pmd_val(pmd) & ~PMD_MASKED_BITS);
+       return (pgtable_t)pmd_page_vaddr(pmd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
@@ -233,11 +255,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 
 #define __pmd_free_tlb(tlb, pmd, addr)               \
        pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX)
-#ifndef CONFIG_PPC_64K_PAGES
+#ifndef __PAGETABLE_PUD_FOLDED
 #define __pud_free_tlb(tlb, pud, addr)               \
        pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE)
 
-#endif /* CONFIG_PPC_64K_PAGES */
+#endif /* __PAGETABLE_PUD_FOLDED */
 
 #define check_pgt_cache()      do { } while (0)
 
diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
new file mode 100644 (file)
index 0000000..43140f8
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef _ASM_POWERPC_PGTABLE_TYPES_H
+#define _ASM_POWERPC_PGTABLE_TYPES_H
+
+#ifdef CONFIG_STRICT_MM_TYPECHECKS
+/* These are used to make use of C type-checking. */
+
+/* PTE level */
+typedef struct { pte_basic_t pte; } pte_t;
+#define __pte(x)       ((pte_t) { (x) })
+static inline pte_basic_t pte_val(pte_t x)
+{
+       return x.pte;
+}
+
+/* PMD level */
+#ifdef CONFIG_PPC64
+typedef struct { unsigned long pmd; } pmd_t;
+#define __pmd(x)       ((pmd_t) { (x) })
+static inline unsigned long pmd_val(pmd_t x)
+{
+       return x.pmd;
+}
+
+/*
+ * 64 bit hash always use 4 level table. Everybody else use 4 level
+ * only for 4K page size.
+ */
+#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES)
+typedef struct { unsigned long pud; } pud_t;
+#define __pud(x)       ((pud_t) { (x) })
+static inline unsigned long pud_val(pud_t x)
+{
+       return x.pud;
+}
+#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC64 */
+
+/* PGD level */
+typedef struct { unsigned long pgd; } pgd_t;
+#define __pgd(x)       ((pgd_t) { (x) })
+static inline unsigned long pgd_val(pgd_t x)
+{
+       return x.pgd;
+}
+
+/* Page protection bits */
+typedef struct { unsigned long pgprot; } pgprot_t;
+#define pgprot_val(x)  ((x).pgprot)
+#define __pgprot(x)    ((pgprot_t) { (x) })
+
+#else
+
+/*
+ * .. while these make it easier on the compiler
+ */
+
+typedef pte_basic_t pte_t;
+#define __pte(x)       (x)
+static inline pte_basic_t pte_val(pte_t pte)
+{
+       return pte;
+}
+
+#ifdef CONFIG_PPC64
+typedef unsigned long pmd_t;
+#define __pmd(x)       (x)
+static inline unsigned long pmd_val(pmd_t pmd)
+{
+       return pmd;
+}
+
+#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES)
+typedef unsigned long pud_t;
+#define __pud(x)       (x)
+static inline unsigned long pud_val(pud_t pud)
+{
+       return pud;
+}
+#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC64 */
+
+typedef unsigned long pgd_t;
+#define __pgd(x)       (x)
+static inline unsigned long pgd_val(pgd_t pgd)
+{
+       return pgd;
+}
+
+typedef unsigned long pgprot_t;
+#define pgprot_val(x)  (x)
+#define __pgprot(x)    (x)
+
+#endif /* CONFIG_STRICT_MM_TYPECHECKS */
+/*
+ * With hash config 64k pages additionally define a bigger "real PTE" type that
+ * gathers the "second half" part of the PTE for pseudo 64k pages
+ */
+#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#else
+typedef struct { pte_t pte; } real_pte_t;
+#endif
+#endif /* _ASM_POWERPC_PGTABLE_TYPES_H */
index 10902c9..9256979 100644 (file)
@@ -46,7 +46,7 @@
 
 /* PowerSurge are the first generation of PCI Pmacs. This include
  * all of the Grand-Central based machines. We currently don't
- * differenciate most of them.
+ * differentiate most of them.
  */
 #define PMAC_TYPE_PSURGE               0x10    /* PowerSurge */
 #define PMAC_TYPE_ANS                  0x11    /* Apple Network Server */
index ac23308..8ab8a1a 100644 (file)
@@ -236,7 +236,9 @@ struct thread_struct {
 #endif
        struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
        unsigned long   trap_nr;        /* last trap # on this thread */
+       u8 load_fp;
 #ifdef CONFIG_ALTIVEC
+       u8 load_vec;
        struct thread_vr_state vr_state;
        struct thread_vr_state *vr_save_area;
        unsigned long   vrsave;
index c4cb2ff..f5f4c66 100644 (file)
 #define MSR_HV         0
 #endif
 
+/*
+ * To be used in shared book E/book S, this avoids needing to worry about
+ * book S/book E in shared code
+ */
+#ifndef MSR_SPE
+#define MSR_SPE        0
+#endif
+
 #define MSR_VEC                __MASK(MSR_VEC_LG)      /* Enable AltiVec */
 #define MSR_VSX                __MASK(MSR_VSX_LG)      /* Enable VSX */
 #define MSR_POW                __MASK(MSR_POW_LG)      /* Enable Power Management */
 #define SPRN_TSCR      0x399   /* Thread Switch Control Register */
 
 #define SPRN_DEC       0x016           /* Decrement Register */
-#define SPRN_DER       0x095           /* Debug Enable Regsiter */
+#define SPRN_DER       0x095           /* Debug Enable Register */
 #define DER_RSTE       0x40000000      /* Reset Interrupt */
 #define DER_CHSTPE     0x20000000      /* Check Stop */
 #define DER_MCIE       0x10000000      /* Machine Check Interrupt */
 #define SPRN_DPDES     0x0B0           /* Directed Priv. Doorbell Exc. State */
 #define SPRN_EAR       0x11A           /* External Address Register */
 #define SPRN_HASH1     0x3D2           /* Primary Hash Address Register */
-#define SPRN_HASH2     0x3D3           /* Secondary Hash Address Resgister */
+#define SPRN_HASH2     0x3D3           /* Secondary Hash Address Register */
 #define SPRN_HID0      0x3F0           /* Hardware Implementation Register 0 */
 #define HID0_HDICE_SH  (63 - 23)       /* 970 HDEC interrupt enable */
 #define HID0_EMCP      (1<<31)         /* Enable Machine Check pin */
 #define ICTRL_EICP     0x00000100      /* enable icache par. check */
 #define SPRN_IMISS     0x3D4           /* Instruction TLB Miss Register */
 #define SPRN_IMMR      0x27E           /* Internal Memory Map Register */
-#define SPRN_L2CR      0x3F9           /* Level 2 Cache Control Regsiter */
+#define SPRN_L2CR      0x3F9           /* Level 2 Cache Control Register */
 #define SPRN_L2CR2     0x3f8
 #define L2CR_L2E               0x80000000      /* L2 enable */
 #define L2CR_L2PE              0x40000000      /* L2 parity enable */
 #define L2CR_L2DO_745x         0x00010000      /* L2 data only (745x) */
 #define L2CR_L2REP_745x                0x00001000      /* L2 repl. algorithm (745x) */
 #define L2CR_L2HWF_745x                0x00000800      /* L2 hardware flush (745x) */
-#define SPRN_L3CR              0x3FA   /* Level 3 Cache Control Regsiter */
+#define SPRN_L3CR              0x3FA   /* Level 3 Cache Control Register */
 #define L3CR_L3E               0x80000000      /* L3 enable */
 #define L3CR_L3PE              0x40000000      /* L3 data parity enable */
 #define L3CR_L3APE             0x20000000      /* L3 addr parity enable */
@@ -1211,9 +1219,11 @@ static inline void mtmsr_isync(unsigned long val)
 #define mfspr(rn)      ({unsigned long rval; \
                        asm volatile("mfspr %0," __stringify(rn) \
                                : "=r" (rval)); rval;})
+#ifndef mtspr
 #define mtspr(rn, v)   asm volatile("mtspr " __stringify(rn) ",%0" : \
                                     : "r" ((unsigned long)(v)) \
                                     : "memory")
+#endif
 
 extern void msr_check_and_set(unsigned long bits);
 extern bool strict_msr_control;
index e8ea346..94d01f8 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef _ASM_POWERPC_REG_8xx_H
 #define _ASM_POWERPC_REG_8xx_H
 
+#include <asm/mmu-8xx.h>
+
 /* Cache control on the MPC8xx is provided through some additional
  * special purpose registers.
  */
 #define SPRN_DC_ADR    569     /* Address needed for some commands */
 #define SPRN_DC_DAT    570     /* Read-only data register */
 
+/* Misc Debug */
+#define SPRN_DPDR      630
+#define SPRN_MI_CAM    816
+#define SPRN_MI_RAM0   817
+#define SPRN_MI_RAM1   818
+#define SPRN_MD_CAM    824
+#define SPRN_MD_RAM0   825
+#define SPRN_MD_RAM1   826
+
 /* Commands.  Only the first few are available to the instruction cache.
 */
 #define        IDC_ENABLE      0x02000000      /* Cache enable */
 #define DC_DFWT                0x40000000      /* Data cache is forced write through */
 #define DC_LES         0x20000000      /* Caches are little endian mode */
 
+#ifdef CONFIG_8xx_CPU6
+#define do_mtspr_cpu6(rn, rn_addr, v)  \
+       do {                                                            \
+               int _reg_cpu6 = rn_addr, _tmp_cpu6;             \
+               asm volatile("stw %0, %1;"                              \
+                            "lwz %0, %1;"                              \
+                            "mtspr " __stringify(rn) ",%2" :           \
+                            : "r" (_reg_cpu6), "m"(_tmp_cpu6),         \
+                              "r" ((unsigned long)(v))                 \
+                            : "memory");                               \
+       } while (0)
+
+#define do_mtspr(rn, v)        asm volatile("mtspr " __stringify(rn) ",%0" :   \
+                                    : "r" ((unsigned long)(v))         \
+                                    : "memory")
+#define mtspr(rn, v) \
+       do {                                                            \
+               if (rn == SPRN_IMMR)                                    \
+                       do_mtspr_cpu6(rn, 0x3d30, v);                   \
+               else if (rn == SPRN_IC_CST)                             \
+                       do_mtspr_cpu6(rn, 0x2110, v);                   \
+               else if (rn == SPRN_IC_ADR)                             \
+                       do_mtspr_cpu6(rn, 0x2310, v);                   \
+               else if (rn == SPRN_IC_DAT)                             \
+                       do_mtspr_cpu6(rn, 0x2510, v);                   \
+               else if (rn == SPRN_DC_CST)                             \
+                       do_mtspr_cpu6(rn, 0x3110, v);                   \
+               else if (rn == SPRN_DC_ADR)                             \
+                       do_mtspr_cpu6(rn, 0x3310, v);                   \
+               else if (rn == SPRN_DC_DAT)                             \
+                       do_mtspr_cpu6(rn, 0x3510, v);                   \
+               else if (rn == SPRN_MI_CTR)                             \
+                       do_mtspr_cpu6(rn, 0x2180, v);                   \
+               else if (rn == SPRN_MI_AP)                              \
+                       do_mtspr_cpu6(rn, 0x2580, v);                   \
+               else if (rn == SPRN_MI_EPN)                             \
+                       do_mtspr_cpu6(rn, 0x2780, v);                   \
+               else if (rn == SPRN_MI_TWC)                             \
+                       do_mtspr_cpu6(rn, 0x2b80, v);                   \
+               else if (rn == SPRN_MI_RPN)                             \
+                       do_mtspr_cpu6(rn, 0x2d80, v);                   \
+               else if (rn == SPRN_MI_CAM)                             \
+                       do_mtspr_cpu6(rn, 0x2190, v);                   \
+               else if (rn == SPRN_MI_RAM0)                            \
+                       do_mtspr_cpu6(rn, 0x2390, v);                   \
+               else if (rn == SPRN_MI_RAM1)                            \
+                       do_mtspr_cpu6(rn, 0x2590, v);                   \
+               else if (rn == SPRN_MD_CTR)                             \
+                       do_mtspr_cpu6(rn, 0x3180, v);                   \
+               else if (rn == SPRN_M_CASID)                            \
+                       do_mtspr_cpu6(rn, 0x3380, v);                   \
+               else if (rn == SPRN_MD_AP)                              \
+                       do_mtspr_cpu6(rn, 0x3580, v);                   \
+               else if (rn == SPRN_MD_EPN)                             \
+                       do_mtspr_cpu6(rn, 0x3780, v);                   \
+               else if (rn == SPRN_M_TWB)                              \
+                       do_mtspr_cpu6(rn, 0x3980, v);                   \
+               else if (rn == SPRN_MD_TWC)                             \
+                       do_mtspr_cpu6(rn, 0x3b80, v);                   \
+               else if (rn == SPRN_MD_RPN)                             \
+                       do_mtspr_cpu6(rn, 0x3d80, v);                   \
+               else if (rn == SPRN_M_TW)                               \
+                       do_mtspr_cpu6(rn, 0x3f80, v);                   \
+               else if (rn == SPRN_MD_CAM)                             \
+                       do_mtspr_cpu6(rn, 0x3190, v);                   \
+               else if (rn == SPRN_MD_RAM0)                            \
+                       do_mtspr_cpu6(rn, 0x3390, v);                   \
+               else if (rn == SPRN_MD_RAM1)                            \
+                       do_mtspr_cpu6(rn, 0x3590, v);                   \
+               else if (rn == SPRN_DEC)                                \
+                       do_mtspr_cpu6(rn, 0x2c00, v);                   \
+               else if (rn == SPRN_TBWL)                               \
+                       do_mtspr_cpu6(rn, 0x3880, v);                   \
+               else if (rn == SPRN_TBWU)                               \
+                       do_mtspr_cpu6(rn, 0x3a80, v);                   \
+               else if (rn == SPRN_DPDR)                               \
+                       do_mtspr_cpu6(rn, 0x2d30, v);                   \
+               else                                                    \
+                       do_mtspr(rn, v);                                \
+       } while (0)
+#endif
+
 #endif /* _ASM_POWERPC_REG_8xx_H */
index 2fef74b..737e012 100644 (file)
 #define SPRN_CDBCR     0x3D7   /* Cache Debug Control Register */
 #define SPRN_TBHI      0x3DC   /* Time Base High */
 #define SPRN_TBLO      0x3DD   /* Time Base Low */
-#define SPRN_DBCR      0x3F2   /* Debug Control Regsiter */
+#define SPRN_DBCR      0x3F2   /* Debug Control Register */
 #define SPRN_PBL1      0x3FC   /* Protection Bound Lower 1 */
 #define SPRN_PBL2      0x3FE   /* Protection Bound Lower 2 */
 #define SPRN_PBU1      0x3FD   /* Protection Bound Upper 1 */
index a5e930a..abf5866 100644 (file)
@@ -22,6 +22,18 @@ static inline int in_kernel_text(unsigned long addr)
        return 0;
 }
 
+static inline unsigned long kernel_toc_addr(void)
+{
+       /* Defined by the linker, see vmlinux.lds.S */
+       extern unsigned long __toc_start;
+
+       /*
+        * The TOC register (r2) points 32kB into the TOC, so that 64kB of
+        * the TOC can be addressed using a single machine instruction.
+        */
+       return (unsigned long)(&__toc_start) + 0x8000UL;
+}
+
 static inline int overlaps_interrupt_vector_text(unsigned long start,
                                                        unsigned long end)
 {
index 78083ed..e1afd4c 100644 (file)
@@ -67,6 +67,9 @@ void generic_cpu_die(unsigned int cpu);
 void generic_set_cpu_dead(unsigned int cpu);
 void generic_set_cpu_up(unsigned int cpu);
 int generic_check_cpu_restart(unsigned int cpu);
+int is_cpu_dead(unsigned int cpu);
+#else
+#define generic_set_cpu_up(i)  do { } while (0)
 #endif
 
 #ifdef CONFIG_PPC64
@@ -201,6 +204,7 @@ extern void generic_secondary_thread_init(void);
 extern unsigned long __secondary_hold_spinloop;
 extern unsigned long __secondary_hold_acknowledge;
 extern char __secondary_hold;
+extern unsigned int booting_thread_hwid;
 
 extern void __early_start(void);
 #endif /* __ASSEMBLY__ */
index 37d2da6..f280dd1 100644 (file)
   *
   * The Darwin I2C driver is less subtle though. On any non-success status
   * from the response command, it waits 5ms and tries again up to 20 times,
-  * it doesn't differenciate between fatal errors or "busy" status.
+  * it doesn't differentiate between fatal errors or "busy" status.
   *
   * This driver provides an asynchronous paramblock based i2c command
   * interface to be used either directly by low level code or by a higher
index 5b268b6..17c8380 100644 (file)
@@ -28,12 +28,14 @@ extern void giveup_all(struct task_struct *);
 extern void enable_kernel_fp(void);
 extern void flush_fp_to_thread(struct task_struct *);
 extern void giveup_fpu(struct task_struct *);
-extern void __giveup_fpu(struct task_struct *);
+extern void save_fpu(struct task_struct *);
 static inline void disable_kernel_fp(void)
 {
        msr_check_and_clear(MSR_FP);
 }
 #else
+static inline void __giveup_fpu(struct task_struct *t) { }
+static inline void save_fpu(struct task_struct *t) { }
 static inline void flush_fp_to_thread(struct task_struct *t) { }
 #endif
 
@@ -41,18 +43,19 @@ static inline void flush_fp_to_thread(struct task_struct *t) { }
 extern void enable_kernel_altivec(void);
 extern void flush_altivec_to_thread(struct task_struct *);
 extern void giveup_altivec(struct task_struct *);
-extern void __giveup_altivec(struct task_struct *);
+extern void save_altivec(struct task_struct *);
 static inline void disable_kernel_altivec(void)
 {
        msr_check_and_clear(MSR_VEC);
 }
+#else
+static inline void save_altivec(struct task_struct *t) { }
+static inline void __giveup_altivec(struct task_struct *t) { }
 #endif
 
 #ifdef CONFIG_VSX
 extern void enable_kernel_vsx(void);
 extern void flush_vsx_to_thread(struct task_struct *);
-extern void giveup_vsx(struct task_struct *);
-extern void __giveup_vsx(struct task_struct *);
 static inline void disable_kernel_vsx(void)
 {
        msr_check_and_clear(MSR_FP|MSR_VEC|MSR_VSX);
@@ -68,6 +71,8 @@ static inline void disable_kernel_spe(void)
 {
        msr_check_and_clear(MSR_SPE);
 }
+#else
+static inline void __giveup_spe(struct task_struct *t) { }
 #endif
 
 static inline void clear_task_ebb(struct task_struct *t)
index 2d7109a..1092fdd 100644 (file)
@@ -31,8 +31,6 @@ extern void tick_broadcast_ipi_handler(void);
 
 extern void generic_calibrate_decr(void);
 
-extern void set_dec_cpu6(unsigned int val);
-
 /* Some sane defaults: 125 MHz timebase, 1GHz processor */
 extern unsigned long ppc_proc_freq;
 #define DEFAULT_PROC_FREQ      (DEFAULT_TB_FREQ * 8)
@@ -166,14 +164,12 @@ static inline void set_dec(int val)
 {
 #if defined(CONFIG_40x)
        mtspr(SPRN_PIT, val);
-#elif defined(CONFIG_8xx_CPU6)
-       set_dec_cpu6(val - 1);
 #else
 #ifndef CONFIG_BOOKE
        --val;
 #endif
        mtspr(SPRN_DEC, val);
-#endif /* not 40x or 8xx_CPU6 */
+#endif /* not 40x */
 }
 
 static inline unsigned long tb_ticks_since(unsigned long tstamp)
index 23d351c..9f77f85 100644 (file)
@@ -78,97 +78,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
 }
 
 #elif defined(CONFIG_PPC_STD_MMU_64)
-
-#define MMU_NO_CONTEXT         0
-
-/*
- * TLB flushing for 64-bit hash-MMU CPUs
- */
-
-#include <linux/percpu.h>
-#include <asm/page.h>
-
-#define PPC64_TLB_BATCH_NR 192
-
-struct ppc64_tlb_batch {
-       int                     active;
-       unsigned long           index;
-       struct mm_struct        *mm;
-       real_pte_t              pte[PPC64_TLB_BATCH_NR];
-       unsigned long           vpn[PPC64_TLB_BATCH_NR];
-       unsigned int            psize;
-       int                     ssize;
-};
-DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
-
-extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
-
-#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
-
-static inline void arch_enter_lazy_mmu_mode(void)
-{
-       struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
-
-       batch->active = 1;
-}
-
-static inline void arch_leave_lazy_mmu_mode(void)
-{
-       struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
-
-       if (batch->index)
-               __flush_tlb_pending(batch);
-       batch->active = 0;
-}
-
-#define arch_flush_lazy_mmu_mode()      do {} while (0)
-
-
-extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
-                           int ssize, unsigned long flags);
-extern void flush_hash_range(unsigned long number, int local);
-extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
-                               pmd_t *pmdp, unsigned int psize, int ssize,
-                               unsigned long flags);
-
-static inline void local_flush_tlb_mm(struct mm_struct *mm)
-{
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-}
-
-static inline void local_flush_tlb_page(struct vm_area_struct *vma,
-                                       unsigned long vmaddr)
-{
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-                                 unsigned long vmaddr)
-{
-}
-
-static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
-                                        unsigned long vmaddr)
-{
-}
-
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-                                  unsigned long start, unsigned long end)
-{
-}
-
-static inline void flush_tlb_kernel_range(unsigned long start,
-                                         unsigned long end)
-{
-}
-
-/* Private function for use by PCI IO mapping code */
-extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
-                                    unsigned long end);
-extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd,
-                               unsigned long addr);
+#include <asm/book3s/64/tlbflush-hash.h>
 #else
 #error Unsupported MMU type
 #endif
index d12b11d..a1d1129 100644 (file)
 
 /* This one _might_ return the CPU number of the CPU reading it;
  * the bootROM decides whether to boot or to sleep/spinloop depending
- * on this register beeing 0 or not
+ * on this register being 0 or not
  */
 #define UNI_N_CPU_NUMBER               0x0050
 
index 2546048..04ef3ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Common definitions accross all variants of ICP and ICS interrupt
+ * Common definitions across all variants of ICP and ICS interrupt
  * controllers.
  */
 
index 7f9c74b..b4504f3 100644 (file)
@@ -78,7 +78,7 @@
 #define EV_SUCCESS             0
 #define EV_EPERM               1       /* Operation not permitted */
 #define EV_ENOENT              2       /*  Entry Not Found */
-#define EV_EIO                 3       /* I/O error occured */
+#define EV_EIO                 3       /* I/O error occurred */
 #define EV_EAGAIN              4       /* The operation had insufficient
                                         * resources to complete and should be
                                         * retried
@@ -89,7 +89,7 @@
 #define EV_ENODEV              7       /* No such device */
 #define EV_EINVAL              8       /* An argument supplied to the hcall
                                           was out of range or invalid */
-#define EV_INTERNAL            9       /* An internal error occured */
+#define EV_INTERNAL            9       /* An internal error occurred */
 #define EV_CONFIG              10      /* A configuration error was detected */
 #define EV_INVALID_STATE       11      /* The object is in an invalid state */
 #define EV_UNIMPLEMENTED       12      /* Unimplemented hypercall */
index 794f22a..2da380f 100644 (file)
@@ -16,14 +16,14 @@ endif
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
-CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog
-CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog
-CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog
-CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 # do not trace tracer code
-CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_ftrace.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 # timers used by tracing
-CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_time.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 endif
 
 obj-y                          := cputable.o ptrace.o syscalls.o \
index 07cebc3..0d0183d 100644 (file)
@@ -95,12 +95,14 @@ int main(void)
        DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state));
        DEFINE(THREAD_FPSAVEAREA, offsetof(struct thread_struct, fp_save_area));
        DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr));
+       DEFINE(THREAD_LOAD_FP, offsetof(struct thread_struct, load_fp));
 #ifdef CONFIG_ALTIVEC
        DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state));
        DEFINE(THREAD_VRSAVEAREA, offsetof(struct thread_struct, vr_save_area));
        DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
        DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
        DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr));
+       DEFINE(THREAD_LOAD_VEC, offsetof(struct thread_struct, load_vec));
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
        DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
@@ -374,6 +376,7 @@ int main(void)
        DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
        DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
        DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
+       DEFINE(CPU_DOWN_FLUSH, offsetof(struct cpu_spec, cpu_down_flush));
 
        DEFINE(pbe_address, offsetof(struct pbe, address));
        DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
index dddba3e..462aed9 100644 (file)
  *
  */
 
+#include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 #include <asm/mmu-book3e.h>
 #include <asm/asm-offsets.h>
+#include <asm/mpc85xx.h>
 
 _GLOBAL(__e500_icache_setup)
        mfspr   r0, SPRN_L1CSR1
@@ -233,3 +235,113 @@ _GLOBAL(__setup_cpu_e5500)
        mtlr    r5
        blr
 #endif
+
+/* flush L1 date cache, it can apply to e500v2, e500mc and e5500 */
+_GLOBAL(flush_dcache_L1)
+       mfmsr   r10
+       wrteei  0
+
+       mfspr   r3,SPRN_L1CFG0
+       rlwinm  r5,r3,9,3       /* Extract cache block size */
+       twlgti  r5,1            /* Only 32 and 64 byte cache blocks
+                                * are currently defined.
+                                */
+       li      r4,32
+       subfic  r6,r5,2         /* r6 = log2(1KiB / cache block size) -
+                                *      log2(number of ways)
+                                */
+       slw     r5,r4,r5        /* r5 = cache block size */
+
+       rlwinm  r7,r3,0,0xff    /* Extract number of KiB in the cache */
+       mulli   r7,r7,13        /* An 8-way cache will require 13
+                                * loads per set.
+                                */
+       slw     r7,r7,r6
+
+       /* save off HID0 and set DCFA */
+       mfspr   r8,SPRN_HID0
+       ori     r9,r8,HID0_DCFA@l
+       mtspr   SPRN_HID0,r9
+       isync
+
+       LOAD_REG_IMMEDIATE(r6, KERNELBASE)
+       mr      r4, r6
+       mtctr   r7
+
+1:     lwz     r3,0(r4)        /* Load... */
+       add     r4,r4,r5
+       bdnz    1b
+
+       msync
+       mr      r4, r6
+       mtctr   r7
+
+1:     dcbf    0,r4            /* ...and flush. */
+       add     r4,r4,r5
+       bdnz    1b
+
+       /* restore HID0 */
+       mtspr   SPRN_HID0,r8
+       isync
+
+       wrtee r10
+
+       blr
+
+has_L2_cache:
+       /* skip L2 cache on P2040/P2040E as they have no L2 cache */
+       mfspr   r3, SPRN_SVR
+       /* shift right by 8 bits and clear E bit of SVR */
+       rlwinm  r4, r3, 24, ~0x800
+
+       lis     r3, SVR_P2040@h
+       ori     r3, r3, SVR_P2040@l
+       cmpw    r4, r3
+       beq     1f
+
+       li      r3, 1
+       blr
+1:
+       li      r3, 0
+       blr
+
+/* flush backside L2 cache */
+flush_backside_L2_cache:
+       mflr    r10
+       bl      has_L2_cache
+       mtlr    r10
+       cmpwi   r3, 0
+       beq     2f
+
+       /* Flush the L2 cache */
+       mfspr   r3, SPRN_L2CSR0
+       ori     r3, r3, L2CSR0_L2FL@l
+       msync
+       isync
+       mtspr   SPRN_L2CSR0,r3
+       isync
+
+       /* check if it is complete */
+1:     mfspr   r3,SPRN_L2CSR0
+       andi.   r3, r3, L2CSR0_L2FL@l
+       bne     1b
+2:
+       blr
+
+_GLOBAL(cpu_down_flush_e500v2)
+       mflr r0
+       bl      flush_dcache_L1
+       mtlr r0
+       blr
+
+_GLOBAL(cpu_down_flush_e500mc)
+_GLOBAL(cpu_down_flush_e5500)
+       mflr r0
+       bl      flush_dcache_L1
+       bl      flush_backside_L2_cache
+       mtlr r0
+       blr
+
+/* L1 Data Cache of e6500 contains no modified data, no flush is required */
+_GLOBAL(cpu_down_flush_e6500)
+       blr
index 9c9b741..584e119 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
+#include <asm/book3s/64/mmu-hash.h>
 
 /* Entry: r3 = crap, r4 = ptr to cputable entry
  *
@@ -83,6 +84,39 @@ _GLOBAL(__restore_cpu_power8)
        mtlr    r11
        blr
 
+_GLOBAL(__setup_cpu_power9)
+       mflr    r11
+       bl      __init_FSCR
+       bl      __init_hvmode_206
+       mtlr    r11
+       beqlr
+       li      r0,0
+       mtspr   SPRN_LPID,r0
+       mfspr   r3,SPRN_LPCR
+       ori     r3, r3, LPCR_PECEDH
+       bl      __init_LPCR
+       bl      __init_HFSCR
+       bl      __init_tlb_power9
+       mtlr    r11
+       blr
+
+_GLOBAL(__restore_cpu_power9)
+       mflr    r11
+       bl      __init_FSCR
+       mfmsr   r3
+       rldicl. r0,r3,4,63
+       mtlr    r11
+       beqlr
+       li      r0,0
+       mtspr   SPRN_LPID,r0
+       mfspr   r3,SPRN_LPCR
+       ori     r3, r3, LPCR_PECEDH
+       bl      __init_LPCR
+       bl      __init_HFSCR
+       bl      __init_tlb_power9
+       mtlr    r11
+       blr
+
 __init_hvmode_206:
        /* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
        mfmsr   r3
@@ -139,7 +173,7 @@ __init_HFSCR:
  * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
  */
 __init_tlb_power7:
-       li      r6,128
+       li      r6,POWER7_TLB_SETS
        mtctr   r6
        li      r7,0xc00        /* IS field = 0b11 */
        ptesync
@@ -150,7 +184,18 @@ __init_tlb_power7:
 1:     blr
 
 __init_tlb_power8:
-       li      r6,512
+       li      r6,POWER8_TLB_SETS
+       mtctr   r6
+       li      r7,0xc00        /* IS field = 0b11 */
+       ptesync
+2:     tlbiel  r7
+       addi    r7,r7,0x1000
+       bdnz    2b
+       ptesync
+1:     blr
+
+__init_tlb_power9:
+       li      r6,POWER9_TLB_SETS_HASH
        mtctr   r6
        li      r7,0xc00        /* IS field = 0b11 */
        ptesync
index 7d80bfd..6c662b8 100644 (file)
@@ -70,9 +70,12 @@ extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power7(void);
 extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power8(void);
+extern void __setup_cpu_power9(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_power9(void);
 extern void __restore_cpu_a2(void);
 extern void __flush_tlb_power7(unsigned int action);
 extern void __flush_tlb_power8(unsigned int action);
+extern void __flush_tlb_power9(unsigned int action);
 extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
 extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
 #endif /* CONFIG_PPC64 */
@@ -116,6 +119,11 @@ extern void __restore_cpu_e6500(void);
 #define COMMON_USER_PA6T       (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
                                 PPC_FEATURE_TRUE_LE | \
                                 PPC_FEATURE_HAS_ALTIVEC_COMP)
+#define COMMON_USER_POWER9     COMMON_USER_POWER8
+#define COMMON_USER2_POWER9    (COMMON_USER2_POWER8 | \
+                                PPC_FEATURE2_ARCH_3_00 | \
+                                PPC_FEATURE2_HAS_IEEE128)
+
 #ifdef CONFIG_PPC_BOOK3E_64
 #define COMMON_USER_BOOKE      (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE)
 #else
@@ -499,6 +507,25 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
+       {       /* Power9 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x004e0000,
+               .cpu_name               = "POWER9 (raw)",
+               .cpu_features           = CPU_FTRS_POWER9,
+               .cpu_user_features      = COMMON_USER_POWER9,
+               .cpu_user_features2     = COMMON_USER2_POWER9,
+               .mmu_features           = MMU_FTRS_POWER9,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_IBM,
+               .oprofile_cpu_type      = "ppc64/power9",
+               .oprofile_type          = PPC_OPROFILE_INVALID,
+               .cpu_setup              = __setup_cpu_power9,
+               .cpu_restore            = __restore_cpu_power9,
+               .flush_tlb              = __flush_tlb_power9,
+               .platform               = "power9",
+       },
        {       /* Cell Broadband Engine */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x00700000,
@@ -2023,6 +2050,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_e500v2,
                .machine_check          = machine_check_e500,
                .platform               = "ppc8548",
+               .cpu_down_flush         = cpu_down_flush_e500v2,
        },
 #else
        {       /* e500mc */
@@ -2042,6 +2070,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_e500mc,
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce500mc",
+               .cpu_down_flush         = cpu_down_flush_e500mc,
        },
 #endif /* CONFIG_PPC_E500MC */
 #endif /* CONFIG_PPC32 */
@@ -2066,6 +2095,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce5500",
+               .cpu_down_flush         = cpu_down_flush_e5500,
        },
        {       /* e6500 */
                .pvr_mask               = 0xffff0000,
@@ -2088,6 +2118,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif
                .machine_check          = machine_check_e500mc,
                .platform               = "ppce6500",
+               .cpu_down_flush         = cpu_down_flush_e6500,
        },
 #endif /* CONFIG_PPC_E500MC */
 #ifdef CONFIG_PPC32
index 40e4d4a..6544017 100644 (file)
@@ -268,13 +268,6 @@ static void *eeh_dump_pe_log(void *data, void *flag)
        struct eeh_dev *edev, *tmp;
        size_t *plen = flag;
 
-       /* If the PE's config space is blocked, 0xFF's will be
-        * returned. It's pointless to collect the log in this
-        * case.
-        */
-       if (pe->state & EEH_PE_CFG_BLOCKED)
-               return NULL;
-
        eeh_pe_for_each_dev(pe, edev, tmp)
                *plen += eeh_dump_dev_log(edev, pci_regs_buf + *plen,
                                          EEH_PCI_REGS_LOG_LEN - *plen);
@@ -677,7 +670,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function)
        /* Check if the request is finished successfully */
        if (active_flag) {
                rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-               if (rc <= 0)
+               if (rc < 0)
                        return rc;
 
                if (rc & active_flag)
@@ -739,7 +732,7 @@ static void *eeh_restore_dev_state(void *data, void *userdata)
 }
 
 /**
- * pcibios_set_pcie_slot_reset - Set PCI-E reset state
+ * pcibios_set_pcie_reset_state - Set PCI-E reset state
  * @dev: pci device struct
  * @state: reset state to enter
  *
@@ -761,7 +754,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
        case pcie_deassert_reset:
                eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
                eeh_unfreeze_pe(pe, false);
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+               if (!(pe->type & EEH_PE_VF))
+                       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                eeh_pe_dev_traverse(pe, eeh_restore_dev_state, dev);
                eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
                break;
@@ -769,14 +763,16 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
                eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
-               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
+               if (!(pe->type & EEH_PE_VF))
+                       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_HOT);
                break;
        case pcie_warm_reset:
                eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
-               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
+               if (!(pe->type & EEH_PE_VF))
+                       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
                break;
        default:
@@ -1243,6 +1239,14 @@ void eeh_remove_device(struct pci_dev *dev)
         * from the parent PE during the BAR resotre.
         */
        edev->pdev = NULL;
+
+       /*
+        * The flag "in_error" is used to trace EEH devices for VFs
+        * in error state or not. It's set in eeh_report_error(). If
+        * it's not set, eeh_report_{reset,resume}() won't be called
+        * for the VF EEH device.
+        */
+       edev->in_error = false;
        dev->dev.archdata.edev = NULL;
        if (!(edev->pe->state & EEH_PE_KEEP))
                eeh_rmv_from_parent_pe(edev);
@@ -1537,6 +1541,17 @@ int eeh_pe_get_state(struct eeh_pe *pe)
        if (!eeh_ops || !eeh_ops->get_state)
                return -ENOENT;
 
+       /*
+        * If the parent PE is owned by the host kernel and is undergoing
+        * error recovery, we should return the PE state as temporarily
+        * unavailable so that the error recovery on the guest is suspended
+        * until the recovery completes on the host.
+        */
+       if (pe->parent &&
+           !(pe->state & EEH_PE_REMOVED) &&
+           (pe->parent->state & (EEH_PE_ISOLATED | EEH_PE_RECOVERING)))
+               return EEH_PE_STATE_UNAVAIL;
+
        result = eeh_ops->get_state(pe, NULL);
        rst_active = !!(result & EEH_STATE_RESET_ACTIVE);
        dma_en = !!(result & EEH_STATE_DMA_ENABLED);
index a1e86e1..ddbcfab 100644 (file)
@@ -195,8 +195,11 @@ static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
                return;
        }
 
-       /* Walk resources on this device, poke them into the tree */
-       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+       /*
+        * Walk resources on this device, poke the first 7 (6 normal BAR and 1
+        * ROM BAR) into the tree.
+        */
+       for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
                resource_size_t start = pci_resource_start(dev,i);
                resource_size_t end = pci_resource_end(dev,i);
                unsigned long flags = pci_resource_flags(dev,i);
@@ -222,10 +225,6 @@ void eeh_addr_cache_insert_dev(struct pci_dev *dev)
 {
        unsigned long flags;
 
-       /* Ignore PCI bridges */
-       if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
-               return;
-
        spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
        __eeh_addr_cache_insert_dev(dev);
        spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
index aabba94..7815095 100644 (file)
@@ -67,6 +67,7 @@ void *eeh_dev_init(struct pci_dn *pdn, void *data)
        edev->pdn = pdn;
        edev->phb = phb;
        INIT_LIST_HEAD(&edev->list);
+       INIT_LIST_HEAD(&edev->rmv_list);
 
        return NULL;
 }
index 650cfb3..fb6207d 100644 (file)
 #include <asm/prom.h>
 #include <asm/rtas.h>
 
+struct eeh_rmv_data {
+       struct list_head edev_list;
+       int removed;
+};
+
 /**
  * eeh_pcid_name - Retrieve name of PCI device driver
  * @pdev: PCI device
@@ -190,7 +195,7 @@ static void *eeh_report_error(void *data, void *userdata)
        enum pci_ers_result rc, *res = userdata;
        struct pci_driver *driver;
 
-       if (!dev || eeh_dev_removed(edev))
+       if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
                return NULL;
        dev->error_state = pci_channel_io_frozen;
 
@@ -211,6 +216,7 @@ static void *eeh_report_error(void *data, void *userdata)
        if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
        if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
+       edev->in_error = true;
        eeh_pcid_put(dev);
        return NULL;
 }
@@ -231,7 +237,7 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
        enum pci_ers_result rc, *res = userdata;
        struct pci_driver *driver;
 
-       if (!dev || eeh_dev_removed(edev))
+       if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
                return NULL;
 
        driver = eeh_pcid_get(dev);
@@ -271,7 +277,7 @@ static void *eeh_report_reset(void *data, void *userdata)
        enum pci_ers_result rc, *res = userdata;
        struct pci_driver *driver;
 
-       if (!dev || eeh_dev_removed(edev))
+       if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
                return NULL;
        dev->error_state = pci_channel_io_normal;
 
@@ -282,7 +288,8 @@ static void *eeh_report_reset(void *data, void *userdata)
 
        if (!driver->err_handler ||
            !driver->err_handler->slot_reset ||
-           (edev->mode & EEH_DEV_NO_HANDLER)) {
+           (edev->mode & EEH_DEV_NO_HANDLER) ||
+           (!edev->in_error)) {
                eeh_pcid_put(dev);
                return NULL;
        }
@@ -326,20 +333,23 @@ static void *eeh_report_resume(void *data, void *userdata)
 {
        struct eeh_dev *edev = (struct eeh_dev *)data;
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+       bool was_in_error;
        struct pci_driver *driver;
 
-       if (!dev || eeh_dev_removed(edev))
+       if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
                return NULL;
        dev->error_state = pci_channel_io_normal;
 
        driver = eeh_pcid_get(dev);
        if (!driver) return NULL;
 
+       was_in_error = edev->in_error;
+       edev->in_error = false;
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
            !driver->err_handler->resume ||
-           (edev->mode & EEH_DEV_NO_HANDLER)) {
+           (edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) {
                edev->mode &= ~EEH_DEV_NO_HANDLER;
                eeh_pcid_put(dev);
                return NULL;
@@ -365,7 +375,7 @@ static void *eeh_report_failure(void *data, void *userdata)
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
        struct pci_driver *driver;
 
-       if (!dev || eeh_dev_removed(edev))
+       if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
                return NULL;
        dev->error_state = pci_channel_io_perm_failure;
 
@@ -386,12 +396,40 @@ static void *eeh_report_failure(void *data, void *userdata)
        return NULL;
 }
 
+static void *eeh_add_virt_device(void *data, void *userdata)
+{
+       struct pci_driver *driver;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+       struct pci_dn *pdn = eeh_dev_to_pdn(edev);
+
+       if (!(edev->physfn)) {
+               pr_warn("%s: EEH dev %04x:%02x:%02x.%01x not for VF\n",
+                       __func__, edev->phb->global_number, pdn->busno,
+                       PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
+               return NULL;
+       }
+
+       driver = eeh_pcid_get(dev);
+       if (driver) {
+               eeh_pcid_put(dev);
+               if (driver->err_handler)
+                       return NULL;
+       }
+
+#ifdef CONFIG_PPC_POWERNV
+       pci_iov_add_virtfn(edev->physfn, pdn->vf_index, 0);
+#endif
+       return NULL;
+}
+
 static void *eeh_rmv_device(void *data, void *userdata)
 {
        struct pci_driver *driver;
        struct eeh_dev *edev = (struct eeh_dev *)data;
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
-       int *removed = (int *)userdata;
+       struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata;
+       int *removed = rmv_data ? &rmv_data->removed : NULL;
 
        /*
         * Actually, we should remove the PCI bridges as well.
@@ -416,7 +454,11 @@ static void *eeh_rmv_device(void *data, void *userdata)
        driver = eeh_pcid_get(dev);
        if (driver) {
                eeh_pcid_put(dev);
-               if (driver->err_handler &&
+               if (removed &&
+                   eeh_pe_passed(edev->pe))
+                       return NULL;
+               if (removed &&
+                   driver->err_handler &&
                    driver->err_handler->error_detected &&
                    driver->err_handler->slot_reset)
                        return NULL;
@@ -427,11 +469,29 @@ static void *eeh_rmv_device(void *data, void *userdata)
                 pci_name(dev));
        edev->bus = dev->bus;
        edev->mode |= EEH_DEV_DISCONNECTED;
-       (*removed)++;
+       if (removed)
+               (*removed)++;
 
-       pci_lock_rescan_remove();
-       pci_stop_and_remove_bus_device(dev);
-       pci_unlock_rescan_remove();
+       if (edev->physfn) {
+#ifdef CONFIG_PPC_POWERNV
+               struct pci_dn *pdn = eeh_dev_to_pdn(edev);
+
+               pci_iov_remove_virtfn(edev->physfn, pdn->vf_index, 0);
+               edev->pdev = NULL;
+
+               /*
+                * We have to set the VF PE number to invalid one, which is
+                * required to plug the VF successfully.
+                */
+               pdn->pe_number = IODA_INVALID_PE;
+#endif
+               if (rmv_data)
+                       list_add(&edev->rmv_list, &rmv_data->edev_list);
+       } else {
+               pci_lock_rescan_remove();
+               pci_stop_and_remove_bus_device(dev);
+               pci_unlock_rescan_remove();
+       }
 
        return NULL;
 }
@@ -545,11 +605,13 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
  * During the reset, udev might be invoked because those affected
  * PCI devices will be removed and then added.
  */
-static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
+static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
+                               struct eeh_rmv_data *rmv_data)
 {
        struct pci_bus *frozen_bus = eeh_pe_bus_get(pe);
        struct timeval tstamp;
-       int cnt, rc, removed = 0;
+       int cnt, rc;
+       struct eeh_dev *edev;
 
        /* pcibios will clear the counter; save the value */
        cnt = pe->freeze_count;
@@ -563,12 +625,16 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         */
        eeh_pe_state_mark(pe, EEH_PE_KEEP);
        if (bus) {
-               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
-               pci_lock_rescan_remove();
-               pcibios_remove_pci_devices(bus);
-               pci_unlock_rescan_remove();
+               if (pe->type & EEH_PE_VF) {
+                       eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
+               } else {
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+                       pci_lock_rescan_remove();
+                       pcibios_remove_pci_devices(bus);
+                       pci_unlock_rescan_remove();
+               }
        } else if (frozen_bus) {
-               eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed);
+               eeh_pe_dev_traverse(pe, eeh_rmv_device, &rmv_data);
        }
 
        /*
@@ -610,14 +676,22 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
                 * PE. We should disconnect it so the binding can be
                 * rebuilt when adding PCI devices.
                 */
+               edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
                eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
-               pcibios_add_pci_devices(bus);
-       } else if (frozen_bus && removed) {
+               if (pe->type & EEH_PE_VF)
+                       eeh_add_virt_device(edev, NULL);
+               else
+                       pcibios_add_pci_devices(bus);
+       } else if (frozen_bus && rmv_data->removed) {
                pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
                ssleep(5);
 
+               edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
                eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
-               pcibios_add_pci_devices(frozen_bus);
+               if (pe->type & EEH_PE_VF)
+                       eeh_add_virt_device(edev, NULL);
+               else
+                       pcibios_add_pci_devices(frozen_bus);
        }
        eeh_pe_state_clear(pe, EEH_PE_KEEP);
 
@@ -636,8 +710,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 static void eeh_handle_normal_event(struct eeh_pe *pe)
 {
        struct pci_bus *frozen_bus;
+       struct eeh_dev *edev, *tmp;
        int rc = 0;
        enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+       struct eeh_rmv_data rmv_data = {LIST_HEAD_INIT(rmv_data.edev_list), 0};
 
        frozen_bus = eeh_pe_bus_get(pe);
        if (!frozen_bus) {
@@ -692,7 +768,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
         */
        if (result == PCI_ERS_RESULT_NONE) {
                pr_info("EEH: Reset with hotplug activity\n");
-               rc = eeh_reset_device(pe, frozen_bus);
+               rc = eeh_reset_device(pe, frozen_bus, NULL);
                if (rc) {
                        pr_warn("%s: Unable to reset, err=%d\n",
                                __func__, rc);
@@ -744,7 +820,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
        /* If any device called out for a reset, then reset the slot */
        if (result == PCI_ERS_RESULT_NEED_RESET) {
                pr_info("EEH: Reset without hotplug activity\n");
-               rc = eeh_reset_device(pe, NULL);
+               rc = eeh_reset_device(pe, NULL, &rmv_data);
                if (rc) {
                        pr_warn("%s: Cannot reset, err=%d\n",
                                __func__, rc);
@@ -764,6 +840,15 @@ static void eeh_handle_normal_event(struct eeh_pe *pe)
                goto hard_fail;
        }
 
+       /*
+        * For those hot removed VFs, we should add back them after PF get
+        * recovered properly.
+        */
+       list_for_each_entry_safe(edev, tmp, &rmv_data.edev_list, rmv_list) {
+               eeh_add_virt_device(edev, NULL);
+               list_del(&edev->rmv_list);
+       }
+
        /* Tell all device drivers that they can resume operations */
        pr_info("EEH: Notify device driver to resume\n");
        eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
@@ -803,12 +888,17 @@ perm_error:
         * the their PCI config any more.
         */
        if (frozen_bus) {
-               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
-               eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+               if (pe->type & EEH_PE_VF) {
+                       eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
+                       eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+               } else {
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+                       eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
 
-               pci_lock_rescan_remove();
-               pcibios_remove_pci_devices(frozen_bus);
-               pci_unlock_rescan_remove();
+                       pci_lock_rescan_remove();
+                       pcibios_remove_pci_devices(frozen_bus);
+                       pci_unlock_rescan_remove();
+               }
        }
 }
 
index 98f8180..eea48d8 100644 (file)
@@ -299,7 +299,10 @@ static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
         * EEH device already having associated PE, but
         * the direct parent EEH device doesn't have yet.
         */
-       pdn = pdn ? pdn->parent : NULL;
+       if (edev->physfn)
+               pdn = pci_get_pdn(edev->physfn);
+       else
+               pdn = pdn ? pdn->parent : NULL;
        while (pdn) {
                /* We're poking out of PCI territory */
                parent = pdn_to_eeh_dev(pdn);
@@ -382,7 +385,10 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
        }
 
        /* Create a new EEH PE */
-       pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
+       if (edev->physfn)
+               pe = eeh_pe_alloc(edev->phb, EEH_PE_VF);
+       else
+               pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
        if (!pe) {
                pr_err("%s: out of memory!\n", __func__);
                return -ENOMEM;
@@ -920,25 +926,21 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe)
  */
 struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
 {
-       struct pci_bus *bus = NULL;
        struct eeh_dev *edev;
        struct pci_dev *pdev;
 
-       if (pe->type & EEH_PE_PHB) {
-               bus = pe->phb->bus;
-       } else if (pe->type & EEH_PE_BUS ||
-                  pe->type & EEH_PE_DEVICE) {
-               if (pe->state & EEH_PE_PRI_BUS) {
-                       bus = pe->bus;
-                       goto out;
-               }
+       if (pe->type & EEH_PE_PHB)
+               return pe->phb->bus;
 
-               edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
-               pdev = eeh_dev_to_pci_dev(edev);
-               if (pdev)
-                       bus = pdev->bus;
-       }
+       /* The primary bus might be cached during probe time */
+       if (pe->state & EEH_PE_PRI_BUS)
+               return pe->bus;
 
-out:
-       return bus;
+       /* Retrieve the parent PCI bus of first (top) PCI device */
+       edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list);
+       pdev = eeh_dev_to_pci_dev(edev);
+       if (pdev)
+               return pdev->bus;
+
+       return NULL;
 }
index 0d525ce..9916d15 100644 (file)
@@ -210,7 +210,29 @@ system_call:                       /* label this so stack traces look sane */
        li      r11,-MAX_ERRNO
        andi.   r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
        bne-    syscall_exit_work
-       cmpld   r3,r11
+
+       andi.   r0,r8,MSR_FP
+       beq 2f
+#ifdef CONFIG_ALTIVEC
+       andis.  r0,r8,MSR_VEC@h
+       bne     3f
+#endif
+2:     addi    r3,r1,STACK_FRAME_OVERHEAD
+#ifdef CONFIG_PPC_BOOK3S
+       mtmsrd  r10,1           /* Restore RI */
+#endif
+       bl      restore_math
+#ifdef CONFIG_PPC_BOOK3S
+       ld      r10,PACAKMSR(r13)
+       li      r9,MSR_RI
+       andc    r11,r10,r9 /* Re-clear RI */
+       mtmsrd  r11,1
+#endif
+       ld      r8,_MSR(r1)
+       ld      r3,RESULT(r1)
+       li      r11,-MAX_ERRNO
+
+3:     cmpld   r3,r11
        ld      r5,_CCR(r1)
        bge-    syscall_error
 .Lsyscall_error_cont:
@@ -602,8 +624,8 @@ _GLOBAL(ret_from_except_lite)
 
        /* Check current_thread_info()->flags */
        andi.   r0,r4,_TIF_USER_WORK_MASK
-#ifdef CONFIG_PPC_BOOK3E
        bne     1f
+#ifdef CONFIG_PPC_BOOK3E
        /*
         * Check to see if the dbcr0 register is set up to debug.
         * Use the internal debug mode bit to do this.
@@ -618,7 +640,9 @@ _GLOBAL(ret_from_except_lite)
        mtspr   SPRN_DBSR,r10
        b       restore
 #else
-       beq     restore
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      restore_math
+       b       restore
 #endif
 1:     andi.   r0,r4,_TIF_NEED_RESCHED
        beq     2f
@@ -1143,8 +1167,12 @@ _GLOBAL(enter_prom)
 #ifdef CONFIG_DYNAMIC_FTRACE
 _GLOBAL(mcount)
 _GLOBAL(_mcount)
-       blr
+       mflr    r12
+       mtctr   r12
+       mtlr    r0
+       bctr
 
+#ifndef CC_USING_MPROFILE_KERNEL
 _GLOBAL_TOC(ftrace_caller)
        /* Taken from output of objdump from lib64/glibc */
        mflr    r3
@@ -1166,6 +1194,115 @@ _GLOBAL(ftrace_graph_stub)
        ld      r0, 128(r1)
        mtlr    r0
        addi    r1, r1, 112
+
+#else /* CC_USING_MPROFILE_KERNEL */
+/*
+ *
+ * ftrace_caller() is the function that replaces _mcount() when ftrace is
+ * active.
+ *
+ * We arrive here after a function A calls function B, and we are the trace
+ * function for B. When we enter r1 points to A's stack frame, B has not yet
+ * had a chance to allocate one yet.
+ *
+ * Additionally r2 may point either to the TOC for A, or B, depending on
+ * whether B did a TOC setup sequence before calling us.
+ *
+ * On entry the LR points back to the _mcount() call site, and r0 holds the
+ * saved LR as it was on entry to B, ie. the original return address at the
+ * call site in A.
+ *
+ * Our job is to save the register state into a struct pt_regs (on the stack)
+ * and then arrange for the ftrace function to be called.
+ */
+_GLOBAL(ftrace_caller)
+       /* Save the original return address in A's stack frame */
+       std     r0,LRSAVE(r1)
+
+       /* Create our stack frame + pt_regs */
+       stdu    r1,-SWITCH_FRAME_SIZE(r1)
+
+       /* Save all gprs to pt_regs */
+       SAVE_8GPRS(0,r1)
+       SAVE_8GPRS(8,r1)
+       SAVE_8GPRS(16,r1)
+       SAVE_8GPRS(24,r1)
+
+       /* Load special regs for save below */
+       mfmsr   r8
+       mfctr   r9
+       mfxer   r10
+       mfcr    r11
+
+       /* Get the _mcount() call site out of LR */
+       mflr    r7
+       /* Save it as pt_regs->nip & pt_regs->link */
+       std     r7, _NIP(r1)
+       std     r7, _LINK(r1)
+
+       /* Save callee's TOC in the ABI compliant location */
+       std     r2, 24(r1)
+       ld      r2,PACATOC(r13) /* get kernel TOC in r2 */
+
+       addis   r3,r2,function_trace_op@toc@ha
+       addi    r3,r3,function_trace_op@toc@l
+       ld      r5,0(r3)
+
+       /* Calculate ip from nip-4 into r3 for call below */
+       subi    r3, r7, MCOUNT_INSN_SIZE
+
+       /* Put the original return address in r4 as parent_ip */
+       mr      r4, r0
+
+       /* Save special regs */
+       std     r8, _MSR(r1)
+       std     r9, _CTR(r1)
+       std     r10, _XER(r1)
+       std     r11, _CCR(r1)
+
+       /* Load &pt_regs in r6 for call below */
+       addi    r6, r1 ,STACK_FRAME_OVERHEAD
+
+       /* ftrace_call(r3, r4, r5, r6) */
+.globl ftrace_call
+ftrace_call:
+       bl      ftrace_stub
+       nop
+
+       /* Load ctr with the possibly modified NIP */
+       ld      r3, _NIP(r1)
+       mtctr   r3
+
+       /* Restore gprs */
+       REST_8GPRS(0,r1)
+       REST_8GPRS(8,r1)
+       REST_8GPRS(16,r1)
+       REST_8GPRS(24,r1)
+
+       /* Restore callee's TOC */
+       ld      r2, 24(r1)
+
+       /* Pop our stack frame */
+       addi r1, r1, SWITCH_FRAME_SIZE
+
+       /* Restore original LR for return to B */
+       ld      r0, LRSAVE(r1)
+       mtlr    r0
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       stdu    r1, -112(r1)
+.globl ftrace_graph_call
+ftrace_graph_call:
+       b       ftrace_graph_stub
+_GLOBAL(ftrace_graph_stub)
+       addi    r1, r1, 112
+#endif
+
+       ld      r0,LRSAVE(r1)   /* restore callee's lr at _mcount site */
+       mtlr    r0
+       bctr                    /* jump after _mcount site */
+#endif /* CC_USING_MPROFILE_KERNEL */
+
 _GLOBAL(ftrace_stub)
        blr
 #else
@@ -1198,6 +1335,7 @@ _GLOBAL(ftrace_stub)
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifndef CC_USING_MPROFILE_KERNEL
 _GLOBAL(ftrace_graph_caller)
        /* load r4 with local address */
        ld      r4, 128(r1)
@@ -1222,6 +1360,56 @@ _GLOBAL(ftrace_graph_caller)
        addi    r1, r1, 112
        blr
 
+#else /* CC_USING_MPROFILE_KERNEL */
+_GLOBAL(ftrace_graph_caller)
+       /* with -mprofile-kernel, parameter regs are still alive at _mcount */
+       std     r10, 104(r1)
+       std     r9, 96(r1)
+       std     r8, 88(r1)
+       std     r7, 80(r1)
+       std     r6, 72(r1)
+       std     r5, 64(r1)
+       std     r4, 56(r1)
+       std     r3, 48(r1)
+
+       /* Save callee's TOC in the ABI compliant location */
+       std     r2, 24(r1)
+       ld      r2, PACATOC(r13)        /* get kernel TOC in r2 */
+
+       mfctr   r4              /* ftrace_caller has moved local addr here */
+       std     r4, 40(r1)
+       mflr    r3              /* ftrace_caller has restored LR from stack */
+       subi    r4, r4, MCOUNT_INSN_SIZE
+
+       bl      prepare_ftrace_return
+       nop
+
+       /*
+        * prepare_ftrace_return gives us the address we divert to.
+        * Change the LR to this.
+        */
+       mtlr    r3
+
+       ld      r0, 40(r1)
+       mtctr   r0
+       ld      r10, 104(r1)
+       ld      r9, 96(r1)
+       ld      r8, 88(r1)
+       ld      r7, 80(r1)
+       ld      r6, 72(r1)
+       ld      r5, 64(r1)
+       ld      r4, 56(r1)
+       ld      r3, 48(r1)
+
+       /* Restore callee's TOC */
+       ld      r2, 24(r1)
+
+       addi    r1, r1, 112
+       mflr    r0
+       std     r0, LRSAVE(r1)
+       bctr
+#endif /* CC_USING_MPROFILE_KERNEL */
+
 _GLOBAL(return_to_handler)
        /* need to save return values */
        std     r4,  -32(r1)
index 2117eac..15da2b5 100644 (file)
@@ -130,6 +130,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        or      r12,r12,r4
        std     r12,_MSR(r1)
 #endif
+       /* Don't care if r4 overflows, this is desired behaviour */
+       lbz     r4,THREAD_LOAD_FP(r5)
+       addi    r4,r4,1
+       stb     r4,THREAD_LOAD_FP(r5)
        addi    r10,r5,THREAD_FPSTATE
        lfd     fr0,FPSTATE_FPSCR(r10)
        MTFSF_L(fr0)
@@ -139,33 +143,20 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        blr
 
 /*
- * __giveup_fpu(tsk)
- * Disable FP for the task given as the argument,
- * and save the floating-point registers in its thread_struct.
+ * save_fpu(tsk)
+ * Save the floating-point registers in its thread_struct.
  * Enables the FPU for use in the kernel on return.
  */
-_GLOBAL(__giveup_fpu)
+_GLOBAL(save_fpu)
        addi    r3,r3,THREAD            /* want THREAD of task */
        PPC_LL  r6,THREAD_FPSAVEAREA(r3)
        PPC_LL  r5,PT_REGS(r3)
        PPC_LCMPI       0,r6,0
        bne     2f
        addi    r6,r3,THREAD_FPSTATE
-2:     PPC_LCMPI       0,r5,0
-       SAVE_32FPVSRS(0, R4, R6)
+2:     SAVE_32FPVSRS(0, R4, R6)
        mffs    fr0
        stfd    fr0,FPSTATE_FPSCR(r6)
-       beq     1f
-       PPC_LL  r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-       li      r3,MSR_FP|MSR_FE0|MSR_FE1
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-       oris    r3,r3,MSR_VSX@h
-END_FTR_SECTION_IFSET(CPU_FTR_VSX)
-#endif
-       andc    r4,r4,r3                /* disable FP for previous task */
-       PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
        blr
 
 /*
index 44d4d8e..9dac18d 100644 (file)
@@ -61,8 +61,11 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
                return -EFAULT;
 
        /* Make sure it is what we expect it to be */
-       if (replaced != old)
+       if (replaced != old) {
+               pr_err("%p: replaced (%#x) != old (%#x)",
+               (void *)ip, replaced, old);
                return -EINVAL;
+       }
 
        /* replace the text with the new text */
        if (patch_instruction((unsigned int *)ip, new))
@@ -106,14 +109,15 @@ static int
 __ftrace_make_nop(struct module *mod,
                  struct dyn_ftrace *rec, unsigned long addr)
 {
-       unsigned int op;
-       unsigned long entry, ptr;
+       unsigned long entry, ptr, tramp;
        unsigned long ip = rec->ip;
-       void *tramp;
+       unsigned int op, pop;
 
        /* read where this goes */
-       if (probe_kernel_read(&op, (void *)ip, sizeof(int)))
+       if (probe_kernel_read(&op, (void *)ip, sizeof(int))) {
+               pr_err("Fetching opcode failed.\n");
                return -EFAULT;
+       }
 
        /* Make sure that that this is still a 24bit jump */
        if (!is_bl_op(op)) {
@@ -122,14 +126,9 @@ __ftrace_make_nop(struct module *mod,
        }
 
        /* lets find where the pointer goes */
-       tramp = (void *)find_bl_target(ip, op);
-
-       pr_devel("ip:%lx jumps to %p", ip, tramp);
+       tramp = find_bl_target(ip, op);
 
-       if (!is_module_trampoline(tramp)) {
-               pr_err("Not a trampoline\n");
-               return -EINVAL;
-       }
+       pr_devel("ip:%lx jumps to %lx", ip, tramp);
 
        if (module_trampoline_target(mod, tramp, &ptr)) {
                pr_err("Failed to get trampoline target\n");
@@ -158,10 +157,42 @@ __ftrace_make_nop(struct module *mod,
         *
         * Use a b +8 to jump over the load.
         */
-       op = 0x48000008;        /* b +8 */
 
-       if (patch_instruction((unsigned int *)ip, op))
+       pop = PPC_INST_BRANCH | 8;      /* b +8 */
+
+       /*
+        * Check what is in the next instruction. We can see ld r2,40(r1), but
+        * on first pass after boot we will see mflr r0.
+        */
+       if (probe_kernel_read(&op, (void *)(ip+4), MCOUNT_INSN_SIZE)) {
+               pr_err("Fetching op failed.\n");
+               return -EFAULT;
+       }
+
+       if (op != PPC_INST_LD_TOC) {
+               unsigned int inst;
+
+               if (probe_kernel_read(&inst, (void *)(ip - 4), 4)) {
+                       pr_err("Fetching instruction at %lx failed.\n", ip - 4);
+                       return -EFAULT;
+               }
+
+               /* We expect either a mlfr r0, or a std r0, LRSAVE(r1) */
+               if (inst != PPC_INST_MFLR && inst != PPC_INST_STD_LR) {
+                       pr_err("Unexpected instructions around bl _mcount\n"
+                              "when enabling dynamic ftrace!\t"
+                              "(%08x,bl,%08x)\n", inst, op);
+                       return -EINVAL;
+               }
+
+               /* When using -mkernel_profile there is no load to jump over */
+               pop = PPC_INST_NOP;
+       }
+
+       if (patch_instruction((unsigned int *)ip, pop)) {
+               pr_err("Patching NOP failed.\n");
                return -EPERM;
+       }
 
        return 0;
 }
@@ -287,16 +318,15 @@ int ftrace_make_nop(struct module *mod,
 
 #ifdef CONFIG_MODULES
 #ifdef CONFIG_PPC64
+/*
+ * Examine the existing instructions for __ftrace_make_call.
+ * They should effectively be a NOP, and follow formal constraints,
+ * depending on the ABI. Return false if they don't.
+ */
+#ifndef CC_USING_MPROFILE_KERNEL
 static int
-__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
 {
-       unsigned int op[2];
-       void *ip = (void *)rec->ip;
-
-       /* read where this goes */
-       if (probe_kernel_read(op, ip, sizeof(op)))
-               return -EFAULT;
-
        /*
         * We expect to see:
         *
@@ -306,8 +336,34 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
         * The load offset is different depending on the ABI. For simplicity
         * just mask it out when doing the compare.
         */
-       if ((op[0] != 0x48000008) || ((op[1] & 0xffff0000) != 0xe8410000)) {
-               pr_err("Unexpected call sequence: %x %x\n", op[0], op[1]);
+       if ((op0 != 0x48000008) || ((op1 & 0xffff0000) != 0xe8410000))
+               return 0;
+       return 1;
+}
+#else
+static int
+expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
+{
+       /* look for patched "NOP" on ppc64 with -mprofile-kernel */
+       if (op0 != PPC_INST_NOP)
+               return 0;
+       return 1;
+}
+#endif
+
+static int
+__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       unsigned int op[2];
+       void *ip = (void *)rec->ip;
+
+       /* read where this goes */
+       if (probe_kernel_read(op, ip, sizeof(op)))
+               return -EFAULT;
+
+       if (!expected_nop_sequence(ip, op[0], op[1])) {
+               pr_err("Unexpected call sequence at %p: %x %x\n",
+               ip, op[0], op[1]);
                return -EINVAL;
        }
 
@@ -330,7 +386,16 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        return 0;
 }
-#else
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+                       unsigned long addr)
+{
+       return ftrace_make_call(rec, addr);
+}
+#endif
+
+#else  /* !CONFIG_PPC64: */
 static int
 __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 {
@@ -455,20 +520,13 @@ void ftrace_replace_code(int enable)
        }
 }
 
+/*
+ * Use the default ftrace_modify_all_code, but without
+ * stop_machine().
+ */
 void arch_ftrace_update_code(int command)
 {
-       if (command & FTRACE_UPDATE_CALLS)
-               ftrace_replace_code(1);
-       else if (command & FTRACE_DISABLE_CALLS)
-               ftrace_replace_code(0);
-
-       if (command & FTRACE_UPDATE_TRACE_FUNC)
-               ftrace_update_ftrace_func(ftrace_trace_function);
-
-       if (command & FTRACE_START_FUNC_RET)
-               ftrace_enable_ftrace_graph_caller();
-       else if (command & FTRACE_STOP_FUNC_RET)
-               ftrace_disable_ftrace_graph_caller();
+       ftrace_modify_all_code(command);
 }
 
 int __init ftrace_dyn_arch_init(void)
index b5061ab..9cdf5c7 100644 (file)
@@ -806,7 +806,7 @@ _GLOBAL(set_context)
 _GLOBAL(init_cpu_state)
        mflr    r22
 #ifdef CONFIG_PPC_47x
-       /* We use the PVR to differenciate 44x cores from 476 */
+       /* We use the PVR to differentiate 44x cores from 476 */
        mfspr   r3,SPRN_PVR
        srwi    r3,r3,16
        cmplwi  cr0,r3,PVR_476FPE@h
index 1b77956..4286775 100644 (file)
@@ -40,6 +40,8 @@
 #include <asm/kvm_book3s_asm.h>
 #include <asm/ptrace.h>
 #include <asm/hw_irq.h>
+#include <asm/cputhreads.h>
+#include <asm/ppc-opcode.h>
 
 /* The physical memory is laid out such that the secondary processor
  * spin code sits at 0x0000...0x00ff. On server, the vectors follow
@@ -181,6 +183,64 @@ exception_marker:
 #endif
 
 #ifdef CONFIG_PPC_BOOK3E
+/*
+ * The booting_thread_hwid holds the thread id we want to boot in cpu
+ * hotplug case. It is set by cpu hotplug code, and is invalid by default.
+ * The thread id is the same as the initial value of SPRN_PIR[THREAD_ID]
+ * bit field.
+ */
+       .globl  booting_thread_hwid
+booting_thread_hwid:
+       .long  INVALID_THREAD_HWID
+       .align 3
+/*
+ * start a thread in the same core
+ * input parameters:
+ * r3 = the thread physical id
+ * r4 = the entry point where thread starts
+ */
+_GLOBAL(book3e_start_thread)
+       LOAD_REG_IMMEDIATE(r5, MSR_KERNEL)
+       cmpi    0, r3, 0
+       beq     10f
+       cmpi    0, r3, 1
+       beq     11f
+       /* If the thread id is invalid, just exit. */
+       b       13f
+10:
+       MTTMR(TMRN_IMSR0, 5)
+       MTTMR(TMRN_INIA0, 4)
+       b       12f
+11:
+       MTTMR(TMRN_IMSR1, 5)
+       MTTMR(TMRN_INIA1, 4)
+12:
+       isync
+       li      r6, 1
+       sld     r6, r6, r3
+       mtspr   SPRN_TENS, r6
+13:
+       blr
+
+/*
+ * stop a thread in the same core
+ * input parameter:
+ * r3 = the thread physical id
+ */
+_GLOBAL(book3e_stop_thread)
+       cmpi    0, r3, 0
+       beq     10f
+       cmpi    0, r3, 1
+       beq     10f
+       /* If the thread id is invalid, just exit. */
+       b       13f
+10:
+       li      r4, 1
+       sld     r4, r4, r3
+       mtspr   SPRN_TENC, r4
+13:
+       blr
+
 _GLOBAL(fsl_secondary_thread_init)
        mfspr   r4,SPRN_BUCSR
 
@@ -261,6 +321,44 @@ _GLOBAL(generic_secondary_smp_init)
        mr      r3,r24
        mr      r4,r25
        bl      book3e_secondary_core_init
+
+/*
+ * After common core init has finished, check if the current thread is the
+ * one we wanted to boot. If not, start the specified thread and stop the
+ * current thread.
+ */
+       LOAD_REG_ADDR(r4, booting_thread_hwid)
+       lwz     r3, 0(r4)
+       li      r5, INVALID_THREAD_HWID
+       cmpw    r3, r5
+       beq     20f
+
+       /*
+        * The value of booting_thread_hwid has been stored in r3,
+        * so make it invalid.
+        */
+       stw     r5, 0(r4)
+
+       /*
+        * Get the current thread id and check if it is the one we wanted.
+        * If not, start the one specified in booting_thread_hwid and stop
+        * the current thread.
+        */
+       mfspr   r8, SPRN_TIR
+       cmpw    r3, r8
+       beq     20f
+
+       /* start the specified thread */
+       LOAD_REG_ADDR(r5, fsl_secondary_thread_init)
+       ld      r4, 0(r5)
+       bl      book3e_start_thread
+
+       /* stop the current thread */
+       mr      r3, r8
+       bl      book3e_stop_thread
+10:
+       b       10b
+20:
 #endif
 
 generic_secondary_common_init:
index 78c1eba..80c6947 100644 (file)
@@ -329,7 +329,7 @@ InstructionTLBMiss:
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-#ifdef CONFIG_MODULES
+#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
        /* Only modules will cause ITLB Misses as we always
         * pin the first 8MB of kernel memory */
        mfspr   r11, SPRN_SRR0  /* Get effective address of fault */
@@ -385,27 +385,26 @@ InstructionTLBMiss:
 
        . = 0x1200
 DataStoreTLBMiss:
-#ifdef CONFIG_8xx_CPU6
        mtspr   SPRN_SPRG_SCRATCH2, r3
-#endif
        EXCEPTION_PROLOG_0
-       mfcr    r10
+       mfcr    r3
 
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       mfspr   r11, SPRN_MD_EPN
-       IS_KERNEL(r11, r11)
+       mfspr   r10, SPRN_MD_EPN
+       IS_KERNEL(r11, r10)
        mfspr   r11, SPRN_M_TW  /* Get level 1 table */
        BRANCH_UNLESS_KERNEL(3f)
        lis     r11, (swapper_pg_dir-PAGE_OFFSET)@ha
 3:
-       mtcr    r10
-       mfspr   r10, SPRN_MD_EPN
 
        /* Insert level 1 index */
        rlwimi  r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)        /* Get the level 1 entry */
+       mtcr    r11
+       bt-     28,DTLBMiss8M           /* bit 28 = Large page (8M) */
+       mtcr    r3
 
        /* We have a pte table, so load fetch the pte from the table.
         */
@@ -453,13 +452,34 @@ DataStoreTLBMiss:
        MTSPR_CPU6(SPRN_MD_RPN, r10, r3)        /* Update TLB entry */
 
        /* Restore registers */
-#ifdef CONFIG_8xx_CPU6
        mfspr   r3, SPRN_SPRG_SCRATCH2
+       mtspr   SPRN_DAR, r11   /* Tag DAR */
+       EXCEPTION_EPILOG_0
+       rfi
+
+DTLBMiss8M:
+       mtcr    r3
+       ori     r11, r11, MD_SVALID
+       MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
+#ifdef CONFIG_PPC_16K_PAGES
+       /*
+        * In 16k pages mode, each PGD entry defines a 64M block.
+        * Here we select the 8M page within the block.
+        */
+       rlwimi  r11, r10, 0, 0x03800000
 #endif
+       rlwinm  r10, r11, 0, 0xff800000
+       ori     r10, r10, 0xf0 | MD_SPS16K | _PAGE_SHARED | _PAGE_DIRTY | \
+                         _PAGE_PRESENT
+       MTSPR_CPU6(SPRN_MD_RPN, r10, r3)        /* Update TLB entry */
+
+       li      r11, RPN_PATTERN
+       mfspr   r3, SPRN_SPRG_SCRATCH2
        mtspr   SPRN_DAR, r11   /* Tag DAR */
        EXCEPTION_EPILOG_0
        rfi
 
+
 /* This is an instruction TLB error on the MPC8xx.  This could be due
  * to many reasons, such as executing guarded memory or illegal instruction
  * addresses.  There is nothing to do but handle a big time error fault.
@@ -537,13 +557,15 @@ FixupDAR:/* Entry point for dcbx workaround. */
        /* Insert level 1 index */
 3:     rlwimi  r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
        lwz     r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)        /* Get the level 1 entry */
+       mtcr    r11
+       bt      28,200f         /* bit 28 = Large page (8M) */
        rlwinm  r11, r11,0,0,19 /* Extract page descriptor page address */
        /* Insert level 2 index */
        rlwimi  r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
        lwz     r11, 0(r11)     /* Get the pte */
        /* concat physical page address(r11) and page offset(r10) */
        rlwimi  r11, r10, 0, 32 - PAGE_SHIFT, 31
-       lwz     r11,0(r11)
+201:   lwz     r11,0(r11)
 /* Check if it really is a dcbx instruction. */
 /* dcbt and dcbtst does not generate DTLB Misses/Errors,
  * no need to include them here */
@@ -562,6 +584,10 @@ FixupDAR:/* Entry point for dcbx workaround. */
 141:   mfspr   r10,SPRN_SPRG_SCRATCH2
        b       DARFixed        /* Nope, go back to normal TLB processing */
 
+       /* concat physical page address(r11) and page offset(r10) */
+200:   rlwimi  r11, r10, 0, 32 - (PAGE_SHIFT << 1), 31
+       b       201b
+
 144:   mfspr   r10, SPRN_DSISR
        rlwinm  r10, r10,0,7,5  /* Clear store bit for buggy dcbst insn */
        mtspr   SPRN_DSISR, r10
@@ -856,68 +882,6 @@ initial_mmu:
        blr
 
 
-/*
- * Set up to use a given MMU context.
- * r3 is context number, r4 is PGD pointer.
- *
- * We place the physical address of the new task page directory loaded
- * into the MMU base register, and set the ASID compare register with
- * the new "context."
- */
-_GLOBAL(set_context)
-
-#ifdef CONFIG_BDI_SWITCH
-       /* Context switch the PTE pointer for the Abatron BDI2000.
-        * The PGDIR is passed as second argument.
-        */
-       lis     r5, KERNELBASE@h
-       lwz     r5, 0xf0(r5)
-       stw     r4, 0x4(r5)
-#endif
-
-       /* Register M_TW will contain base address of level 1 table minus the
-        * lower part of the kernel PGDIR base address, so that all accesses to
-        * level 1 table are done relative to lower part of kernel PGDIR base
-        * address.
-        */
-       li      r5, (swapper_pg_dir-PAGE_OFFSET)@l
-       sub     r4, r4, r5
-       tophys  (r4, r4)
-#ifdef CONFIG_8xx_CPU6
-       lis     r6, cpu6_errata_word@h
-       ori     r6, r6, cpu6_errata_word@l
-       li      r7, 0x3f80
-       stw     r7, 12(r6)
-       lwz     r7, 12(r6)
-#endif
-       mtspr   SPRN_M_TW, r4           /* Update pointeur to level 1 table */
-#ifdef CONFIG_8xx_CPU6
-       li      r7, 0x3380
-       stw     r7, 12(r6)
-       lwz     r7, 12(r6)
-#endif
-       mtspr   SPRN_M_CASID, r3        /* Update context */
-       SYNC
-       blr
-
-#ifdef CONFIG_8xx_CPU6
-/* It's here because it is unique to the 8xx.
- * It is important we get called with interrupts disabled.  I used to
- * do that, but it appears that all code that calls this already had
- * interrupt disabled.
- */
-       .globl  set_dec_cpu6
-set_dec_cpu6:
-       lis     r7, cpu6_errata_word@h
-       ori     r7, r7, cpu6_errata_word@l
-       li      r4, 0x2c00
-       stw     r4, 8(r7)
-       lwz     r4, 8(r7)
-        mtspr   22, r3         /* Update Decrementer */
-       SYNC
-       blr
-#endif
-
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the data segment,
index f705171..3bfa315 100644 (file)
@@ -1037,80 +1037,6 @@ _GLOBAL(set_context)
        isync                   /* Force context change */
        blr
 
-_GLOBAL(flush_dcache_L1)
-       mfspr   r3,SPRN_L1CFG0
-
-       rlwinm  r5,r3,9,3       /* Extract cache block size */
-       twlgti  r5,1            /* Only 32 and 64 byte cache blocks
-                                * are currently defined.
-                                */
-       li      r4,32
-       subfic  r6,r5,2         /* r6 = log2(1KiB / cache block size) -
-                                *      log2(number of ways)
-                                */
-       slw     r5,r4,r5        /* r5 = cache block size */
-
-       rlwinm  r7,r3,0,0xff    /* Extract number of KiB in the cache */
-       mulli   r7,r7,13        /* An 8-way cache will require 13
-                                * loads per set.
-                                */
-       slw     r7,r7,r6
-
-       /* save off HID0 and set DCFA */
-       mfspr   r8,SPRN_HID0
-       ori     r9,r8,HID0_DCFA@l
-       mtspr   SPRN_HID0,r9
-       isync
-
-       lis     r4,KERNELBASE@h
-       mtctr   r7
-
-1:     lwz     r3,0(r4)        /* Load... */
-       add     r4,r4,r5
-       bdnz    1b
-
-       msync
-       lis     r4,KERNELBASE@h
-       mtctr   r7
-
-1:     dcbf    0,r4            /* ...and flush. */
-       add     r4,r4,r5
-       bdnz    1b
-       
-       /* restore HID0 */
-       mtspr   SPRN_HID0,r8
-       isync
-
-       blr
-
-/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
-_GLOBAL(__flush_disable_L1)
-       mflr    r10
-       bl      flush_dcache_L1 /* Flush L1 d-cache */
-       mtlr    r10
-
-       mfspr   r4, SPRN_L1CSR0 /* Invalidate and disable d-cache */
-       li      r5, 2
-       rlwimi  r4, r5, 0, 3
-
-       msync
-       isync
-       mtspr   SPRN_L1CSR0, r4
-       isync
-
-1:     mfspr   r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
-       andi.   r4, r4, 2
-       bne     1b
-
-       mfspr   r4, SPRN_L1CSR1 /* Invalidate and disable i-cache */
-       li      r5, 2
-       rlwimi  r4, r5, 0, 3
-
-       mtspr   SPRN_L1CSR1, r4
-       isync
-
-       blr
-
 #ifdef CONFIG_SMP
 /* When we get here, r24 needs to hold the CPU # */
        .globl __secondary_start
index cf4fb54..470ceeb 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/kvm_book3s_asm.h>
 #include <asm/opal.h>
 #include <asm/cpuidle.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 
 #undef DEBUG
 
index e77c3cc..dbf0981 100644 (file)
@@ -445,7 +445,11 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
  * Global data
  */
 struct kgdb_arch arch_kgdb_ops = {
+#ifdef __LITTLE_ENDIAN__
+       .gdb_bpt_instr = {0x08, 0x10, 0x82, 0x7d},
+#else
        .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+#endif
 };
 
 static int kgdb_not_implemented(struct pt_regs *regs)
index 2c647b1..ee62b19 100644 (file)
@@ -54,8 +54,8 @@ static void flush_tlb_206(unsigned int num_sets, unsigned int action)
 }
 
 /*
- * Generic routine to flush TLB on power7. This routine is used as
- * flush_tlb hook in cpu_spec for Power7 processor.
+ * Generic routines to flush TLB on POWER processors. These routines
+ * are used as flush_tlb hook in the cpu_spec.
  *
  * action => TLB_INVAL_SCOPE_GLOBAL:  Invalidate all TLBs.
  *          TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID.
@@ -65,18 +65,17 @@ void __flush_tlb_power7(unsigned int action)
        flush_tlb_206(POWER7_TLB_SETS, action);
 }
 
-/*
- * Generic routine to flush TLB on power8. This routine is used as
- * flush_tlb hook in cpu_spec for power8 processor.
- *
- * action => TLB_INVAL_SCOPE_GLOBAL:  Invalidate all TLBs.
- *          TLB_INVAL_SCOPE_LPID: Invalidate TLB for current LPID.
- */
 void __flush_tlb_power8(unsigned int action)
 {
        flush_tlb_206(POWER8_TLB_SETS, action);
 }
 
+void __flush_tlb_power9(unsigned int action)
+{
+       flush_tlb_206(POWER9_TLB_SETS_HASH, action);
+}
+
+
 /* flush SLBs and reload */
 static void flush_and_reload_slb(void)
 {
index be8edd6..bf5160f 100644 (file)
@@ -91,17 +91,16 @@ _GLOBAL(mulhdu)
        addc    r7,r0,r7
        addze   r4,r4
 1:     beqlr   cr1             /* all done if high part of A is 0 */
-       mr      r10,r3
        mullw   r9,r3,r5
-       mulhwu  r3,r3,r5
+       mulhwu  r10,r3,r5
        beq     2f
-       mullw   r0,r10,r6
-       mulhwu  r8,r10,r6
+       mullw   r0,r3,r6
+       mulhwu  r8,r3,r6
        addc    r7,r0,r7
        adde    r4,r4,r8
-       addze   r3,r3
+       addze   r10,r10
 2:     addc    r4,r4,r9
-       addze   r3,r3
+       addze   r3,r10
        blr
 
 /*
@@ -296,12 +295,9 @@ _GLOBAL(real_writeb)
  * Flush instruction cache.
  * This is a no-op on the 601.
  */
+#ifndef CONFIG_PPC_8xx
 _GLOBAL(flush_instruction_cache)
-#if defined(CONFIG_8xx)
-       isync
-       lis     r5, IDC_INVALL@h
-       mtspr   SPRN_IC_CST, r5
-#elif defined(CONFIG_4xx)
+#if defined(CONFIG_4xx)
 #ifdef CONFIG_403GCX
        li      r3, 512
        mtctr   r3
@@ -334,9 +330,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
        mfspr   r3,SPRN_HID0
        ori     r3,r3,HID0_ICFI
        mtspr   SPRN_HID0,r3
-#endif /* CONFIG_8xx/4xx */
+#endif /* CONFIG_4xx */
        isync
        blr
+#endif /* CONFIG_PPC_8xx */
 
 /*
  * Write any modified data cache blocks out to memory
@@ -350,10 +347,9 @@ BEGIN_FTR_SECTION
        PURGE_PREFETCHED_INS
        blr                             /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
+       rlwinm  r3,r3,0,0,31 - L1_CACHE_SHIFT
        subf    r4,r3,r4
-       add     r4,r4,r5
+       addi    r4,r4,L1_CACHE_BYTES - 1
        srwi.   r4,r4,L1_CACHE_SHIFT
        beqlr
        mtctr   r4
@@ -376,71 +372,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        sync                            /* additional sync needed on g4 */
        isync
        blr
-/*
- * Write any modified data cache blocks out to memory.
- * Does not invalidate the corresponding cache lines (especially for
- * any corresponding instruction cache).
- *
- * clean_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(clean_dcache_range)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-       add     r4,r4,r5
-       srwi.   r4,r4,L1_CACHE_SHIFT
-       beqlr
-       mtctr   r4
-
-1:     dcbst   0,r3
-       addi    r3,r3,L1_CACHE_BYTES
-       bdnz    1b
-       sync                            /* wait for dcbst's to get to ram */
-       blr
-
-/*
- * Write any modified data cache blocks out to memory and invalidate them.
- * Does not invalidate the corresponding instruction cache blocks.
- *
- * flush_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(flush_dcache_range)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-       add     r4,r4,r5
-       srwi.   r4,r4,L1_CACHE_SHIFT
-       beqlr
-       mtctr   r4
-
-1:     dcbf    0,r3
-       addi    r3,r3,L1_CACHE_BYTES
-       bdnz    1b
-       sync                            /* wait for dcbst's to get to ram */
-       blr
-
-/*
- * Like above, but invalidate the D-cache.  This is used by the 8xx
- * to invalidate the cache so the PPC core doesn't get stale data
- * from the CPM (no cache snooping here :-).
- *
- * invalidate_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(invalidate_dcache_range)
-       li      r5,L1_CACHE_BYTES-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-       add     r4,r4,r5
-       srwi.   r4,r4,L1_CACHE_SHIFT
-       beqlr
-       mtctr   r4
-
-1:     dcbi    0,r3
-       addi    r3,r3,L1_CACHE_BYTES
-       bdnz    1b
-       sync                            /* wait for dcbi's to get to ram */
-       blr
-
 /*
  * Flush a particular page from the data cache to RAM.
  * Note: this is necessary because the instruction cache does *not*
@@ -518,22 +449,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        blr
 #endif /* CONFIG_BOOKE */
 
-/*
- * Clear pages using the dcbz instruction, which doesn't cause any
- * memory traffic (except to write out any cache lines which get
- * displaced).  This only works on cacheable memory.
- *
- * void clear_pages(void *page, int order) ;
- */
-_GLOBAL(clear_pages)
-       li      r0,PAGE_SIZE/L1_CACHE_BYTES
-       slw     r0,r0,r4
-       mtctr   r0
-1:     dcbz    0,r3
-       addi    r3,r3,L1_CACHE_BYTES
-       bdnz    1b
-       blr
-
 /*
  * Copy a whole page.  We use the dcbz instruction on the destination
  * to reduce memory traffic (it eliminates the unnecessary reads of
index 9547381..d1f1b35 100644 (file)
@@ -47,6 +47,11 @@ int module_finalize(const Elf_Ehdr *hdr,
                const Elf_Shdr *sechdrs, struct module *me)
 {
        const Elf_Shdr *sect;
+       int rc;
+
+       rc = module_finalize_ftrace(me, sechdrs);
+       if (rc)
+               return rc;
 
        /* Apply feature fixups */
        sect = find_section(hdr, sechdrs, "__ftr_fixup");
index 2c01665..5a7a78f 100644 (file)
@@ -181,7 +181,7 @@ static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
 /* Set up a trampoline in the PLT to bounce us to the distant function */
 static uint32_t do_plt_call(void *location,
                            Elf32_Addr val,
-                           Elf32_Shdr *sechdrs,
+                           const Elf32_Shdr *sechdrs,
                            struct module *mod)
 {
        struct ppc_plt_entry *entry;
@@ -294,11 +294,19 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
                        return -ENOEXEC;
                }
        }
+
+       return 0;
+}
+
 #ifdef CONFIG_DYNAMIC_FTRACE
-       module->arch.tramp =
-               do_plt_call(module->core_layout.base,
-                           (unsigned long)ftrace_caller,
-                           sechdrs, module);
-#endif
+int module_finalize_ftrace(struct module *module, const Elf_Shdr *sechdrs)
+{
+       module->arch.tramp = do_plt_call(module->core_layout.base,
+                                        (unsigned long)ftrace_caller,
+                                        sechdrs, module);
+       if (!module->arch.tramp)
+               return -ENOENT;
+
        return 0;
 }
+#endif
index 08b7a40..9ce9a25 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/code-patching.h>
 #include <linux/sort.h>
 #include <asm/setup.h>
+#include <asm/sections.h>
 
 /* FIXME: We don't do .init separately.  To do this, we'd need to have
    a separate r2 value in the init and core section, and stub between
@@ -41,7 +42,6 @@
    --RR.  */
 
 #if defined(_CALL_ELF) && _CALL_ELF == 2
-#define R2_STACK_OFFSET 24
 
 /* An address is simply the address of the function. */
 typedef unsigned long func_desc_t;
@@ -73,7 +73,6 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
        return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
 }
 #else
-#define R2_STACK_OFFSET 40
 
 /* An address is address of the OPD entry, which contains address of fn. */
 typedef struct ppc64_opd_entry func_desc_t;
@@ -96,6 +95,8 @@ static unsigned int local_entry_offset(const Elf64_Sym *sym)
 }
 #endif
 
+#define STUB_MAGIC 0x73747562 /* stub */
+
 /* Like PPC32, we need little trampolines to do > 24-bit jumps (into
    the kernel itself).  But on PPC64, these need to be used for every
    jump, actually, to reset r2 (TOC+0x8000). */
@@ -105,7 +106,8 @@ struct ppc64_stub_entry
         * need 6 instructions on ABIv2 but we always allocate 7 so
         * so we don't have to modify the trampoline load instruction. */
        u32 jump[7];
-       u32 unused;
+       /* Used by ftrace to identify stubs */
+       u32 magic;
        /* Data for the above code */
        func_desc_t funcdata;
 };
@@ -139,70 +141,39 @@ static u32 ppc64_stub_insns[] = {
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
-
-static u32 ppc64_stub_mask[] = {
-       0xffff0000,
-       0xffff0000,
-       0xffffffff,
-       0xffffffff,
-#if !defined(_CALL_ELF) || _CALL_ELF != 2
-       0xffffffff,
-#endif
-       0xffffffff,
-       0xffffffff
-};
-
-bool is_module_trampoline(u32 *p)
+int module_trampoline_target(struct module *mod, unsigned long addr,
+                            unsigned long *target)
 {
-       unsigned int i;
-       u32 insns[ARRAY_SIZE(ppc64_stub_insns)];
-
-       BUILD_BUG_ON(sizeof(ppc64_stub_insns) != sizeof(ppc64_stub_mask));
+       struct ppc64_stub_entry *stub;
+       func_desc_t funcdata;
+       u32 magic;
 
-       if (probe_kernel_read(insns, p, sizeof(insns)))
+       if (!within_module_core(addr, mod)) {
+               pr_err("%s: stub %lx not in module %s\n", __func__, addr, mod->name);
                return -EFAULT;
-
-       for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
-               u32 insna = insns[i];
-               u32 insnb = ppc64_stub_insns[i];
-               u32 mask = ppc64_stub_mask[i];
-
-               if ((insna & mask) != (insnb & mask))
-                       return false;
        }
 
-       return true;
-}
-
-int module_trampoline_target(struct module *mod, u32 *trampoline,
-                            unsigned long *target)
-{
-       u32 buf[2];
-       u16 upper, lower;
-       long offset;
-       void *toc_entry;
+       stub = (struct ppc64_stub_entry *)addr;
 
-       if (probe_kernel_read(buf, trampoline, sizeof(buf)))
+       if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
+               pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
                return -EFAULT;
+       }
 
-       upper = buf[0] & 0xffff;
-       lower = buf[1] & 0xffff;
-
-       /* perform the addis/addi, both signed */
-       offset = ((short)upper << 16) + (short)lower;
+       if (magic != STUB_MAGIC) {
+               pr_err("%s: bad magic for stub %lx for %s\n", __func__, addr, mod->name);
+               return -EFAULT;
+       }
 
-       /*
-        * Now get the address this trampoline jumps to. This
-        * is always 32 bytes into our trampoline stub.
-        */
-       toc_entry = (void *)mod->arch.toc + offset + 32;
+       if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
+               pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
+                return -EFAULT;
+       }
 
-       if (probe_kernel_read(target, toc_entry, sizeof(*target)))
-               return -EFAULT;
+       *target = stub_func_addr(funcdata);
 
        return 0;
 }
-
 #endif
 
 /* Count how many different 24-bit relocations (different symbol,
@@ -413,7 +384,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
 /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
    gives the value maximum span in an instruction which uses a signed
    offset) */
-static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
+static inline unsigned long my_r2(const Elf64_Shdr *sechdrs, struct module *me)
 {
        return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
 }
@@ -426,7 +397,7 @@ static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
 
 /* Patch stub to reference function and correct r2 value. */
-static inline int create_stub(Elf64_Shdr *sechdrs,
+static inline int create_stub(const Elf64_Shdr *sechdrs,
                              struct ppc64_stub_entry *entry,
                              unsigned long addr,
                              struct module *me)
@@ -447,12 +418,14 @@ static inline int create_stub(Elf64_Shdr *sechdrs,
        entry->jump[0] |= PPC_HA(reladdr);
        entry->jump[1] |= PPC_LO(reladdr);
        entry->funcdata = func_desc(addr);
+       entry->magic = STUB_MAGIC;
+
        return 1;
 }
 
 /* Create stub to jump to function described in this OPD/ptr: we need the
    stub to set up the TOC ptr (r2) for the function. */
-static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
+static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
                                   unsigned long addr,
                                   struct module *me)
 {
@@ -476,17 +449,60 @@ static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
        return (unsigned long)&stubs[i];
 }
 
+#ifdef CC_USING_MPROFILE_KERNEL
+static bool is_early_mcount_callsite(u32 *instruction)
+{
+       /*
+        * Check if this is one of the -mprofile-kernel sequences.
+        */
+       if (instruction[-1] == PPC_INST_STD_LR &&
+           instruction[-2] == PPC_INST_MFLR)
+               return true;
+
+       if (instruction[-1] == PPC_INST_MFLR)
+               return true;
+
+       return false;
+}
+
+/*
+ * In case of _mcount calls, do not save the current callee's TOC (in r2) into
+ * the original caller's stack frame. If we did we would clobber the saved TOC
+ * value of the original caller.
+ */
+static void squash_toc_save_inst(const char *name, unsigned long addr)
+{
+       struct ppc64_stub_entry *stub = (struct ppc64_stub_entry *)addr;
+
+       /* Only for calls to _mcount */
+       if (strcmp("_mcount", name) != 0)
+               return;
+
+       stub->jump[2] = PPC_INST_NOP;
+}
+#else
+static void squash_toc_save_inst(const char *name, unsigned long addr) { }
+
+/* without -mprofile-kernel, mcount calls are never early */
+static bool is_early_mcount_callsite(u32 *instruction)
+{
+       return false;
+}
+#endif
+
 /* We expect a noop next: if it is, replace it with instruction to
    restore r2. */
 static int restore_r2(u32 *instruction, struct module *me)
 {
        if (*instruction != PPC_INST_NOP) {
+               if (is_early_mcount_callsite(instruction - 1))
+                       return 1;
                pr_err("%s: Expect noop after relocate, got %08x\n",
                       me->name, *instruction);
                return 0;
        }
        /* ld r2,R2_STACK_OFFSET(r1) */
-       *instruction = 0xe8410000 | R2_STACK_OFFSET;
+       *instruction = PPC_INST_LD_TOC;
        return 1;
 }
 
@@ -611,6 +627,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                                        return -ENOENT;
                                if (!restore_r2((u32 *)location + 1, me))
                                        return -ENOEXEC;
+
+                               squash_toc_save_inst(strtab + sym->st_name, value);
                        } else
                                value += local_entry_offset(sym);
 
@@ -693,12 +711,84 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                }
        }
 
+       return 0;
+}
+
 #ifdef CONFIG_DYNAMIC_FTRACE
-       me->arch.toc = my_r2(sechdrs, me);
-       me->arch.tramp = stub_for_addr(sechdrs,
-                                      (unsigned long)ftrace_caller,
-                                      me);
+
+#ifdef CC_USING_MPROFILE_KERNEL
+
+#define PACATOC offsetof(struct paca_struct, kernel_toc)
+
+/*
+ * For mprofile-kernel we use a special stub for ftrace_caller() because we
+ * can't rely on r2 containing this module's TOC when we enter the stub.
+ *
+ * That can happen if the function calling us didn't need to use the toc. In
+ * that case it won't have setup r2, and the r2 value will be either the
+ * kernel's toc, or possibly another modules toc.
+ *
+ * To deal with that this stub uses the kernel toc, which is always accessible
+ * via the paca (in r13). The target (ftrace_caller()) is responsible for
+ * saving and restoring the toc before returning.
+ */
+static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
+{
+       struct ppc64_stub_entry *entry;
+       unsigned int i, num_stubs;
+       static u32 stub_insns[] = {
+               0xe98d0000 | PACATOC,   /* ld      r12,PACATOC(r13)     */
+               0x3d8c0000,             /* addis   r12,r12,<high>       */
+               0x398c0000,             /* addi    r12,r12,<low>        */
+               0x7d8903a6,             /* mtctr   r12                  */
+               0x4e800420,             /* bctr                         */
+       };
+       long reladdr;
+
+       num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*entry);
+
+       /* Find the next available stub entry */
+       entry = (void *)sechdrs[me->arch.stubs_section].sh_addr;
+       for (i = 0; i < num_stubs && stub_func_addr(entry->funcdata); i++, entry++);
+
+       if (i >= num_stubs) {
+               pr_err("%s: Unable to find a free slot for ftrace stub.\n", me->name);
+               return 0;
+       }
+
+       memcpy(entry->jump, stub_insns, sizeof(stub_insns));
+
+       /* Stub uses address relative to kernel toc (from the paca) */
+       reladdr = (unsigned long)ftrace_caller - kernel_toc_addr();
+       if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
+               pr_err("%s: Address of ftrace_caller out of range of kernel_toc.\n", me->name);
+               return 0;
+       }
+
+       entry->jump[1] |= PPC_HA(reladdr);
+       entry->jump[2] |= PPC_LO(reladdr);
+
+       /* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */
+       entry->funcdata = func_desc((unsigned long)ftrace_caller);
+       entry->magic = STUB_MAGIC;
+
+       return (unsigned long)entry;
+}
+#else
+static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
+{
+       return stub_for_addr(sechdrs, (unsigned long)ftrace_caller, me);
+}
 #endif
 
+int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
+{
+       mod->arch.toc = my_r2(sechdrs, mod);
+       mod->arch.tramp = create_ftrace_stub(sechdrs, mod);
+
+       if (!mod->arch.tramp)
+               return -ENOENT;
+
        return 0;
 }
+#endif
index 01ea0ed..93dae29 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/kexec.h>
 
-/* This symbol is provided by the linker - let it fill in the paca
- * field correctly */
-extern unsigned long __toc_start;
-
 #ifdef CONFIG_PPC_BOOK3S
 
 /*
@@ -149,11 +145,6 @@ EXPORT_SYMBOL(paca);
 
 void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 {
-       /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
-       * of the TOC can be addressed using a single machine instruction.
-       */
-       unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
-
 #ifdef CONFIG_PPC_BOOK3S
        new_paca->lppaca_ptr = new_lppaca(cpu);
 #else
@@ -161,7 +152,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 #endif
        new_paca->lock_token = 0x8000;
        new_paca->paca_index = cpu;
-       new_paca->kernel_toc = kernel_toc;
+       new_paca->kernel_toc = kernel_toc_addr();
        new_paca->kernelbase = (unsigned long) _stext;
        /* Only set MSR:IR/DR when MMU is initialized */
        new_paca->kernel_msr = MSR_KERNEL & ~(MSR_IR | MSR_DR);
index 7f9ed0c..59c4361 100644 (file)
@@ -55,7 +55,7 @@ void pcibios_remove_pci_devices(struct pci_bus *bus)
 
        pr_debug("PCI: Removing devices on bus %04x:%02x\n",
                 pci_domain_nr(bus),  bus->number);
-       list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+       list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
                pr_debug("   Removing %s...\n", pci_name(dev));
                pci_stop_and_remove_bus_device(dev);
        }
index b3b4df9..38102cb 100644 (file)
@@ -139,6 +139,7 @@ struct pci_dn *pci_get_pdn(struct pci_dev *pdev)
 #ifdef CONFIG_PCI_IOV
 static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
                                           struct pci_dev *pdev,
+                                          int vf_index,
                                           int busno, int devfn)
 {
        struct pci_dn *pdn;
@@ -158,6 +159,7 @@ static struct pci_dn *add_one_dev_pci_data(struct pci_dn *parent,
        pdn->busno = busno;
        pdn->devfn = devfn;
 #ifdef CONFIG_PPC_POWERNV
+       pdn->vf_index = vf_index;
        pdn->pe_number = IODA_INVALID_PE;
 #endif
        INIT_LIST_HEAD(&pdn->child_list);
@@ -179,6 +181,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
 {
 #ifdef CONFIG_PCI_IOV
        struct pci_dn *parent, *pdn;
+       struct eeh_dev *edev;
        int i;
 
        /* Only support IOV for now */
@@ -196,7 +199,7 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
                return NULL;
 
        for (i = 0; i < pci_sriov_get_totalvfs(pdev); i++) {
-               pdn = add_one_dev_pci_data(parent, NULL,
+               pdn = add_one_dev_pci_data(parent, NULL, i,
                                           pci_iov_virtfn_bus(pdev, i),
                                           pci_iov_virtfn_devfn(pdev, i));
                if (!pdn) {
@@ -204,6 +207,12 @@ struct pci_dn *add_dev_pci_data(struct pci_dev *pdev)
                                 __func__, i);
                        return NULL;
                }
+
+               /* Create the EEH device for the VF */
+               eeh_dev_init(pdn, pci_bus_to_host(pdev->bus));
+               edev = pdn_to_eeh_dev(pdn);
+               BUG_ON(!edev);
+               edev->physfn = pdev;
        }
 #endif /* CONFIG_PCI_IOV */
 
@@ -215,6 +224,7 @@ void remove_dev_pci_data(struct pci_dev *pdev)
 #ifdef CONFIG_PCI_IOV
        struct pci_dn *parent;
        struct pci_dn *pdn, *tmp;
+       struct eeh_dev *edev;
        int i;
 
        /*
@@ -256,6 +266,13 @@ void remove_dev_pci_data(struct pci_dev *pdev)
                            pdn->devfn != pci_iov_virtfn_devfn(pdev, i))
                                continue;
 
+                       /* Release EEH device for the VF */
+                       edev = pdn_to_eeh_dev(pdn);
+                       if (edev) {
+                               pdn->edev = NULL;
+                               kfree(edev);
+                       }
+
                        if (!list_empty(&pdn->list))
                                list_del(&pdn->list);
 
index 41e1607..9f01e28 100644 (file)
@@ -6,7 +6,9 @@
 #include <asm/cacheflush.h>
 #include <asm/epapr_hcalls.h>
 
+#ifdef CONFIG_PPC64
 EXPORT_SYMBOL(flush_dcache_range);
+#endif
 EXPORT_SYMBOL(flush_icache_range);
 
 EXPORT_SYMBOL(empty_zero_page);
@@ -28,10 +30,6 @@ EXPORT_SYMBOL(load_vr_state);
 EXPORT_SYMBOL(store_vr_state);
 #endif
 
-#ifdef CONFIG_VSX
-EXPORT_SYMBOL_GPL(__giveup_vsx);
-#endif
-
 #ifdef CONFIG_EPAPR_PARAVIRT
 EXPORT_SYMBOL(epapr_hypercall_start);
 #endif
index 30ddd8a..2bfaafe 100644 (file)
@@ -10,7 +10,6 @@
 #include <asm/pgtable.h>
 #include <asm/dcr.h>
 
-EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
 EXPORT_SYMBOL(DMA_MODE_READ);
 EXPORT_SYMBOL(DMA_MODE_WRITE);
index 3c5736e..612df30 100644 (file)
@@ -133,6 +133,16 @@ void __msr_check_and_clear(unsigned long bits)
 EXPORT_SYMBOL(__msr_check_and_clear);
 
 #ifdef CONFIG_PPC_FPU
+void __giveup_fpu(struct task_struct *tsk)
+{
+       save_fpu(tsk);
+       tsk->thread.regs->msr &= ~MSR_FP;
+#ifdef CONFIG_VSX
+       if (cpu_has_feature(CPU_FTR_VSX))
+               tsk->thread.regs->msr &= ~MSR_VSX;
+#endif
+}
+
 void giveup_fpu(struct task_struct *tsk)
 {
        check_if_tm_restore_required(tsk);
@@ -187,9 +197,32 @@ void enable_kernel_fp(void)
        }
 }
 EXPORT_SYMBOL(enable_kernel_fp);
+
+static int restore_fp(struct task_struct *tsk) {
+       if (tsk->thread.load_fp) {
+               load_fp_state(&current->thread.fp_state);
+               current->thread.load_fp++;
+               return 1;
+       }
+       return 0;
+}
+#else
+static int restore_fp(struct task_struct *tsk) { return 0; }
 #endif /* CONFIG_PPC_FPU */
 
 #ifdef CONFIG_ALTIVEC
+#define loadvec(thr) ((thr).load_vec)
+
+static void __giveup_altivec(struct task_struct *tsk)
+{
+       save_altivec(tsk);
+       tsk->thread.regs->msr &= ~MSR_VEC;
+#ifdef CONFIG_VSX
+       if (cpu_has_feature(CPU_FTR_VSX))
+               tsk->thread.regs->msr &= ~MSR_VSX;
+#endif
+}
+
 void giveup_altivec(struct task_struct *tsk)
 {
        check_if_tm_restore_required(tsk);
@@ -229,22 +262,49 @@ void flush_altivec_to_thread(struct task_struct *tsk)
        }
 }
 EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
+
+static int restore_altivec(struct task_struct *tsk)
+{
+       if (cpu_has_feature(CPU_FTR_ALTIVEC) && tsk->thread.load_vec) {
+               load_vr_state(&tsk->thread.vr_state);
+               tsk->thread.used_vr = 1;
+               tsk->thread.load_vec++;
+
+               return 1;
+       }
+       return 0;
+}
+#else
+#define loadvec(thr) 0
+static inline int restore_altivec(struct task_struct *tsk) { return 0; }
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_VSX
-void giveup_vsx(struct task_struct *tsk)
+static void __giveup_vsx(struct task_struct *tsk)
 {
-       check_if_tm_restore_required(tsk);
-
-       msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX);
        if (tsk->thread.regs->msr & MSR_FP)
                __giveup_fpu(tsk);
        if (tsk->thread.regs->msr & MSR_VEC)
                __giveup_altivec(tsk);
+       tsk->thread.regs->msr &= ~MSR_VSX;
+}
+
+static void giveup_vsx(struct task_struct *tsk)
+{
+       check_if_tm_restore_required(tsk);
+
+       msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX);
        __giveup_vsx(tsk);
        msr_check_and_clear(MSR_FP|MSR_VEC|MSR_VSX);
 }
-EXPORT_SYMBOL(giveup_vsx);
+
+static void save_vsx(struct task_struct *tsk)
+{
+       if (tsk->thread.regs->msr & MSR_FP)
+               save_fpu(tsk);
+       if (tsk->thread.regs->msr & MSR_VEC)
+               save_altivec(tsk);
+}
 
 void enable_kernel_vsx(void)
 {
@@ -275,6 +335,19 @@ void flush_vsx_to_thread(struct task_struct *tsk)
        }
 }
 EXPORT_SYMBOL_GPL(flush_vsx_to_thread);
+
+static int restore_vsx(struct task_struct *tsk)
+{
+       if (cpu_has_feature(CPU_FTR_VSX)) {
+               tsk->thread.used_vsr = 1;
+               return 1;
+       }
+
+       return 0;
+}
+#else
+static inline int restore_vsx(struct task_struct *tsk) { return 0; }
+static inline void save_vsx(struct task_struct *tsk) { }
 #endif /* CONFIG_VSX */
 
 #ifdef CONFIG_SPE
@@ -374,12 +447,76 @@ void giveup_all(struct task_struct *tsk)
 }
 EXPORT_SYMBOL(giveup_all);
 
+void restore_math(struct pt_regs *regs)
+{
+       unsigned long msr;
+
+       if (!current->thread.load_fp && !loadvec(current->thread))
+               return;
+
+       msr = regs->msr;
+       msr_check_and_set(msr_all_available);
+
+       /*
+        * Only reload if the bit is not set in the user MSR, the bit BEING set
+        * indicates that the registers are hot
+        */
+       if ((!(msr & MSR_FP)) && restore_fp(current))
+               msr |= MSR_FP | current->thread.fpexc_mode;
+
+       if ((!(msr & MSR_VEC)) && restore_altivec(current))
+               msr |= MSR_VEC;
+
+       if ((msr & (MSR_FP | MSR_VEC)) == (MSR_FP | MSR_VEC) &&
+                       restore_vsx(current)) {
+               msr |= MSR_VSX;
+       }
+
+       msr_check_and_clear(msr_all_available);
+
+       regs->msr = msr;
+}
+
+void save_all(struct task_struct *tsk)
+{
+       unsigned long usermsr;
+
+       if (!tsk->thread.regs)
+               return;
+
+       usermsr = tsk->thread.regs->msr;
+
+       if ((usermsr & msr_all_available) == 0)
+               return;
+
+       msr_check_and_set(msr_all_available);
+
+       /*
+        * Saving the way the register space is in hardware, save_vsx boils
+        * down to a save_fpu() and save_altivec()
+        */
+       if (usermsr & MSR_VSX) {
+               save_vsx(tsk);
+       } else {
+               if (usermsr & MSR_FP)
+                       save_fpu(tsk);
+
+               if (usermsr & MSR_VEC)
+                       save_altivec(tsk);
+       }
+
+       if (usermsr & MSR_SPE)
+               __giveup_spe(tsk);
+
+       msr_check_and_clear(msr_all_available);
+}
+
 void flush_all_to_thread(struct task_struct *tsk)
 {
        if (tsk->thread.regs) {
                preempt_disable();
                BUG_ON(tsk != current);
-               giveup_all(tsk);
+               save_all(tsk);
 
 #ifdef CONFIG_SPE
                if (tsk->thread.regs->msr & MSR_SPE)
@@ -832,17 +969,9 @@ void restore_tm_state(struct pt_regs *regs)
 
        msr_diff = current->thread.ckpt_regs.msr & ~regs->msr;
        msr_diff &= MSR_FP | MSR_VEC | MSR_VSX;
-       if (msr_diff & MSR_FP) {
-               msr_check_and_set(MSR_FP);
-               load_fp_state(&current->thread.fp_state);
-               msr_check_and_clear(MSR_FP);
-               regs->msr |= current->thread.fpexc_mode;
-       }
-       if (msr_diff & MSR_VEC) {
-               msr_check_and_set(MSR_VEC);
-               load_vr_state(&current->thread.vr_state);
-               msr_check_and_clear(MSR_VEC);
-       }
+
+       restore_math(regs);
+
        regs->msr |= msr_diff;
 }
 
@@ -1006,6 +1135,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
                batch = this_cpu_ptr(&ppc64_tlb_batch);
                batch->active = 1;
        }
+
+       if (current_thread_info()->task->thread.regs)
+               restore_math(current_thread_info()->task->thread.regs);
+
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        return last;
@@ -1307,6 +1440,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
                f = ret_from_fork;
        }
+       childregs->msr &= ~(MSR_FP|MSR_VEC|MSR_VSX);
        sp -= STACK_FRAME_OVERHEAD;
 
        /*
index cf8c7e4..cb64d6f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Common signal handling code for both 32 and 64 bits
  *
- *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
  *    Extracted from signal_32.c and signal_64.c
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -178,7 +178,7 @@ unsigned long get_tm_stackpointer(struct pt_regs *regs)
         * need to use the stack pointer from the checkpointed state, rather
         * than the speculated state.  This ensures that the signal context
         * (written tm suspended) will be written below the stack required for
-        * the rollback.  The transaction is aborted becuase of the treclaim,
+        * the rollback.  The transaction is aborted because of the treclaim,
         * so any memory written between the tbegin and the signal will be
         * rolled back anyway.
         *
index 51b2741..be305c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation
  *    Extracted from signal_32.c and signal_64.c
  *
  * This file is subject to the terms and conditions of the GNU General
index b7dea05..8cac1eb 100644 (file)
@@ -445,7 +445,7 @@ void generic_cpu_die(unsigned int cpu)
 
        for (i = 0; i < 100; i++) {
                smp_rmb();
-               if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+               if (is_cpu_dead(cpu))
                        return;
                msleep(100);
        }
@@ -472,6 +472,11 @@ int generic_check_cpu_restart(unsigned int cpu)
        return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
 }
 
+int is_cpu_dead(unsigned int cpu)
+{
+       return per_cpu(cpu_state, cpu) == CPU_DEAD;
+}
+
 static bool secondaries_inhibited(void)
 {
        return kvm_hv_mode_active();
index 33c47fc..9229ba6 100644 (file)
@@ -1147,6 +1147,7 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                goto bail;
        }
        if (reason & REASON_TRAP) {
+               unsigned long bugaddr;
                /* Debugger is first in line to stop recursive faults in
                 * rcu_lock, notify_die, or atomic_notifier_call_chain */
                if (debugger_bpt(regs))
@@ -1157,8 +1158,15 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                                == NOTIFY_STOP)
                        goto bail;
 
+               bugaddr = regs->nip;
+               /*
+                * Fixup bugaddr for BUG_ON() in real mode
+                */
+               if (!is_kernel_addr(bugaddr) && !(regs->msr & MSR_IR))
+                       bugaddr += PAGE_OFFSET;
+
                if (!(regs->msr & MSR_PR) &&  /* not user-mode */
-                   report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) {
+                   report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
                        regs->nip += 4;
                        goto bail;
                }
@@ -1393,7 +1401,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
                 * is a read DSCR attempt through a mfspr instruction, we
                 * just emulate the instruction instead. This code path will
                 * always emulate all the mfspr instructions till the user
-                * has attempted atleast one mtspr instruction. This way it
+                * has attempted at least one mtspr instruction. This way it
                 * preserves the same behaviour when the user is accessing
                 * the DSCR through privilege level only SPR number (0x11)
                 * which is emulated through illegal instruction exception.
index 162d0f7..1c2e7a3 100644 (file)
@@ -91,6 +91,10 @@ _GLOBAL(load_up_altivec)
        oris    r12,r12,MSR_VEC@h
        std     r12,_MSR(r1)
 #endif
+       /* Don't care if r4 overflows, this is desired behaviour */
+       lbz     r4,THREAD_LOAD_VEC(r5)
+       addi    r4,r4,1
+       stb     r4,THREAD_LOAD_VEC(r5)
        addi    r6,r5,THREAD_VRSTATE
        li      r4,1
        li      r10,VRSTATE_VSCR
@@ -102,36 +106,20 @@ _GLOBAL(load_up_altivec)
        blr
 
 /*
- * __giveup_altivec(tsk)
- * Disable VMX for the task given as the argument,
- * and save the vector registers in its thread_struct.
+ * save_altivec(tsk)
+ * Save the vector registers to its thread_struct
  */
-_GLOBAL(__giveup_altivec)
+_GLOBAL(save_altivec)
        addi    r3,r3,THREAD            /* want THREAD of task */
        PPC_LL  r7,THREAD_VRSAVEAREA(r3)
        PPC_LL  r5,PT_REGS(r3)
        PPC_LCMPI       0,r7,0
        bne     2f
        addi    r7,r3,THREAD_VRSTATE
-2:     PPC_LCMPI       0,r5,0
-       SAVE_32VRS(0,r4,r7)
+2:     SAVE_32VRS(0,r4,r7)
        mfvscr  v0
        li      r4,VRSTATE_VSCR
        stvx    v0,r4,r7
-       beq     1f
-       PPC_LL  r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-       lis     r3,(MSR_VEC|MSR_VSX)@h
-FTR_SECTION_ELSE
-       lis     r3,MSR_VEC@h
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
-#else
-       lis     r3,MSR_VEC@h
-#endif
-       andc    r4,r4,r3                /* disable FP for previous task */
-       PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
        blr
 
 #ifdef CONFIG_VSX
@@ -163,23 +151,6 @@ _GLOBAL(load_up_vsx)
        std     r12,_MSR(r1)
        b       fast_exception_return
 
-/*
- * __giveup_vsx(tsk)
- * Disable VSX for the task given as the argument.
- * Does NOT save vsx registers.
- */
-_GLOBAL(__giveup_vsx)
-       addi    r3,r3,THREAD            /* want THREAD of task */
-       ld      r5,PT_REGS(r3)
-       cmpdi   0,r5,0
-       beq     1f
-       ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-       lis     r3,MSR_VSX@h
-       andc    r4,r4,r3                /* disable VSX for previous task */
-       std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-       blr
-
 #endif /* CONFIG_VSX */
 
 
index 55c4d51..9991069 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash32.h>
+#include <asm/book3s/32/mmu-hash.h>
 #include <asm/machdep.h>
 #include <asm/mmu_context.h>
 #include <asm/hw_irq.h>
index 9bf7031..b9131aa 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 
 /* #define DEBUG_MMU */
 
index 913cd21..114edac 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/machdep.h>
 #include <asm/mmu_context.h>
 #include <asm/hw_irq.h>
index fb37290..c7b78d8 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/hvcall.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
index 2c2d103..8297004 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/hvcall.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
index 44be73e..f88b859 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/mmu_context.h>
 #include <asm/hvcall.h>
 #include <asm/synch.h>
index 9170051..4cb8db0 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/hvcall.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
index 85b32f1..62ea3c6 100644 (file)
@@ -27,7 +27,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/exception-64s.h>
 #include <asm/kvm_book3s_asm.h>
-#include <asm/mmu-hash64.h>
+#include <asm/book3s/64/mmu-hash.h>
 #include <asm/tm.h>
 
 #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
index 905e94a..46871d5 100644 (file)
@@ -432,7 +432,7 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
         * the whole masked_pending business which is about not
         * losing interrupts that occur while masked.
         *
-        * I don't differenciate normal deliveries and resends, this
+        * I don't differentiate normal deliveries and resends, this
         * implementation will differ from PAPR and not lose such
         * interrupts.
         */
index 778ef86..4d66f44 100644 (file)
@@ -992,7 +992,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
        kvmppc_restart_interrupt(vcpu, exit_nr);
 
        /*
-        * get last instruction before beeing preempted
+        * get last instruction before being preempted
         * TODO: for e6500 check also BOOKE_INTERRUPT_LRAT_ERROR & ESR_DATA
         */
        switch (exit_nr) {
index cda695d..f48a0c2 100644 (file)
@@ -182,7 +182,7 @@ int kvmppc_core_check_processor_compat(void)
                r = 0;
 #ifdef CONFIG_ALTIVEC
        /*
-        * Since guests have the priviledge to enable AltiVec, we need AltiVec
+        * Since guests have the privilege to enable AltiVec, we need AltiVec
         * support in the host to save/restore their context.
         * Don't use CPU_FTR_ALTIVEC to identify cores with AltiVec unit
         * because it's cleared in the absence of CONFIG_ALTIVEC!
index a47e142..ba21be1 100644 (file)
@@ -6,8 +6,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 ccflags-$(CONFIG_PPC64)        := $(NO_MINIMAL_TOC)
 
-CFLAGS_REMOVE_code-patching.o = -pg
-CFLAGS_REMOVE_feature-fixups.o = -pg
+CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_feature-fixups.o = $(CC_FLAGS_FTRACE)
 
 obj-y += string.o alloc.o crtsavres.o ppc_ksyms.o code-patching.o \
         feature-fixups.o
@@ -22,8 +22,7 @@ obj64-$(CONFIG_SMP)   += locks.o
 obj64-$(CONFIG_ALTIVEC)        += vmx-helper.o
 
 ifeq ($(CONFIG_GENERIC_CSUM),)
-obj-y                  += checksum_$(CONFIG_WORD_SIZE).o
-obj-$(CONFIG_PPC64)    += checksum_wrappers_64.o
+obj-y                  += checksum_$(CONFIG_WORD_SIZE).o checksum_wrappers.o
 endif
 
 obj-$(CONFIG_PPC_EMULATE_SSTEP)        += sstep.o ldstfp.o
index 6d67e05..d90870a 100644 (file)
 
 #include <linux/sys.h>
 #include <asm/processor.h>
+#include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ppc_asm.h>
 
        .text
 
-/*
- * ip_fast_csum(buf, len) -- Optimized for IP header
- * len is in words and is always >= 5.
- */
-_GLOBAL(ip_fast_csum)
-       lwz     r0,0(r3)
-       lwzu    r5,4(r3)
-       addic.  r4,r4,-2
-       addc    r0,r0,r5
-       mtctr   r4
-       blelr-
-1:     lwzu    r4,4(r3)
-       adde    r0,r0,r4
-       bdnz    1b
-       addze   r0,r0           /* add in final carry */
-       rlwinm  r3,r0,16,0,31   /* fold two halves together */
-       add     r3,r0,r3
-       not     r3,r3
-       srwi    r3,r3,16
-       blr
-
 /*
  * computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
  *
- * csum_partial(buff, len, sum)
+ * __csum_partial(buff, len, sum)
  */
-_GLOBAL(csum_partial)
-       addic   r0,r5,0
+_GLOBAL(__csum_partial)
        subi    r3,r3,4
-       srwi.   r6,r4,2
+       srawi.  r6,r4,2         /* Divide len by 4 and also clear carry */
        beq     3f              /* if we're doing < 4 bytes */
-       andi.   r5,r3,2         /* Align buffer to longword boundary */
+       andi.   r0,r3,2         /* Align buffer to longword boundary */
        beq+    1f
-       lhz     r5,4(r3)        /* do 2 bytes to get aligned */
-       addi    r3,r3,2
+       lhz     r0,4(r3)        /* do 2 bytes to get aligned */
        subi    r4,r4,2
-       addc    r0,r0,r5
+       addi    r3,r3,2
        srwi.   r6,r4,2         /* # words to do */
+       adde    r5,r5,r0
        beq     3f
-1:     mtctr   r6
-2:     lwzu    r5,4(r3)        /* the bdnz has zero overhead, so it should */
-       adde    r0,r0,r5        /* be unnecessary to unroll this loop */
+1:     andi.   r6,r6,3         /* Prepare to handle words 4 by 4 */
+       beq     21f
+       mtctr   r6
+2:     lwzu    r0,4(r3)
+       adde    r5,r5,r0
        bdnz    2b
-       andi.   r4,r4,3
-3:     cmpwi   0,r4,2
-       blt+    4f
-       lhz     r5,4(r3)
+21:    srwi.   r6,r4,4         /* # blocks of 4 words to do */
+       beq     3f
+       mtctr   r6
+22:    lwz     r0,4(r3)
+       lwz     r6,8(r3)
+       lwz     r7,12(r3)
+       lwzu    r8,16(r3)
+       adde    r5,r5,r0
+       adde    r5,r5,r6
+       adde    r5,r5,r7
+       adde    r5,r5,r8
+       bdnz    22b
+3:     andi.   r0,r4,2
+       beq+    4f
+       lhz     r0,4(r3)
        addi    r3,r3,2
-       subi    r4,r4,2
-       adde    r0,r0,r5
-4:     cmpwi   0,r4,1
-       bne+    5f
-       lbz     r5,4(r3)
-       slwi    r5,r5,8         /* Upper byte of word */
-       adde    r0,r0,r5
-5:     addze   r3,r0           /* add in final carry */
+       adde    r5,r5,r0
+4:     andi.   r0,r4,1
+       beq+    5f
+       lbz     r0,4(r3)
+       slwi    r0,r0,8         /* Upper byte of word */
+       adde    r5,r5,r0
+5:     addze   r3,r5           /* add in final carry */
        blr
 
 /*
@@ -87,123 +78,220 @@ _GLOBAL(csum_partial)
  *
  * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)
  */
+#define CSUM_COPY_16_BYTES_WITHEX(n)   \
+8 ## n ## 0:                   \
+       lwz     r7,4(r4);       \
+8 ## n ## 1:                   \
+       lwz     r8,8(r4);       \
+8 ## n ## 2:                   \
+       lwz     r9,12(r4);      \
+8 ## n ## 3:                   \
+       lwzu    r10,16(r4);     \
+8 ## n ## 4:                   \
+       stw     r7,4(r6);       \
+       adde    r12,r12,r7;     \
+8 ## n ## 5:                   \
+       stw     r8,8(r6);       \
+       adde    r12,r12,r8;     \
+8 ## n ## 6:                   \
+       stw     r9,12(r6);      \
+       adde    r12,r12,r9;     \
+8 ## n ## 7:                   \
+       stwu    r10,16(r6);     \
+       adde    r12,r12,r10
+
+#define CSUM_COPY_16_BYTES_EXCODE(n)           \
+.section __ex_table,"a";               \
+       .align  2;                      \
+       .long   8 ## n ## 0b,src_error; \
+       .long   8 ## n ## 1b,src_error; \
+       .long   8 ## n ## 2b,src_error; \
+       .long   8 ## n ## 3b,src_error; \
+       .long   8 ## n ## 4b,dst_error; \
+       .long   8 ## n ## 5b,dst_error; \
+       .long   8 ## n ## 6b,dst_error; \
+       .long   8 ## n ## 7b,dst_error; \
+       .text
+
+       .text
+       .stabs  "arch/powerpc/lib/",N_SO,0,0,0f
+       .stabs  "checksum_32.S",N_SO,0,0,0f
+0:
+
+CACHELINE_BYTES = L1_CACHE_BYTES
+LG_CACHELINE_BYTES = L1_CACHE_SHIFT
+CACHELINE_MASK = (L1_CACHE_BYTES-1)
+
 _GLOBAL(csum_partial_copy_generic)
-       addic   r0,r6,0
-       subi    r3,r3,4
-       subi    r4,r4,4
-       srwi.   r6,r5,2
-       beq     3f              /* if we're doing < 4 bytes */
-       andi.   r9,r4,2         /* Align dst to longword boundary */
-       beq+    1f
-81:    lhz     r6,4(r3)        /* do 2 bytes to get aligned */
-       addi    r3,r3,2
-       subi    r5,r5,2
-91:    sth     r6,4(r4)
-       addi    r4,r4,2
-       addc    r0,r0,r6
-       srwi.   r6,r5,2         /* # words to do */
-       beq     3f
-1:     srwi.   r6,r5,4         /* # groups of 4 words to do */
-       beq     10f
-       mtctr   r6
-71:    lwz     r6,4(r3)
-72:    lwz     r9,8(r3)
-73:    lwz     r10,12(r3)
-74:    lwzu    r11,16(r3)
-       adde    r0,r0,r6
-75:    stw     r6,4(r4)
-       adde    r0,r0,r9
-76:    stw     r9,8(r4)
-       adde    r0,r0,r10
-77:    stw     r10,12(r4)
-       adde    r0,r0,r11
-78:    stwu    r11,16(r4)
-       bdnz    71b
-10:    rlwinm. r6,r5,30,30,31  /* # words left to do */
-       beq     13f
-       mtctr   r6
-82:    lwzu    r9,4(r3)
-92:    stwu    r9,4(r4)
-       adde    r0,r0,r9
-       bdnz    82b
-13:    andi.   r5,r5,3
-3:     cmpwi   0,r5,2
-       blt+    4f
-83:    lhz     r6,4(r3)
-       addi    r3,r3,2
-       subi    r5,r5,2
-93:    sth     r6,4(r4)
+       stwu    r1,-16(r1)
+       stw     r7,12(r1)
+       stw     r8,8(r1)
+
+       andi.   r0,r4,1                 /* is destination address even ? */
+       cmplwi  cr7,r0,0
+       addic   r12,r6,0
+       addi    r6,r4,-4
+       neg     r0,r4
+       addi    r4,r3,-4
+       andi.   r0,r0,CACHELINE_MASK    /* # bytes to start of cache line */
+       beq     58f
+
+       cmplw   0,r5,r0                 /* is this more than total to do? */
+       blt     63f                     /* if not much to do */
+       andi.   r8,r0,3                 /* get it word-aligned first */
+       mtctr   r8
+       beq+    61f
+       li      r3,0
+70:    lbz     r9,4(r4)                /* do some bytes */
+       addi    r4,r4,1
+       slwi    r3,r3,8
+       rlwimi  r3,r9,0,24,31
+71:    stb     r9,4(r6)
+       addi    r6,r6,1
+       bdnz    70b
+       adde    r12,r12,r3
+61:    subf    r5,r0,r5
+       srwi.   r0,r0,2
+       mtctr   r0
+       beq     58f
+72:    lwzu    r9,4(r4)                /* do some words */
+       adde    r12,r12,r9
+73:    stwu    r9,4(r6)
+       bdnz    72b
+
+58:    srwi.   r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+       clrlwi  r5,r5,32-LG_CACHELINE_BYTES
+       li      r11,4
+       beq     63f
+
+       /* Here we decide how far ahead to prefetch the source */
+       li      r3,4
+       cmpwi   r0,1
+       li      r7,0
+       ble     114f
+       li      r7,1
+#if MAX_COPY_PREFETCH > 1
+       /* Heuristically, for large transfers we prefetch
+          MAX_COPY_PREFETCH cachelines ahead.  For small transfers
+          we prefetch 1 cacheline ahead. */
+       cmpwi   r0,MAX_COPY_PREFETCH
+       ble     112f
+       li      r7,MAX_COPY_PREFETCH
+112:   mtctr   r7
+111:   dcbt    r3,r4
+       addi    r3,r3,CACHELINE_BYTES
+       bdnz    111b
+#else
+       dcbt    r3,r4
+       addi    r3,r3,CACHELINE_BYTES
+#endif /* MAX_COPY_PREFETCH > 1 */
+
+114:   subf    r8,r7,r0
+       mr      r0,r7
+       mtctr   r8
+
+53:    dcbt    r3,r4
+54:    dcbz    r11,r6
+/* the main body of the cacheline loop */
+       CSUM_COPY_16_BYTES_WITHEX(0)
+#if L1_CACHE_BYTES >= 32
+       CSUM_COPY_16_BYTES_WITHEX(1)
+#if L1_CACHE_BYTES >= 64
+       CSUM_COPY_16_BYTES_WITHEX(2)
+       CSUM_COPY_16_BYTES_WITHEX(3)
+#if L1_CACHE_BYTES >= 128
+       CSUM_COPY_16_BYTES_WITHEX(4)
+       CSUM_COPY_16_BYTES_WITHEX(5)
+       CSUM_COPY_16_BYTES_WITHEX(6)
+       CSUM_COPY_16_BYTES_WITHEX(7)
+#endif
+#endif
+#endif
+       bdnz    53b
+       cmpwi   r0,0
+       li      r3,4
+       li      r7,0
+       bne     114b
+
+63:    srwi.   r0,r5,2
+       mtctr   r0
+       beq     64f
+30:    lwzu    r0,4(r4)
+       adde    r12,r12,r0
+31:    stwu    r0,4(r6)
+       bdnz    30b
+
+64:    andi.   r0,r5,2
+       beq+    65f
+40:    lhz     r0,4(r4)
        addi    r4,r4,2
-       adde    r0,r0,r6
-4:     cmpwi   0,r5,1
-       bne+    5f
-84:    lbz     r6,4(r3)
-94:    stb     r6,4(r4)
-       slwi    r6,r6,8         /* Upper byte of word */
-       adde    r0,r0,r6
-5:     addze   r3,r0           /* add in final carry */
+41:    sth     r0,4(r6)
+       adde    r12,r12,r0
+       addi    r6,r6,2
+65:    andi.   r0,r5,1
+       beq+    66f
+50:    lbz     r0,4(r4)
+51:    stb     r0,4(r6)
+       slwi    r0,r0,8
+       adde    r12,r12,r0
+66:    addze   r3,r12
+       addi    r1,r1,16
+       beqlr+  cr7
+       rlwinm  r3,r3,8,0,31    /* swap bytes for odd destination */
        blr
 
-/* These shouldn't go in the fixup section, since that would
-   cause the ex_table addresses to get out of order. */
-
-src_error_4:
-       mfctr   r6              /* update # bytes remaining from ctr */
-       rlwimi  r5,r6,4,0,27
-       b       79f
-src_error_1:
-       li      r6,0
-       subi    r5,r5,2
-95:    sth     r6,4(r4)
-       addi    r4,r4,2
-79:    srwi.   r6,r5,2
-       beq     3f
-       mtctr   r6
-src_error_2:
-       li      r6,0
-96:    stwu    r6,4(r4)
-       bdnz    96b
-3:     andi.   r5,r5,3
-       beq     src_error
-src_error_3:
-       li      r6,0
-       mtctr   r5
-       addi    r4,r4,3
-97:    stbu    r6,1(r4)
-       bdnz    97b
+/* read fault */
 src_error:
-       cmpwi   0,r7,0
-       beq     1f
-       li      r6,-EFAULT
-       stw     r6,0(r7)
-1:     addze   r3,r0
+       lwz     r7,12(r1)
+       addi    r1,r1,16
+       cmpwi   cr0,r7,0
+       beqlr
+       li      r0,-EFAULT
+       stw     r0,0(r7)
        blr
-
+/* write fault */
 dst_error:
-       cmpwi   0,r8,0
-       beq     1f
-       li      r6,-EFAULT
-       stw     r6,0(r8)
-1:     addze   r3,r0
+       lwz     r8,8(r1)
+       addi    r1,r1,16
+       cmpwi   cr0,r8,0
+       beqlr
+       li      r0,-EFAULT
+       stw     r0,0(r8)
        blr
 
-.section __ex_table,"a"
-       .long   81b,src_error_1
-       .long   91b,dst_error
-       .long   71b,src_error_4
-       .long   72b,src_error_4
-       .long   73b,src_error_4
-       .long   74b,src_error_4
-       .long   75b,dst_error
-       .long   76b,dst_error
-       .long   77b,dst_error
-       .long   78b,dst_error
-       .long   82b,src_error_2
-       .long   92b,dst_error
-       .long   83b,src_error_3
-       .long   93b,dst_error
-       .long   84b,src_error_3
-       .long   94b,dst_error
-       .long   95b,dst_error
-       .long   96b,dst_error
-       .long   97b,dst_error
+       .section __ex_table,"a"
+       .align  2
+       .long   70b,src_error
+       .long   71b,dst_error
+       .long   72b,src_error
+       .long   73b,dst_error
+       .long   54b,dst_error
+       .text
+
+/*
+ * this stuff handles faults in the cacheline loop and branches to either
+ * src_error (if in read part) or dst_error (if in write part)
+ */
+       CSUM_COPY_16_BYTES_EXCODE(0)
+#if L1_CACHE_BYTES >= 32
+       CSUM_COPY_16_BYTES_EXCODE(1)
+#if L1_CACHE_BYTES >= 64
+       CSUM_COPY_16_BYTES_EXCODE(2)
+       CSUM_COPY_16_BYTES_EXCODE(3)
+#if L1_CACHE_BYTES >= 128
+       CSUM_COPY_16_BYTES_EXCODE(4)
+       CSUM_COPY_16_BYTES_EXCODE(5)
+       CSUM_COPY_16_BYTES_EXCODE(6)
+       CSUM_COPY_16_BYTES_EXCODE(7)
+#endif
+#endif
+#endif
+
+       .section __ex_table,"a"
+       .align  2
+       .long   30b,src_error
+       .long   31b,dst_error
+       .long   40b,src_error
+       .long   41b,dst_error
+       .long   50b,src_error
+       .long   51b,dst_error
index f3ef354..8e6e510 100644 (file)
 #include <asm/errno.h>
 #include <asm/ppc_asm.h>
 
-/*
- * ip_fast_csum(r3=buf, r4=len) -- Optimized for IP header
- * len is in words and is always >= 5.
- *
- * In practice len == 5, but this is not guaranteed.  So this code does not
- * attempt to use doubleword instructions.
- */
-_GLOBAL(ip_fast_csum)
-       lwz     r0,0(r3)
-       lwzu    r5,4(r3)
-       addic.  r4,r4,-2
-       addc    r0,r0,r5
-       mtctr   r4
-       blelr-
-1:     lwzu    r4,4(r3)
-       adde    r0,r0,r4
-       bdnz    1b
-       addze   r0,r0           /* add in final carry */
-        rldicl  r4,r0,32,0      /* fold two 32-bit halves together */
-        add     r0,r0,r4
-        srdi    r0,r0,32
-       rlwinm  r3,r0,16,0,31   /* fold two halves together */
-       add     r3,r0,r3
-       not     r3,r3
-       srwi    r3,r3,16
-       blr
-
 /*
  * Computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit).
  *
- * csum_partial(r3=buff, r4=len, r5=sum)
+ * __csum_partial(r3=buff, r4=len, r5=sum)
  */
-_GLOBAL(csum_partial)
+_GLOBAL(__csum_partial)
        addic   r0,r5,0                 /* clear carry */
 
        srdi.   r6,r4,3                 /* less than 8 bytes? */
diff --git a/arch/powerpc/lib/checksum_wrappers.c b/arch/powerpc/lib/checksum_wrappers.c
new file mode 100644 (file)
index 0000000..08e3a33
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <linux/export.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+
+__wsum csum_and_copy_from_user(const void __user *src, void *dst,
+                              int len, __wsum sum, int *err_ptr)
+{
+       unsigned int csum;
+
+       might_sleep();
+
+       *err_ptr = 0;
+
+       if (!len) {
+               csum = 0;
+               goto out;
+       }
+
+       if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) {
+               *err_ptr = -EFAULT;
+               csum = (__force unsigned int)sum;
+               goto out;
+       }
+
+       csum = csum_partial_copy_generic((void __force *)src, dst,
+                                        len, sum, err_ptr, NULL);
+
+       if (unlikely(*err_ptr)) {
+               int missing = __copy_from_user(dst, src, len);
+
+               if (missing) {
+                       memset(dst + len - missing, 0, missing);
+                       *err_ptr = -EFAULT;
+               } else {
+                       *err_ptr = 0;
+               }
+
+               csum = csum_partial(dst, len, sum);
+       }
+
+out:
+       return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
+                            __wsum sum, int *err_ptr)
+{
+       unsigned int csum;
+
+       might_sleep();
+
+       *err_ptr = 0;
+
+       if (!len) {
+               csum = 0;
+               goto out;
+       }
+
+       if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
+               *err_ptr = -EFAULT;
+               csum = -1; /* invalid checksum */
+               goto out;
+       }
+
+       csum = csum_partial_copy_generic(src, (void __force *)dst,
+                                        len, sum, NULL, err_ptr);
+
+       if (unlikely(*err_ptr)) {
+               csum = csum_partial(src, len, sum);
+
+               if (copy_to_user(dst, src, len)) {
+                       *err_ptr = -EFAULT;
+                       csum = -1; /* invalid checksum */
+               }
+       }
+
+out:
+       return (__force __wsum)csum;
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c
deleted file mode 100644 (file)
index 08e3a33..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) IBM Corporation, 2010
- *
- * Author: Anton Blanchard <anton@au.ibm.com>
- */
-#include <linux/export.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm/checksum.h>
-#include <asm/uaccess.h>
-
-__wsum csum_and_copy_from_user(const void __user *src, void *dst,
-                              int len, __wsum sum, int *err_ptr)
-{
-       unsigned int csum;
-
-       might_sleep();
-
-       *err_ptr = 0;
-
-       if (!len) {
-               csum = 0;
-               goto out;
-       }
-
-       if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) {
-               *err_ptr = -EFAULT;
-               csum = (__force unsigned int)sum;
-               goto out;
-       }
-
-       csum = csum_partial_copy_generic((void __force *)src, dst,
-                                        len, sum, err_ptr, NULL);
-
-       if (unlikely(*err_ptr)) {
-               int missing = __copy_from_user(dst, src, len);
-
-               if (missing) {
-                       memset(dst + len - missing, 0, missing);
-                       *err_ptr = -EFAULT;
-               } else {
-                       *err_ptr = 0;
-               }
-
-               csum = csum_partial(dst, len, sum);
-       }
-
-out:
-       return (__force __wsum)csum;
-}
-EXPORT_SYMBOL(csum_and_copy_from_user);
-
-__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
-                            __wsum sum, int *err_ptr)
-{
-       unsigned int csum;
-
-       might_sleep();
-
-       *err_ptr = 0;
-
-       if (!len) {
-               csum = 0;
-               goto out;
-       }
-
-       if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) {
-               *err_ptr = -EFAULT;
-               csum = -1; /* invalid checksum */
-               goto out;
-       }
-
-       csum = csum_partial_copy_generic(src, (void __force *)dst,
-                                        len, sum, NULL, err_ptr);
-
-       if (unlikely(*err_ptr)) {
-               csum = csum_partial(src, len, sum);
-
-               if (copy_to_user(dst, src, len)) {
-                       *err_ptr = -EFAULT;
-                       csum = -1; /* invalid checksum */
-               }
-       }
-
-out:
-       return (__force __wsum)csum;
-}
-EXPORT_SYMBOL(csum_and_copy_to_user);
index c7f8e95..c422812 100644 (file)
@@ -17,10 +17,8 @@ EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
 
 #ifndef CONFIG_GENERIC_CSUM
-EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(__csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
-EXPORT_SYMBOL(ip_fast_csum);
-EXPORT_SYMBOL(csum_tcpudp_magic);
 #endif
 
 EXPORT_SYMBOL(__copy_tofrom_user);
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
new file mode 100644 (file)
index 0000000..9491005
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * This file contains the routines for initializing the MMU
+ * on the 8xx series of chips.
+ *  -- christophe
+ *
+ *  Derived from arch/powerpc/mm/40x_mmu.c:
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/memblock.h>
+
+#include "mmu_decl.h"
+
+extern int __map_without_ltlbs;
+/*
+ * MMU_init_hw does the chip-specific initialization of the MMU hardware.
+ */
+void __init MMU_init_hw(void)
+{
+       /* Nothing to do for the time being but keep it similar to other PPC */
+}
+
+#define LARGE_PAGE_SIZE_4M     (1<<22)
+#define LARGE_PAGE_SIZE_8M     (1<<23)
+#define LARGE_PAGE_SIZE_64M    (1<<26)
+
+unsigned long __init mmu_mapin_ram(unsigned long top)
+{
+       unsigned long v, s, mapped;
+       phys_addr_t p;
+
+       v = KERNELBASE;
+       p = 0;
+       s = top;
+
+       if (__map_without_ltlbs)
+               return 0;
+
+#ifdef CONFIG_PPC_4K_PAGES
+       while (s >= LARGE_PAGE_SIZE_8M) {
+               pmd_t *pmdp;
+               unsigned long val = p | MD_PS8MEG;
+
+               pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v);
+               *pmdp++ = __pmd(val);
+               *pmdp++ = __pmd(val + LARGE_PAGE_SIZE_4M);
+
+               v += LARGE_PAGE_SIZE_8M;
+               p += LARGE_PAGE_SIZE_8M;
+               s -= LARGE_PAGE_SIZE_8M;
+       }
+#else /* CONFIG_PPC_16K_PAGES */
+       while (s >= LARGE_PAGE_SIZE_64M) {
+               pmd_t *pmdp;
+               unsigned long val = p | MD_PS8MEG;
+
+               pmdp = pmd_offset(pud_offset(pgd_offset_k(v), v), v);
+               *pmdp++ = __pmd(val);
+
+               v += LARGE_PAGE_SIZE_64M;
+               p += LARGE_PAGE_SIZE_64M;
+               s -= LARGE_PAGE_SIZE_64M;
+       }
+#endif
+
+       mapped = top - s;
+
+       /* If the size of RAM is not an exact power of two, we may not
+        * have covered RAM in its entirety with 8 MiB
+        * pages. Consequently, restrict the top end of RAM currently
+        * allocable so that calls to the MEMBLOCK to allocate PTEs for "tail"
+        * coverage with normal-sized pages (or other reasons) do not
+        * attempt to allocate outside the allowed range.
+        */
+       memblock_set_current_limit(mapped);
+
+       return mapped;
+}
+
+void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+                               phys_addr_t first_memblock_size)
+{
+       /* We don't currently support the first MEMBLOCK not mapping 0
+        * physical on those processors
+        */
+       BUG_ON(first_memblock_base != 0);
+
+#ifdef CONFIG_PIN_TLB
+       /* 8xx can only access 24MB at the moment */
+       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000));
+#else
+       /* 8xx can only access 8MB at the moment */
+       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+#endif
+}
+
+/*
+ * Set up to use a given MMU context.
+ * id is context number, pgd is PGD pointer.
+ *
+ * We place the physical address of the new task page directory loaded
+ * into the MMU base register, and set the ASID compare register with
+ * the new "context."
+ */
+void set_context(unsigned long id, pgd_t *pgd)
+{
+       s16 offset = (s16)(__pa(swapper_pg_dir));
+
+#ifdef CONFIG_BDI_SWITCH
+       pgd_t   **ptr = *(pgd_t ***)(KERNELBASE + 0xf0);
+
+       /* Context switch the PTE pointer for the Abatron BDI2000.
+        * The PGDIR is passed as second argument.
+        */
+       *(ptr + 1) = pgd;
+#endif
+
+       /* Register M_TW will contain base address of level 1 table minus the
+        * lower part of the kernel PGDIR base address, so that all accesses to
+        * level 1 table are done relative to lower part of kernel PGDIR base
+        * address.
+        */
+       mtspr(SPRN_M_TW, __pa(pgd) - offset);
+
+       /* Update context */
+       mtspr(SPRN_M_CASID, id);
+       /* sync */
+       mb();
+}
+
+void flush_instruction_cache(void)
+{
+       isync();
+       mtspr(SPRN_IC_CST, IDC_INVALL);
+       isync();
+}
index 1ffeda8..adfee3f 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_PPC_ICSWX)               += icswx.o
 obj-$(CONFIG_PPC_ICSWX_PID)    += icswx_pid.o
 obj-$(CONFIG_40x)              += 40x_mmu.o
 obj-$(CONFIG_44x)              += 44x_mmu.o
+obj-$(CONFIG_PPC_8xx)          += 8xx_mmu.o
 obj-$(CONFIG_PPC_FSL_BOOK3E)   += fsl_booke_mmu.o
 obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
 obj-$(CONFIG_PPC_SPLPAR)       += vphn.o
index 169aba4..2dc74e5 100644 (file)
@@ -327,7 +327,7 @@ void __dma_sync(void *vaddr, size_t size, int direction)
                 * invalidate only when cache-line aligned otherwise there is
                 * the potential for discarding uncommitted data from the cache
                 */
-               if ((start & (L1_CACHE_BYTES - 1)) || (size & (L1_CACHE_BYTES - 1)))
+               if ((start | end) & (L1_CACHE_BYTES - 1))
                        flush_dcache_range(start, end);
                else
                        invalidate_dcache_range(start, end);
index f3afe3d..a1b2713 100644 (file)
@@ -72,10 +72,11 @@ unsigned long tlbcam_sz(int idx)
        return tlbcam_addrs[idx].limit - tlbcam_addrs[idx].start + 1;
 }
 
+#ifdef CONFIG_FSL_BOOKE
 /*
  * Return PA for this VA if it is mapped by a CAM, or 0
  */
-phys_addr_t v_mapped_by_tlbcam(unsigned long va)
+phys_addr_t v_block_mapped(unsigned long va)
 {
        int b;
        for (b = 0; b < tlbcam_index; ++b)
@@ -87,7 +88,7 @@ phys_addr_t v_mapped_by_tlbcam(unsigned long va)
 /*
  * Return VA for a given PA or 0 if not mapped
  */
-unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
+unsigned long p_block_mapped(phys_addr_t pa)
 {
        int b;
        for (b = 0; b < tlbcam_index; ++b)
@@ -97,6 +98,7 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa)
                        return tlbcam_addrs[b].start+(pa-tlbcam_addrs[b].phys);
        return 0;
 }
+#endif
 
 /*
  * Set up a variable-size TLB entry (tlbcam). The parameters are not checked;
index e7c0454..47d1b26 100644 (file)
@@ -44,7 +44,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
                 * a write access. Since this is 4K insert of 64K page size
                 * also add _PAGE_COMBO
                 */
-               new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE;
+               new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
                if (access & _PAGE_RW)
                        new_pte |= _PAGE_DIRTY;
        } while (old_pte != __cmpxchg_u64((unsigned long *)ptep,
@@ -106,7 +106,7 @@ repeat:
                        }
                }
                /*
-                * Hypervisor failure. Restore old pmd and return -1
+                * Hypervisor failure. Restore old pte and return -1
                 * similar to __hash_page_*
                 */
                if (unlikely(slot == -2)) {
index edb0991..b2d659c 100644 (file)
@@ -188,7 +188,7 @@ repeat:
                }
        }
        /*
-        * Hypervisor failure. Restore old pmd and return -1
+        * Hypervisor failure. Restore old pte and return -1
         * similar to __hash_page_*
         */
        if (unlikely(slot == -2)) {
@@ -249,8 +249,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,
                        return 0;
                /*
                 * Try to lock the PTE, add ACCESSED and DIRTY if it was
-                * a write access. Since this is 4K insert of 64K page size
-                * also add _PAGE_COMBO
+                * a write access.
                 */
                new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
                if (access & _PAGE_RW)
@@ -311,7 +310,7 @@ repeat:
                        }
                }
                /*
-                * Hypervisor failure. Restore old pmd and return -1
+                * Hypervisor failure. Restore old pte and return -1
                 * similar to __hash_page_*
                 */
                if (unlikely(slot == -2)) {
index 1005281..7635b1c 100644 (file)
@@ -168,11 +168,11 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
                rflags |= HPTE_R_N;
        /*
         * PP bits:
-        * Linux use slb key 0 for kernel and 1 for user.
-        * kernel areas are mapped by PP bits 00
-        * and and there is no kernel RO (_PAGE_KERNEL_RO).
-        * User area mapped by 0x2 and read only use by
-        * 0x3.
+        * Linux uses slb key 0 for kernel and 1 for user.
+        * kernel areas are mapped with PP=00
+        * and there is no kernel RO (_PAGE_KERNEL_RO).
+        * User area is mapped with PP=0x2 for read/write
+        * or PP=0x3 for read-only (including writeable but clean pages).
         */
        if (pteflags & _PAGE_USER) {
                rflags |= 0x2;
@@ -265,28 +265,32 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
        return ret < 0 ? ret : 0;
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
 int htab_remove_mapping(unsigned long vstart, unsigned long vend,
                      int psize, int ssize)
 {
        unsigned long vaddr;
        unsigned int step, shift;
+       int rc;
+       int ret = 0;
 
        shift = mmu_psize_defs[psize].shift;
        step = 1 << shift;
 
-       if (!ppc_md.hpte_removebolted) {
-               printk(KERN_WARNING "Platform doesn't implement "
-                               "hpte_removebolted\n");
-               return -EINVAL;
-       }
+       if (!ppc_md.hpte_removebolted)
+               return -ENODEV;
 
-       for (vaddr = vstart; vaddr < vend; vaddr += step)
-               ppc_md.hpte_removebolted(vaddr, psize, ssize);
+       for (vaddr = vstart; vaddr < vend; vaddr += step) {
+               rc = ppc_md.hpte_removebolted(vaddr, psize, ssize);
+               if (rc == -ENOENT) {
+                       ret = -ENOENT;
+                       continue;
+               }
+               if (rc < 0)
+                       return rc;
+       }
 
-       return 0;
+       return ret;
 }
-#endif /* CONFIG_MEMORY_HOTPLUG */
 
 static int __init htab_dt_scan_seg_sizes(unsigned long node,
                                         const char *uname, int depth,
@@ -607,10 +611,28 @@ static int __init htab_dt_scan_pftsize(unsigned long node,
        return 0;
 }
 
-static unsigned long __init htab_get_table_size(void)
+unsigned htab_shift_for_mem_size(unsigned long mem_size)
 {
-       unsigned long mem_size, rnd_mem_size, pteg_count, psize;
+       unsigned memshift = __ilog2(mem_size);
+       unsigned pshift = mmu_psize_defs[mmu_virtual_psize].shift;
+       unsigned pteg_shift;
+
+       /* round mem_size up to next power of 2 */
+       if ((1UL << memshift) < mem_size)
+               memshift += 1;
+
+       /* aim for 2 pages / pteg */
+       pteg_shift = memshift - (pshift + 1);
 
+       /*
+        * 2^11 PTEGS of 128 bytes each, ie. 2^18 bytes is the minimum htab
+        * size permitted by the architecture.
+        */
+       return max(pteg_shift + 7, 18U);
+}
+
+static unsigned long __init htab_get_table_size(void)
+{
        /* If hash size isn't already provided by the platform, we try to
         * retrieve it from the device-tree. If it's not there neither, we
         * calculate it now based on the total RAM size
@@ -620,31 +642,30 @@ static unsigned long __init htab_get_table_size(void)
        if (ppc64_pft_size)
                return 1UL << ppc64_pft_size;
 
-       /* round mem_size up to next power of 2 */
-       mem_size = memblock_phys_mem_size();
-       rnd_mem_size = 1UL << __ilog2(mem_size);
-       if (rnd_mem_size < mem_size)
-               rnd_mem_size <<= 1;
-
-       /* # pages / 2 */
-       psize = mmu_psize_defs[mmu_virtual_psize].shift;
-       pteg_count = max(rnd_mem_size >> (psize + 1), 1UL << 11);
-
-       return pteg_count << 7;
+       return 1UL << htab_shift_for_mem_size(memblock_phys_mem_size());
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 int create_section_mapping(unsigned long start, unsigned long end)
 {
-       return htab_bolt_mapping(start, end, __pa(start),
-                                pgprot_val(PAGE_KERNEL), mmu_linear_psize,
-                                mmu_kernel_ssize);
+       int rc = htab_bolt_mapping(start, end, __pa(start),
+                                  pgprot_val(PAGE_KERNEL), mmu_linear_psize,
+                                  mmu_kernel_ssize);
+
+       if (rc < 0) {
+               int rc2 = htab_remove_mapping(start, end, mmu_linear_psize,
+                                             mmu_kernel_ssize);
+               BUG_ON(rc2 && (rc2 != -ENOENT));
+       }
+       return rc;
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
 {
-       return htab_remove_mapping(start, end, mmu_linear_psize,
-                       mmu_kernel_ssize);
+       int rc = htab_remove_mapping(start, end, mmu_linear_psize,
+                                    mmu_kernel_ssize);
+       WARN_ON(rc < 0);
+       return rc;
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
index e2138c7..8555fce 100644 (file)
@@ -76,7 +76,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                if (old_pte & _PAGE_F_SECOND)
                        hash = ~hash;
                slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
-               slot += (old_pte & _PAGE_F_GIX) >> 12;
+               slot += (old_pte & _PAGE_F_GIX) >> _PAGE_F_GIX_SHIFT;
 
                if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
                                         mmu_psize, ssize, flags) == -1)
@@ -105,7 +105,8 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                        return -1;
                }
 
-               new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX);
+               new_pte |= (slot << _PAGE_F_GIX_SHIFT) &
+                       (_PAGE_F_SECOND | _PAGE_F_GIX);
        }
 
        /*
index 744e24b..6dd272b 100644 (file)
@@ -107,8 +107,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                kmem_cache_free(cachep, new);
        else {
 #ifdef CONFIG_PPC_BOOK3S_64
-               hpdp->pd = (unsigned long)new |
-                           (shift_to_mmu_psize(pshift) << 2);
+               hpdp->pd = __pa(new) | (shift_to_mmu_psize(pshift) << 2);
 #else
                hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
 #endif
index c2b7716..c899fe3 100644 (file)
@@ -178,10 +178,6 @@ void __init MMU_init(void)
        /* Initialize early top-down ioremap allocator */
        ioremap_bot = IOREMAP_TOP;
 
-       /* Map in I/O resources */
-       if (ppc_md.progress)
-               ppc_md.progress("MMU:setio", 0x302);
-
        if (ppc_md.progress)
                ppc_md.progress("MMU:exit", 0x211);
 
@@ -193,22 +189,3 @@ void __init MMU_init(void)
        /* Shortly after that, the entire linear mapping will be available */
        memblock_set_current_limit(lowmem_end_addr);
 }
-
-#ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
-void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-                               phys_addr_t first_memblock_size)
-{
-       /* We don't currently support the first MEMBLOCK not mapping 0
-        * physical on those processors
-        */
-       BUG_ON(first_memblock_base != 0);
-
-#ifdef CONFIG_PIN_TLB
-       /* 8xx can only access 24MB at the moment */
-       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000));
-#else
-       /* 8xx can only access 8MB at the moment */
-       memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
-#endif
-}
-#endif /* CONFIG_8xx */
index 379a6a9..ba65566 100644 (file)
@@ -85,6 +85,11 @@ static void pgd_ctor(void *addr)
        memset(addr, 0, PGD_TABLE_SIZE);
 }
 
+static void pud_ctor(void *addr)
+{
+       memset(addr, 0, PUD_TABLE_SIZE);
+}
+
 static void pmd_ctor(void *addr)
 {
        memset(addr, 0, PMD_TABLE_SIZE);
@@ -138,14 +143,18 @@ void pgtable_cache_init(void)
 {
        pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor);
        pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor);
+       /*
+        * In all current configs, when the PUD index exists it's the
+        * same size as either the pgd or pmd index except with THP enabled
+        * on book3s 64
+        */
+       if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
+               pgtable_cache_add(PUD_INDEX_SIZE, pud_ctor);
+
        if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_CACHE_INDEX))
                panic("Couldn't allocate pgtable caches");
-       /* In all current configs, when the PUD index exists it's the
-        * same size as either the pgd or pmd index.  Verify that the
-        * initialization above has also created a PUD cache.  This
-        * will need re-examiniation if we add new possibilities for
-        * the pagetable layout. */
-       BUG_ON(PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE));
+       if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
+               panic("Couldn't allocate pud pgtable caches");
 }
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
@@ -188,9 +197,9 @@ static int __meminit vmemmap_populated(unsigned long start, int page_size)
  */
 
 #ifdef CONFIG_PPC_BOOK3E
-static void __meminit vmemmap_create_mapping(unsigned long start,
-                                            unsigned long page_size,
-                                            unsigned long phys)
+static int __meminit vmemmap_create_mapping(unsigned long start,
+                                           unsigned long page_size,
+                                           unsigned long phys)
 {
        /* Create a PTE encoding without page size */
        unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED |
@@ -208,6 +217,8 @@ static void __meminit vmemmap_create_mapping(unsigned long start,
         */
        for (i = 0; i < page_size; i += PAGE_SIZE)
                BUG_ON(map_kernel_page(start + i, phys, flags));
+
+       return 0;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -217,25 +228,31 @@ static void vmemmap_remove_mapping(unsigned long start,
 }
 #endif
 #else /* CONFIG_PPC_BOOK3E */
-static void __meminit vmemmap_create_mapping(unsigned long start,
-                                            unsigned long page_size,
-                                            unsigned long phys)
+static int __meminit vmemmap_create_mapping(unsigned long start,
+                                           unsigned long page_size,
+                                           unsigned long phys)
 {
-       int  mapped = htab_bolt_mapping(start, start + page_size, phys,
-                                       pgprot_val(PAGE_KERNEL),
-                                       mmu_vmemmap_psize,
-                                       mmu_kernel_ssize);
-       BUG_ON(mapped < 0);
+       int rc = htab_bolt_mapping(start, start + page_size, phys,
+                                  pgprot_val(PAGE_KERNEL),
+                                  mmu_vmemmap_psize, mmu_kernel_ssize);
+       if (rc < 0) {
+               int rc2 = htab_remove_mapping(start, start + page_size,
+                                             mmu_vmemmap_psize,
+                                             mmu_kernel_ssize);
+               BUG_ON(rc2 && (rc2 != -ENOENT));
+       }
+       return rc;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 static void vmemmap_remove_mapping(unsigned long start,
                                   unsigned long page_size)
 {
-       int mapped = htab_remove_mapping(start, start + page_size,
-                                        mmu_vmemmap_psize,
-                                        mmu_kernel_ssize);
-       BUG_ON(mapped < 0);
+       int rc = htab_remove_mapping(start, start + page_size,
+                                    mmu_vmemmap_psize,
+                                    mmu_kernel_ssize);
+       BUG_ON((rc < 0) && (rc != -ENOENT));
+       WARN_ON(rc == -ENOENT);
 }
 #endif
 
@@ -303,6 +320,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
 
        for (; start < end; start += page_size) {
                void *p;
+               int rc;
 
                if (vmemmap_populated(start, page_size))
                        continue;
@@ -316,7 +334,13 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
                pr_debug("      * %016lx..%016lx allocated at %p\n",
                         start, start + page_size, p);
 
-               vmemmap_create_mapping(start, page_size, __pa(p));
+               rc = vmemmap_create_mapping(start, page_size, __pa(p));
+               if (rc < 0) {
+                       pr_warning(
+                               "vmemmap_populate: Unable to create vmemmap mapping: %d\n",
+                               rc);
+                       return -EFAULT;
+               }
        }
 
        return 0;
index f078a1f..ac79dbd 100644 (file)
@@ -119,12 +119,18 @@ int arch_add_memory(int nid, u64 start, u64 size, bool for_device)
        struct zone *zone;
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
+       int rc;
 
        pgdata = NODE_DATA(nid);
 
        start = (unsigned long)__va(start);
-       if (create_section_mapping(start, start + size))
-               return -EINVAL;
+       rc = create_section_mapping(start, start + size);
+       if (rc) {
+               pr_warning(
+                       "Unable to create mapping for hot added memory 0x%llx..0x%llx: %d\n",
+                       start, start + size, rc);
+               return -EFAULT;
+       }
 
        /* this should work for most non-highmem platforms */
        zone = pgdata->node_zones +
index 9f58ff4..bfb7c0b 100644 (file)
@@ -100,7 +100,6 @@ extern void setbat(int index, unsigned long virt, phys_addr_t phys,
 
 extern int __map_without_bats;
 extern int __allow_ioremap_reserved;
-extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
 struct hash_pte;
@@ -110,7 +109,8 @@ extern unsigned long Hash_size, Hash_mask;
 #endif /* CONFIG_PPC32 */
 
 #ifdef CONFIG_PPC64
-extern int map_kernel_page(unsigned long ea, unsigned long pa, int flags);
+extern int map_kernel_page(unsigned long ea, unsigned long pa,
+                          unsigned long flags);
 #endif /* CONFIG_PPC64 */
 
 extern unsigned long ioremap_bot;
@@ -132,22 +132,17 @@ extern void wii_memory_fixups(void);
 /* ...and now those things that may be slightly different between processor
  * architectures.  -- Dan
  */
-#if defined(CONFIG_8xx)
-#define MMU_init_hw()          do { } while(0)
-#define mmu_mapin_ram(top)     (0UL)
-
-#elif defined(CONFIG_4xx)
+#ifdef CONFIG_PPC32
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(unsigned long top);
+#endif
 
-#elif defined(CONFIG_PPC_FSL_BOOK3E)
+#ifdef CONFIG_PPC_FSL_BOOK3E
 extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx,
                                     bool dryrun);
 extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
                                 phys_addr_t phys);
 #ifdef CONFIG_PPC32
-extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(unsigned long top);
 extern void adjust_total_lowmem(void);
 extern int switch_to_as1(void);
 extern void restore_to_as0(int esel, int offset, void *dt_ptr, int bootcpu);
@@ -162,8 +157,14 @@ struct tlbcam {
        u32     MAS3;
        u32     MAS7;
 };
-#elif defined(CONFIG_PPC32)
-/* anything 32-bit except 4xx or 8xx */
-extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(unsigned long top);
+#endif
+
+#if defined(CONFIG_6xx) || defined(CONFIG_FSL_BOOKE)
+/* 6xx have BATS */
+/* FSL_BOOKE have TLBCAM */
+phys_addr_t v_block_mapped(unsigned long va);
+unsigned long p_block_mapped(phys_addr_t pa);
+#else
+static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
+static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
 #endif
index 7692d1b..bf7bf32 100644 (file)
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_base;
 unsigned long ioremap_bot;
 EXPORT_SYMBOL(ioremap_bot);    /* aka VMALLOC_END */
 
-#ifdef CONFIG_6xx
-#define HAVE_BATS      1
-#endif
-
-#if defined(CONFIG_FSL_BOOKE)
-#define HAVE_TLBCAM    1
-#endif
-
-extern char etext[], _stext[];
-
-#ifdef HAVE_BATS
-extern phys_addr_t v_mapped_by_bats(unsigned long va);
-extern unsigned long p_mapped_by_bats(phys_addr_t pa);
-#else /* !HAVE_BATS */
-#define v_mapped_by_bats(x)    (0UL)
-#define p_mapped_by_bats(x)    (0UL)
-#endif /* HAVE_BATS */
-
-#ifdef HAVE_TLBCAM
-extern phys_addr_t v_mapped_by_tlbcam(unsigned long va);
-extern unsigned long p_mapped_by_tlbcam(phys_addr_t pa);
-#else /* !HAVE_TLBCAM */
-#define v_mapped_by_tlbcam(x)  (0UL)
-#define p_mapped_by_tlbcam(x)  (0UL)
-#endif /* HAVE_TLBCAM */
+extern char etext[], _stext[], _sinittext[], _einittext[];
 
 #define PGDIR_ORDER    (32 + PGD_T_LOG2 - PGDIR_SHIFT)
 
@@ -197,7 +172,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
        /*
         * Choose an address to map it to.
         * Once the vmalloc system is running, we use it.
-        * Before then, we use space going down from ioremap_base
+        * Before then, we use space going down from IOREMAP_TOP
         * (ioremap_bot records where we're up to).
         */
        p = addr & PAGE_MASK;
@@ -228,19 +203,10 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
 
        /*
         * Is it already mapped?  Perhaps overlapped by a previous
-        * BAT mapping.  If the whole area is mapped then we're done,
-        * otherwise remap it since we want to keep the virt addrs for
-        * each request contiguous.
-        *
-        * We make the assumption here that if the bottom and top
-        * of the range we want are mapped then it's mapped to the
-        * same virt address (and this is contiguous).
-        *  -- Cort
+        * mapping.
         */
-       if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
-               goto out;
-
-       if ((v = p_mapped_by_tlbcam(p)))
+       v = p_block_mapped(p);
+       if (v)
                goto out;
 
        if (slab_is_available()) {
@@ -278,7 +244,8 @@ void iounmap(volatile void __iomem *addr)
         * If mapped by BATs then there is nothing to do.
         * Calling vfree() generates a benign warning.
         */
-       if (v_mapped_by_bats((unsigned long)addr)) return;
+       if (v_block_mapped((unsigned long)addr))
+               return;
 
        if (addr > high_memory && (unsigned long) addr < ioremap_bot)
                vunmap((void *) (PAGE_MASK & (unsigned long)addr));
@@ -322,7 +289,8 @@ void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
        v = PAGE_OFFSET + s;
        p = memstart_addr + s;
        for (; s < top; s += PAGE_SIZE) {
-               ktext = ((char *) v >= _stext && (char *) v < etext);
+               ktext = ((char *)v >= _stext && (char *)v < etext) ||
+                       ((char *)v >= _sinittext && (char *)v < _einittext);
                f = ktext ? pgprot_val(PAGE_KERNEL_TEXT) : pgprot_val(PAGE_KERNEL);
                map_page(v, p, f);
 #ifdef CONFIG_PPC_STD_MMU_32
@@ -403,7 +371,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot)
        BUG_ON(PageHighMem(page));
        address = (unsigned long)page_address(page);
 
-       if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address))
+       if (v_block_mapped(address))
                return 0;
        if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
                return -EINVAL;
index d9cc66c..3471060 100644 (file)
@@ -88,7 +88,7 @@ static __ref void *early_alloc_pgtable(unsigned long size)
  * map_kernel_page adds an entry to the ioremap page table
  * and adds an entry to the HPT, possibly bolting it
  */
-int map_kernel_page(unsigned long ea, unsigned long pa, int flags)
+int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags)
 {
        pgd_t *pgdp;
        pud_t *pudp;
@@ -749,7 +749,7 @@ pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
 {
        unsigned long pmdv;
 
-       pmdv = pfn << PTE_RPN_SHIFT;
+       pmdv = (pfn << PTE_RPN_SHIFT) & PTE_RPN_MASK;
        return pmd_set_protbits(__pmd(pmdv), pgprot);
 }
 
@@ -817,6 +817,13 @@ pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
 
 int has_transparent_hugepage(void)
 {
+
+       BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) >= MAX_ORDER,
+               "hugepages can't be allocated by the buddy allocator");
+
+       BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) < 2,
+                        "We need more than 2 pages to do deferred thp split");
+
        if (!mmu_has_feature(MMU_FTR_16M_PAGE))
                return 0;
        /*
index 6b2f3e4..2a049fb 100644 (file)
@@ -49,7 +49,7 @@ struct batrange {             /* stores address ranges mapped by BATs */
 /*
  * Return PA for this VA if it is mapped by a BAT, or 0
  */
-phys_addr_t v_mapped_by_bats(unsigned long va)
+phys_addr_t v_block_mapped(unsigned long va)
 {
        int b;
        for (b = 0; b < 4; ++b)
@@ -61,7 +61,7 @@ phys_addr_t v_mapped_by_bats(unsigned long va)
 /*
  * Return VA for a given PA or 0 if not mapped
  */
-unsigned long p_mapped_by_bats(phys_addr_t pa)
+unsigned long p_block_mapped(phys_addr_t pa)
 {
        int b;
        for (b = 0; b < 4; ++b)
index 29d6987..eb82d78 100644 (file)
@@ -895,7 +895,7 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_PAIRED_MAS)
 BEGIN_MMU_FTR_SECTION
 virt_page_table_tlb_miss_done:
 
-       /* We have overriden MAS2:EPN but currently our primary TLB miss
+       /* We have overridden MAS2:EPN but currently our primary TLB miss
         * handler will always restore it so that should not be an issue,
         * if we ever optimize the primary handler to not write MAS2 on
         * some cases, we'll have to restore MAS2:EPN here based on the
index bb04e4d..f466848 100644 (file)
@@ -640,9 +640,7 @@ static void early_init_this_mmu(void)
                 * transient mapping would cause problems.
                 */
 #ifdef CONFIG_SMP
-               if (cpu != boot_cpuid &&
-                   (cpu != cpu_first_thread_sibling(cpu) ||
-                    cpu == cpu_first_thread_sibling(boot_cpuid)))
+               if (hweight32(get_tensr()) > 1)
                        map = false;
 #endif
 
index 68c4775..eabecfc 100644 (file)
@@ -108,7 +108,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
        blr
 2:
 #ifdef CONFIG_PPC_47x
-       oris    r7,r6,0x8000    /* specify way explicitely */
+       oris    r7,r6,0x8000    /* specify way explicitly */
        clrrwi  r4,r3,12        /* get an EPN for the hashing with V = 0 */
        ori     r4,r4,PPC47x_TLBE_SIZE
        tlbwe   r4,r7,0         /* write it */
@@ -149,7 +149,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
        li      r3,-1           /* Current set */
        lis     r10,tlb_47x_boltmap@h
        ori     r10,r10,tlb_47x_boltmap@l
-       lis     r7,0x8000       /* Specify way explicitely */
+       lis     r7,0x8000       /* Specify way explicitly */
 
        b       9f              /* For each set */
 
index 863d893..c82497a 100644 (file)
@@ -208,7 +208,7 @@ static void pm_rtas_reset_signals(u32 node)
 
        /*
         * The debug bus is being set to the passthru disable state.
-        * However, the FW still expects atleast one legal signal routing
+        * However, the FW still expects at least one legal signal routing
         * entry or it will return an error on the arguments.   If we don't
         * supply a valid entry, we must ignore all return values.  Ignoring
         * all return values means we might miss an error we should be
@@ -1008,7 +1008,7 @@ static int initial_lfsr[] = {
  *
  * To avoid the time to compute the LFSR, a lookup table is used.  The 24 bit
  * LFSR sequence is broken into four ranges.  The spacing of the precomputed
- * values is adjusted in each range so the error between the user specifed
+ * values is adjusted in each range so the error between the user specified
  * number (N) of events between samples and the actual number of events based
  * on the precomputed value will be les then about 6.2%.  Note, if the user
  * specifies N < 2^16, the LFSR value that is 2^16 from the end will be used.
index d1e65ce..97a1d40 100644 (file)
@@ -651,7 +651,7 @@ static void pmao_restore_workaround(bool ebb)
 
        /*
         * We are already soft-disabled in power_pmu_enable(). We need to hard
-        * enable to actually prevent the PMU exception from firing.
+        * disable to actually prevent the PMU exception from firing.
         */
        hard_irq_disable();
 
index 3b09ecf..2da41b7 100644 (file)
 #include "hv-24x7-catalog.h"
 #include "hv-common.h"
 
-static const char *event_domain_suffix(unsigned domain)
-{
-       switch (domain) {
-#define DOMAIN(n, v, x, c)             \
-       case HV_PERF_DOMAIN_##n:        \
-               return "__" #n;
-#include "hv-24x7-domains.h"
-#undef DOMAIN
-       default:
-               WARN(1, "unknown domain %d\n", domain);
-               return "__UNKNOWN_DOMAIN_SUFFIX";
-       }
-}
-
 static bool domain_is_valid(unsigned domain)
 {
        switch (domain) {
@@ -68,6 +54,24 @@ static bool is_physical_domain(unsigned domain)
        }
 }
 
+static const char *domain_name(unsigned domain)
+{
+       if (!domain_is_valid(domain))
+               return NULL;
+
+       switch (domain) {
+       case HV_PERF_DOMAIN_PHYS_CHIP:          return "Physical Chip";
+       case HV_PERF_DOMAIN_PHYS_CORE:          return "Physical Core";
+       case HV_PERF_DOMAIN_VCPU_HOME_CORE:     return "VCPU Home Core";
+       case HV_PERF_DOMAIN_VCPU_HOME_CHIP:     return "VCPU Home Chip";
+       case HV_PERF_DOMAIN_VCPU_HOME_NODE:     return "VCPU Home Node";
+       case HV_PERF_DOMAIN_VCPU_REMOTE_NODE:   return "VCPU Remote Node";
+       }
+
+       WARN_ON_ONCE(domain);
+       return NULL;
+}
+
 static bool catalog_entry_domain_is_valid(unsigned domain)
 {
        return is_physical_domain(domain);
@@ -101,6 +105,7 @@ static bool catalog_entry_domain_is_valid(unsigned domain)
 EVENT_DEFINE_RANGE_FORMAT(domain, config, 0, 3);
 /* u16 */
 EVENT_DEFINE_RANGE_FORMAT(core, config, 16, 31);
+EVENT_DEFINE_RANGE_FORMAT(chip, config, 16, 31);
 EVENT_DEFINE_RANGE_FORMAT(vcpu, config, 16, 31);
 /* u32, see "data_offset" */
 EVENT_DEFINE_RANGE_FORMAT(offset, config, 32, 63);
@@ -115,6 +120,7 @@ static struct attribute *format_attrs[] = {
        &format_attr_domain.attr,
        &format_attr_offset.attr,
        &format_attr_core.attr,
+       &format_attr_chip.attr,
        &format_attr_vcpu.attr,
        &format_attr_lpar.attr,
        NULL,
@@ -274,32 +280,70 @@ static unsigned long h_get_24x7_catalog_page(char page[],
                                        version, index);
 }
 
-static unsigned core_domains[] = {
-       HV_PERF_DOMAIN_PHYS_CORE,
-       HV_PERF_DOMAIN_VCPU_HOME_CORE,
-       HV_PERF_DOMAIN_VCPU_HOME_CHIP,
-       HV_PERF_DOMAIN_VCPU_HOME_NODE,
-       HV_PERF_DOMAIN_VCPU_REMOTE_NODE,
-};
-/* chip event data always yeilds a single event, core yeilds multiple */
-#define MAX_EVENTS_PER_EVENT_DATA ARRAY_SIZE(core_domains)
-
+/*
+ * Each event we find in the catalog, will have a sysfs entry. Format the
+ * data for this sysfs entry based on the event's domain.
+ *
+ * Events belonging to the Chip domain can only be monitored in that domain.
+ * i.e the domain for these events is a fixed/knwon value.
+ *
+ * Events belonging to the Core domain can be monitored either in the physical
+ * core or in one of the virtual CPU domains. So the domain value for these
+ * events must be specified by the user (i.e is a required parameter). Format
+ * the Core events with 'domain=?' so the perf-tool can error check required
+ * parameters.
+ *
+ * NOTE: For the Core domain events, rather than making domain a required
+ *      parameter we could default it to PHYS_CORE and allowe users to
+ *      override the domain to one of the VCPU domains.
+ *
+ *      However, this can make the interface a little inconsistent.
+ *
+ *      If we set domain=2 (PHYS_CHIP) and allow user to override this field
+ *      the user may be tempted to also modify the "offset=x" field in which
+ *      can lead to confusing usage. Consider the HPM_PCYC (offset=0x18) and
+ *      HPM_INST (offset=0x20) events. With:
+ *
+ *             perf stat -e hv_24x7/HPM_PCYC,offset=0x20/
+ *
+ *     we end up monitoring HPM_INST, while the command line has HPM_PCYC.
+ *
+ *     By not assigning a default value to the domain for the Core events,
+ *     we can have simple guidelines:
+ *
+ *             - Specifying values for parameters with "=?" is required.
+ *
+ *             - Specifying (i.e overriding) values for other parameters
+ *               is undefined.
+ */
 static char *event_fmt(struct hv_24x7_event_data *event, unsigned domain)
 {
        const char *sindex;
        const char *lpar;
+       const char *domain_str;
+       char buf[8];
 
-       if (is_physical_domain(domain)) {
+       switch (domain) {
+       case HV_PERF_DOMAIN_PHYS_CHIP:
+               snprintf(buf, sizeof(buf), "%d", domain);
+               domain_str = buf;
+               lpar = "0x0";
+               sindex = "chip";
+               break;
+       case HV_PERF_DOMAIN_PHYS_CORE:
+               domain_str = "?";
                lpar = "0x0";
                sindex = "core";
-       } else {
+               break;
+       default:
+               domain_str = "?";
                lpar = "?";
                sindex = "vcpu";
        }
 
        return kasprintf(GFP_KERNEL,
-                       "domain=0x%x,offset=0x%x,%s=?,lpar=%s",
-                       domain,
+                       "domain=%s,offset=0x%x,%s=?,lpar=%s",
+                       domain_str,
                        be16_to_cpu(event->event_counter_offs) +
                                be16_to_cpu(event->event_group_record_offs),
                        sindex,
@@ -339,6 +383,15 @@ static struct attribute *device_str_attr_create_(char *name, char *str)
        return &attr->attr.attr;
 }
 
+/*
+ * Allocate and initialize strings representing event attributes.
+ *
+ * NOTE: The strings allocated here are never destroyed and continue to
+ *      exist till shutdown. This is to allow us to create as many events
+ *      from the catalog as possible, even if we encounter errors with some.
+ *      In case of changes to error paths in future, these may need to be
+ *      freed by the caller.
+ */
 static struct attribute *device_str_attr_create(char *name, int name_max,
                                                int name_nonce,
                                                char *str, size_t str_max)
@@ -370,16 +423,6 @@ out_s:
        return NULL;
 }
 
-static void device_str_attr_destroy(struct attribute *attr)
-{
-       struct dev_ext_attribute *d;
-
-       d = container_of(attr, struct dev_ext_attribute, attr.attr);
-       kfree(d->var);
-       kfree(d->attr.attr.name);
-       kfree(d);
-}
-
 static struct attribute *event_to_attr(unsigned ix,
                                       struct hv_24x7_event_data *event,
                                       unsigned domain,
@@ -387,7 +430,6 @@ static struct attribute *event_to_attr(unsigned ix,
 {
        int event_name_len;
        char *ev_name, *a_ev_name, *val;
-       const char *ev_suffix;
        struct attribute *attr;
 
        if (!domain_is_valid(domain)) {
@@ -400,14 +442,13 @@ static struct attribute *event_to_attr(unsigned ix,
        if (!val)
                return NULL;
 
-       ev_suffix = event_domain_suffix(domain);
        ev_name = event_name(event, &event_name_len);
        if (!nonce)
-               a_ev_name = kasprintf(GFP_KERNEL, "%.*s%s",
-                               (int)event_name_len, ev_name, ev_suffix);
+               a_ev_name = kasprintf(GFP_KERNEL, "%.*s",
+                               (int)event_name_len, ev_name);
        else
-               a_ev_name = kasprintf(GFP_KERNEL, "%.*s%s__%d",
-                               (int)event_name_len, ev_name, ev_suffix, nonce);
+               a_ev_name = kasprintf(GFP_KERNEL, "%.*s__%d",
+                               (int)event_name_len, ev_name, nonce);
 
        if (!a_ev_name)
                goto out_val;
@@ -452,45 +493,14 @@ event_to_long_desc_attr(struct hv_24x7_event_data *event, int nonce)
        return device_str_attr_create(name, nl, nonce, desc, dl);
 }
 
-static ssize_t event_data_to_attrs(unsigned ix, struct attribute **attrs,
+static int event_data_to_attrs(unsigned ix, struct attribute **attrs,
                                   struct hv_24x7_event_data *event, int nonce)
 {
-       unsigned i;
-
-       switch (event->domain) {
-       case HV_PERF_DOMAIN_PHYS_CHIP:
-               *attrs = event_to_attr(ix, event, event->domain, nonce);
-               return 1;
-       case HV_PERF_DOMAIN_PHYS_CORE:
-               for (i = 0; i < ARRAY_SIZE(core_domains); i++) {
-                       attrs[i] = event_to_attr(ix, event, core_domains[i],
-                                               nonce);
-                       if (!attrs[i]) {
-                               pr_warn("catalog event %u: individual attr %u "
-                                       "creation failure\n", ix, i);
-                               for (; i; i--)
-                                       device_str_attr_destroy(attrs[i - 1]);
-                               return -1;
-                       }
-               }
-               return i;
-       default:
-               pr_warn("catalog event %u: domain %u is not allowed in the "
-                               "catalog\n", ix, event->domain);
+       *attrs = event_to_attr(ix, event, event->domain, nonce);
+       if (!*attrs)
                return -1;
-       }
-}
 
-static size_t event_to_attr_ct(struct hv_24x7_event_data *event)
-{
-       switch (event->domain) {
-       case HV_PERF_DOMAIN_PHYS_CHIP:
-               return 1;
-       case HV_PERF_DOMAIN_PHYS_CORE:
-               return ARRAY_SIZE(core_domains);
-       default:
-               return 0;
-       }
+       return 0;
 }
 
 /* */
@@ -718,9 +728,8 @@ static int create_events_from_catalog(struct attribute ***events_,
                goto e_free;
        }
 
-       if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) {
-               pr_err("event_entry_count %zu is invalid\n",
-                               event_entry_count);
+       if (SIZE_MAX - 1 < event_entry_count) {
+               pr_err("event_entry_count %zu is invalid\n", event_entry_count);
                ret = -EIO;
                goto e_free;
        }
@@ -793,7 +802,7 @@ static int create_events_from_catalog(struct attribute ***events_,
                        continue;
                }
 
-               attr_max += event_to_attr_ct(event);
+               attr_max++;
        }
 
        event_idx_last = event_idx;
@@ -843,12 +852,12 @@ static int create_events_from_catalog(struct attribute ***events_,
                nonce = event_uniq_add(&ev_uniq, name, nl, event->domain);
                ct    = event_data_to_attrs(event_idx, events + event_attr_ct,
                                            event, nonce);
-               if (ct <= 0) {
+               if (ct < 0) {
                        pr_warn("event %zu (%.*s) creation failure, skipping\n",
                                event_idx, nl, name);
                        junk_events++;
                } else {
-                       event_attr_ct += ct;
+                       event_attr_ct++;
                        event_descs[desc_ct] = event_to_desc_attr(event, nonce);
                        if (event_descs[desc_ct])
                                desc_ct++;
@@ -953,6 +962,27 @@ e_free:
        return ret;
 }
 
+static ssize_t domains_show(struct device *dev, struct device_attribute *attr,
+                           char *page)
+{
+       int d, n, count = 0;
+       const char *str;
+
+       for (d = 0; d < HV_PERF_DOMAIN_MAX; d++) {
+               str = domain_name(d);
+               if (!str)
+                       continue;
+
+               n = sprintf(page, "%d: %s\n", d, str);
+               if (n < 0)
+                       break;
+
+               count += n;
+               page += n;
+       }
+       return count;
+}
+
 #define PAGE_0_ATTR(_name, _fmt, _expr)                                \
 static ssize_t _name##_show(struct device *dev,                        \
                            struct device_attribute *dev_attr,  \
@@ -981,6 +1011,7 @@ PAGE_0_ATTR(catalog_version, "%lld\n",
 PAGE_0_ATTR(catalog_len, "%lld\n",
                (unsigned long long)be32_to_cpu(page_0->length) * 4096);
 static BIN_ATTR_RO(catalog, 0/* real length varies */);
+static DEVICE_ATTR_RO(domains);
 
 static struct bin_attribute *if_bin_attrs[] = {
        &bin_attr_catalog,
@@ -990,6 +1021,7 @@ static struct bin_attribute *if_bin_attrs[] = {
 static struct attribute *if_attrs[] = {
        &dev_attr_catalog_len.attr,
        &dev_attr_catalog_version.attr,
+       &dev_attr_domains.attr,
        NULL,
 };
 
@@ -1081,10 +1113,16 @@ static int add_event_to_24x7_request(struct perf_event *event,
                return -EINVAL;
        }
 
-       if (is_physical_domain(event_get_domain(event)))
+       switch (event_get_domain(event)) {
+       case HV_PERF_DOMAIN_PHYS_CHIP:
+               idx = event_get_chip(event);
+               break;
+       case HV_PERF_DOMAIN_PHYS_CORE:
                idx = event_get_core(event);
-       else
+               break;
+       default:
                idx = event_get_vcpu(event);
+       }
 
        i = request_buffer->num_requests++;
        req = &request_buffer->requests[i];
@@ -1200,11 +1238,12 @@ static int h_24x7_event_init(struct perf_event *event)
                return -EACCES;
        }
 
-       /* see if the event complains */
+       /* Get the initial value of the counter for this event */
        if (single_24x7_request(event, &ct)) {
                pr_devel("test hcall failed\n");
                return -EIO;
        }
+       (void)local64_xchg(&event->hw.prev_count, ct);
 
        return 0;
 }
@@ -1267,6 +1306,16 @@ static void h_24x7_event_read(struct perf_event *event)
                        h24x7hw = &get_cpu_var(hv_24x7_hw);
                        h24x7hw->events[i] = event;
                        put_cpu_var(h24x7hw);
+                       /*
+                        * Clear the event count so we can compute the _change_
+                        * in the 24x7 raw counter value at the end of the txn.
+                        *
+                        * Note that we could alternatively read the 24x7 value
+                        * now and save its value in event->hw.prev_count. But
+                        * that would require issuing a hcall, which would then
+                        * defeat the purpose of using the txn interface.
+                        */
+                       local64_set(&event->count, 0);
                }
 
                put_cpu_var(hv_24x7_reqb);
index 0f9fa21..791455e 100644 (file)
@@ -7,6 +7,7 @@ enum hv_perf_domains {
 #define DOMAIN(n, v, x, c) HV_PERF_DOMAIN_##n = v,
 #include "hv-24x7-domains.h"
 #undef DOMAIN
+       HV_PERF_DOMAIN_MAX,
 };
 
 struct hv_24x7_request {
@@ -80,7 +81,7 @@ struct hv_24x7_result {
        __u8 results_complete;
        __be16 num_elements_returned;
 
-       /* This is a copy of @data_size from the coresponding hv_24x7_request */
+       /* This is a copy of @data_size from the corresponding hv_24x7_request */
        __be16 result_element_data_size;
        __u8 reserved[0x2];
 
index 856fe6e..7aa3723 100644 (file)
@@ -127,8 +127,16 @@ static const struct attribute_group *attr_groups[] = {
        NULL,
 };
 
-#define GPCI_MAX_DATA_BYTES \
-       (1024 - sizeof(struct hv_get_perf_counter_info_params))
+#define HGPCI_REQ_BUFFER_SIZE  4096
+#define HGPCI_MAX_DATA_BYTES \
+       (HGPCI_REQ_BUFFER_SIZE - sizeof(struct hv_get_perf_counter_info_params))
+
+DEFINE_PER_CPU(char, hv_gpci_reqb[HGPCI_REQ_BUFFER_SIZE]) __aligned(sizeof(uint64_t));
+
+struct hv_gpci_request_buffer {
+       struct hv_get_perf_counter_info_params params;
+       uint8_t bytes[HGPCI_MAX_DATA_BYTES];
+} __packed;
 
 static unsigned long single_gpci_request(u32 req, u32 starting_index,
                u16 secondary_index, u8 version_in, u32 offset, u8 length,
@@ -137,24 +145,21 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
        unsigned long ret;
        size_t i;
        u64 count;
+       struct hv_gpci_request_buffer *arg;
+
+       arg = (void *)get_cpu_var(hv_gpci_reqb);
+       memset(arg, 0, HGPCI_REQ_BUFFER_SIZE);
 
-       struct {
-               struct hv_get_perf_counter_info_params params;
-               uint8_t bytes[GPCI_MAX_DATA_BYTES];
-       } __packed __aligned(sizeof(uint64_t)) arg = {
-               .params = {
-                       .counter_request = cpu_to_be32(req),
-                       .starting_index = cpu_to_be32(starting_index),
-                       .secondary_index = cpu_to_be16(secondary_index),
-                       .counter_info_version_in = version_in,
-               }
-       };
+       arg->params.counter_request = cpu_to_be32(req);
+       arg->params.starting_index = cpu_to_be32(starting_index);
+       arg->params.secondary_index = cpu_to_be16(secondary_index);
+       arg->params.counter_info_version_in = version_in;
 
        ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
-                       virt_to_phys(&arg), sizeof(arg));
+                       virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
        if (ret) {
                pr_devel("hcall failed: 0x%lx\n", ret);
-               return ret;
+               goto out;
        }
 
        /*
@@ -163,9 +168,11 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
         */
        count = 0;
        for (i = offset; i < offset + length; i++)
-               count |= arg.bytes[i] << (i - offset);
+               count |= arg->bytes[i] << (i - offset);
 
        *value = count;
+out:
+       put_cpu_var(hv_gpci_reqb);
        return ret;
 }
 
@@ -245,10 +252,10 @@ static int h_gpci_event_init(struct perf_event *event)
        }
 
        /* last byte within the buffer? */
-       if ((event_get_offset(event) + length) > GPCI_MAX_DATA_BYTES) {
+       if ((event_get_offset(event) + length) > HGPCI_MAX_DATA_BYTES) {
                pr_devel("request outside of buffer: %zu > %zu\n",
                                (size_t)event_get_offset(event) + length,
-                               GPCI_MAX_DATA_BYTES);
+                               HGPCI_MAX_DATA_BYTES);
                return -EINVAL;
        }
 
index 5b62f23..a383c23 100644 (file)
@@ -54,7 +54,7 @@
  * Power7 event codes.
  */
 #define EVENT(_name, _code) \
-       PME_##_name = _code,
+       _name = _code,
 
 enum {
 #include "power7-events-list.h"
@@ -318,14 +318,14 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 }
 
 static int power7_generic_events[] = {
-       [PERF_COUNT_HW_CPU_CYCLES] =                    PME_PM_CYC,
-       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =       PME_PM_GCT_NOSLOT_CYC,
-       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =        PME_PM_CMPLU_STALL,
-       [PERF_COUNT_HW_INSTRUCTIONS] =                  PME_PM_INST_CMPL,
-       [PERF_COUNT_HW_CACHE_REFERENCES] =              PME_PM_LD_REF_L1,
-       [PERF_COUNT_HW_CACHE_MISSES] =                  PME_PM_LD_MISS_L1,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =           PME_PM_BRU_FIN,
-       [PERF_COUNT_HW_BRANCH_MISSES] =                 PME_PM_BR_MPRED,
+       [PERF_COUNT_HW_CPU_CYCLES] =                    PM_CYC,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =       PM_GCT_NOSLOT_CYC,
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =        PM_CMPLU_STALL,
+       [PERF_COUNT_HW_INSTRUCTIONS] =                  PM_INST_CMPL,
+       [PERF_COUNT_HW_CACHE_REFERENCES] =              PM_LD_REF_L1,
+       [PERF_COUNT_HW_CACHE_MISSES] =                  PM_LD_MISS_L1,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =           PM_BRU_FIN,
+       [PERF_COUNT_HW_BRANCH_MISSES] =                 PM_BR_MPRED,
 };
 
 #define C(x)   PERF_COUNT_HW_CACHE_##x
diff --git a/arch/powerpc/perf/power8-events-list.h b/arch/powerpc/perf/power8-events-list.h
new file mode 100644 (file)
index 0000000..741b77e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Performance counter support for POWER8 processors.
+ *
+ * Copyright 2014 Sukadev Bhattiprolu, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Power8 event codes.
+ */
+EVENT(PM_CYC,                                  0x0001e)
+EVENT(PM_GCT_NOSLOT_CYC,                       0x100f8)
+EVENT(PM_CMPLU_STALL,                          0x4000a)
+EVENT(PM_INST_CMPL,                            0x00002)
+EVENT(PM_BRU_FIN,                              0x10068)
+EVENT(PM_BR_MPRED_CMPL,                                0x400f6)
+
+/* All L1 D cache load references counted at finish, gated by reject */
+EVENT(PM_LD_REF_L1,                            0x100ee)
+/* Load Missed L1 */
+EVENT(PM_LD_MISS_L1,                           0x3e054)
+/* Store Missed L1 */
+EVENT(PM_ST_MISS_L1,                           0x300f0)
+/* L1 cache data prefetches */
+EVENT(PM_L1_PREF,                              0x0d8b8)
+/* Instruction fetches from L1 */
+EVENT(PM_INST_FROM_L1,                         0x04080)
+/* Demand iCache Miss */
+EVENT(PM_L1_ICACHE_MISS,                       0x200fd)
+/* Instruction Demand sectors wriittent into IL1 */
+EVENT(PM_L1_DEMAND_WRITE,                      0x0408c)
+/* Instruction prefetch written into IL1 */
+EVENT(PM_IC_PREF_WRITE,                                0x0408e)
+/* The data cache was reloaded from local core's L3 due to a demand load */
+EVENT(PM_DATA_FROM_L3,                         0x4c042)
+/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
+EVENT(PM_DATA_FROM_L3MISS,                     0x300fe)
+/* All successful D-side store dispatches for this thread */
+EVENT(PM_L2_ST,                                        0x17080)
+/* All successful D-side store dispatches for this thread that were L2 Miss */
+EVENT(PM_L2_ST_MISS,                           0x17082)
+/* Total HW L3 prefetches(Load+store) */
+EVENT(PM_L3_PREF_ALL,                          0x4e052)
+/* Data PTEG reload */
+EVENT(PM_DTLB_MISS,                            0x300fc)
+/* ITLB Reloaded */
+EVENT(PM_ITLB_MISS,                            0x400fc)
index 9958ba8..690d918 100644 (file)
 #include <asm/firmware.h>
 #include <asm/cputable.h>
 
-
 /*
  * Some power8 event codes.
  */
-#define PM_CYC                         0x0001e
-#define PM_GCT_NOSLOT_CYC              0x100f8
-#define PM_CMPLU_STALL                 0x4000a
-#define PM_INST_CMPL                   0x00002
-#define PM_BRU_FIN                     0x10068
-#define PM_BR_MPRED_CMPL               0x400f6
-
-/* All L1 D cache load references counted at finish, gated by reject */
-#define PM_LD_REF_L1                   0x100ee
-/* Load Missed L1 */
-#define PM_LD_MISS_L1                  0x3e054
-/* Store Missed L1 */
-#define PM_ST_MISS_L1                  0x300f0
-/* L1 cache data prefetches */
-#define PM_L1_PREF                     0x0d8b8
-/* Instruction fetches from L1 */
-#define PM_INST_FROM_L1                        0x04080
-/* Demand iCache Miss */
-#define PM_L1_ICACHE_MISS              0x200fd
-/* Instruction Demand sectors wriittent into IL1 */
-#define PM_L1_DEMAND_WRITE             0x0408c
-/* Instruction prefetch written into IL1 */
-#define PM_IC_PREF_WRITE               0x0408e
-/* The data cache was reloaded from local core's L3 due to a demand load */
-#define PM_DATA_FROM_L3                        0x4c042
-/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
-#define PM_DATA_FROM_L3MISS            0x300fe
-/* All successful D-side store dispatches for this thread */
-#define PM_L2_ST                       0x17080
-/* All successful D-side store dispatches for this thread that were L2 Miss */
-#define PM_L2_ST_MISS                  0x17082
-/* Total HW L3 prefetches(Load+store) */
-#define PM_L3_PREF_ALL                 0x4e052
-/* Data PTEG reload */
-#define PM_DTLB_MISS                   0x300fc
-/* ITLB Reloaded */
-#define PM_ITLB_MISS                   0x400fc
+#define EVENT(_name, _code)    _name = _code,
+
+enum {
+#include "power8-events-list.h"
+};
 
+#undef EVENT
 
 /*
  * Raw event encoding for POWER8:
@@ -415,7 +383,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
                        pmc_inuse |= 1 << pmc;
        }
 
-       /* In continous sampling mode, update SDAR on TLB miss */
+       /* In continuous sampling mode, update SDAR on TLB miss */
        mmcra = MMCRA_SDAR_MODE_TLB;
        mmcr1 = mmcr2 = 0;
 
@@ -604,6 +572,71 @@ static void power8_disable_pmc(unsigned int pmc, unsigned long mmcr[])
                mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
 }
 
+GENERIC_EVENT_ATTR(cpu-cycles,                 PM_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-frontend,    PM_GCT_NOSLOT_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-backend,     PM_CMPLU_STALL);
+GENERIC_EVENT_ATTR(instructions,               PM_INST_CMPL);
+GENERIC_EVENT_ATTR(branch-instructions,                PM_BRU_FIN);
+GENERIC_EVENT_ATTR(branch-misses,              PM_BR_MPRED_CMPL);
+GENERIC_EVENT_ATTR(cache-references,           PM_LD_REF_L1);
+GENERIC_EVENT_ATTR(cache-misses,               PM_LD_MISS_L1);
+
+CACHE_EVENT_ATTR(L1-dcache-load-misses,                PM_LD_MISS_L1);
+CACHE_EVENT_ATTR(L1-dcache-loads,              PM_LD_REF_L1);
+
+CACHE_EVENT_ATTR(L1-dcache-prefetches,         PM_L1_PREF);
+CACHE_EVENT_ATTR(L1-dcache-store-misses,       PM_ST_MISS_L1);
+CACHE_EVENT_ATTR(L1-icache-load-misses,                PM_L1_ICACHE_MISS);
+CACHE_EVENT_ATTR(L1-icache-loads,              PM_INST_FROM_L1);
+CACHE_EVENT_ATTR(L1-icache-prefetches,         PM_IC_PREF_WRITE);
+
+CACHE_EVENT_ATTR(LLC-load-misses,              PM_DATA_FROM_L3MISS);
+CACHE_EVENT_ATTR(LLC-loads,                    PM_DATA_FROM_L3);
+CACHE_EVENT_ATTR(LLC-prefetches,               PM_L3_PREF_ALL);
+CACHE_EVENT_ATTR(LLC-store-misses,             PM_L2_ST_MISS);
+CACHE_EVENT_ATTR(LLC-stores,                   PM_L2_ST);
+
+CACHE_EVENT_ATTR(branch-load-misses,           PM_BR_MPRED_CMPL);
+CACHE_EVENT_ATTR(branch-loads,                 PM_BRU_FIN);
+CACHE_EVENT_ATTR(dTLB-load-misses,             PM_DTLB_MISS);
+CACHE_EVENT_ATTR(iTLB-load-misses,             PM_ITLB_MISS);
+
+static struct attribute *power8_events_attr[] = {
+       GENERIC_EVENT_PTR(PM_CYC),
+       GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
+       GENERIC_EVENT_PTR(PM_CMPLU_STALL),
+       GENERIC_EVENT_PTR(PM_INST_CMPL),
+       GENERIC_EVENT_PTR(PM_BRU_FIN),
+       GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
+       GENERIC_EVENT_PTR(PM_LD_REF_L1),
+       GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+
+       CACHE_EVENT_PTR(PM_LD_MISS_L1),
+       CACHE_EVENT_PTR(PM_LD_REF_L1),
+       CACHE_EVENT_PTR(PM_L1_PREF),
+       CACHE_EVENT_PTR(PM_ST_MISS_L1),
+       CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
+       CACHE_EVENT_PTR(PM_INST_FROM_L1),
+       CACHE_EVENT_PTR(PM_IC_PREF_WRITE),
+       CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
+       CACHE_EVENT_PTR(PM_DATA_FROM_L3),
+       CACHE_EVENT_PTR(PM_L3_PREF_ALL),
+       CACHE_EVENT_PTR(PM_L2_ST_MISS),
+       CACHE_EVENT_PTR(PM_L2_ST),
+
+       CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
+       CACHE_EVENT_PTR(PM_BRU_FIN),
+
+       CACHE_EVENT_PTR(PM_DTLB_MISS),
+       CACHE_EVENT_PTR(PM_ITLB_MISS),
+       NULL
+};
+
+static struct attribute_group power8_pmu_events_group = {
+       .name = "events",
+       .attrs = power8_events_attr,
+};
+
 PMU_FORMAT_ATTR(event,         "config:0-49");
 PMU_FORMAT_ATTR(pmcxsel,       "config:0-7");
 PMU_FORMAT_ATTR(mark,          "config:8");
@@ -640,6 +673,7 @@ struct attribute_group power8_pmu_format_group = {
 
 static const struct attribute_group *power8_pmu_attr_groups[] = {
        &power8_pmu_format_group,
+       &power8_pmu_events_group,
        NULL,
 };
 
index 6eb3b2a..00282c2 100644 (file)
@@ -319,7 +319,7 @@ mpc52xx_pci_setup(struct pci_controller *hose,
 
        tmp = in_be32(&pci_regs->gscr);
 #if 0
-       /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+       /* Reset the exteral bus ( internal PCI controller is NOT reset ) */
        /* Not necessary and can be a bad thing if for example the bootloader
           is displaying a splash screen or ... Just left here for
           documentation purpose if anyone need it */
index 97915fe..e626461 100644 (file)
@@ -8,6 +8,7 @@ menuconfig FSL_SOC_BOOKE
        select FSL_PCI if PCI
        select SERIAL_8250_EXTENDED if SERIAL_8250
        select SERIAL_8250_SHARE_IRQ if SERIAL_8250
+       select FSL_CORENET_RCPM if PPC_E500MC
        default y
 
 if FSL_SOC_BOOKE
index 1fe7fb9..7bc86da 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_FSL_PMC)            += mpc85xx_pm_ops.o
 
 obj-y += common.o
 
index 949f22c..28720a4 100644 (file)
@@ -9,11 +9,14 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
+#include <asm/fsl_pm.h>
 #include <soc/fsl/qe/qe.h>
 #include <sysdev/cpm2_pic.h>
 
 #include "mpc85xx.h"
 
+const struct fsl_pm_ops *qoriq_pm_ops;
+
 static const struct of_device_id mpc85xx_common_ids[] __initconst = {
        { .type = "soc", },
        { .compatible = "soc", },
index 5ac70de..d7e87ff 100644 (file)
@@ -99,7 +99,7 @@ static void mpc85xx_cds_restart(char *cmd)
                pci_read_config_byte(dev, 0x47, &tmp);
 
                /*
-                *  At this point, the harware reset should have triggered.
+                *  At this point, the hardware reset should have triggered.
                 *  However, if it doesn't work for some mysterious reason,
                 *  just fall through to the default reset below.
                 */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
new file mode 100644 (file)
index 0000000..f05325f
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * MPC85xx PM operators
+ *
+ * Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/fsl/guts.h>
+
+#include <asm/io.h>
+#include <asm/fsl_pm.h>
+
+static struct ccsr_guts __iomem *guts;
+
+static void mpc85xx_irq_mask(int cpu)
+{
+
+}
+
+static void mpc85xx_irq_unmask(int cpu)
+{
+
+}
+
+static void mpc85xx_cpu_die(int cpu)
+{
+       u32 tmp;
+
+       tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
+       mtspr(SPRN_HID0, tmp);
+
+       /* Enter NAP mode. */
+       tmp = mfmsr();
+       tmp |= MSR_WE;
+       asm volatile(
+               "msync\n"
+               "mtmsr %0\n"
+               "isync\n"
+               :
+               : "r" (tmp));
+}
+
+static void mpc85xx_cpu_up_prepare(int cpu)
+{
+
+}
+
+static void mpc85xx_freeze_time_base(bool freeze)
+{
+       uint32_t mask;
+
+       mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
+       if (freeze)
+               setbits32(&guts->devdisr, mask);
+       else
+               clrbits32(&guts->devdisr, mask);
+
+       in_be32(&guts->devdisr);
+}
+
+static const struct of_device_id mpc85xx_smp_guts_ids[] = {
+       { .compatible = "fsl,mpc8572-guts", },
+       { .compatible = "fsl,p1020-guts", },
+       { .compatible = "fsl,p1021-guts", },
+       { .compatible = "fsl,p1022-guts", },
+       { .compatible = "fsl,p1023-guts", },
+       { .compatible = "fsl,p2020-guts", },
+       { .compatible = "fsl,bsc9132-guts", },
+       {},
+};
+
+static const struct fsl_pm_ops mpc85xx_pm_ops = {
+       .freeze_time_base = mpc85xx_freeze_time_base,
+       .irq_mask = mpc85xx_irq_mask,
+       .irq_unmask = mpc85xx_irq_unmask,
+       .cpu_die = mpc85xx_cpu_die,
+       .cpu_up_prepare = mpc85xx_cpu_up_prepare,
+};
+
+int __init mpc85xx_setup_pmc(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
+       if (np) {
+               guts = of_iomap(np, 0);
+               of_node_put(np);
+               if (!guts) {
+                       pr_err("Could not map guts node address\n");
+                       return -ENOMEM;
+               }
+       }
+
+       qoriq_pm_ops = &mpc85xx_pm_ops;
+
+       return 0;
+}
index 6b107ce..fe9f19e 100644 (file)
@@ -2,7 +2,7 @@
  * Author: Andy Fleming <afleming@freescale.com>
  *        Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2006-2008, 2011-2012 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012, 2015 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
@@ -29,6 +28,7 @@
 #include <asm/dbell.h>
 #include <asm/code-patching.h>
 #include <asm/cputhreads.h>
+#include <asm/fsl_pm.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
@@ -43,35 +43,23 @@ struct epapr_spin_table {
        u32     pir;
 };
 
-static struct ccsr_guts __iomem *guts;
+#ifdef CONFIG_HOTPLUG_CPU
 static u64 timebase;
 static int tb_req;
 static int tb_valid;
 
-static void mpc85xx_timebase_freeze(int freeze)
-{
-       uint32_t mask;
-
-       mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
-       if (freeze)
-               setbits32(&guts->devdisr, mask);
-       else
-               clrbits32(&guts->devdisr, mask);
-
-       in_be32(&guts->devdisr);
-}
-
 static void mpc85xx_give_timebase(void)
 {
        unsigned long flags;
 
        local_irq_save(flags);
+       hard_irq_disable();
 
        while (!tb_req)
                barrier();
        tb_req = 0;
 
-       mpc85xx_timebase_freeze(1);
+       qoriq_pm_ops->freeze_time_base(true);
 #ifdef CONFIG_PPC64
        /*
         * e5500/e6500 have a workaround for erratum A-006958 in place
@@ -104,7 +92,7 @@ static void mpc85xx_give_timebase(void)
        while (tb_valid)
                barrier();
 
-       mpc85xx_timebase_freeze(0);
+       qoriq_pm_ops->freeze_time_base(false);
 
        local_irq_restore(flags);
 }
@@ -114,6 +102,7 @@ static void mpc85xx_take_timebase(void)
        unsigned long flags;
 
        local_irq_save(flags);
+       hard_irq_disable();
 
        tb_req = 1;
        while (!tb_valid)
@@ -126,36 +115,54 @@ static void mpc85xx_take_timebase(void)
        local_irq_restore(flags);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static void smp_85xx_mach_cpu_die(void)
 {
        unsigned int cpu = smp_processor_id();
-       u32 tmp;
 
        local_irq_disable();
+       hard_irq_disable();
+       /* mask all irqs to prevent cpu wakeup */
+       qoriq_pm_ops->irq_mask(cpu);
+
        idle_task_exit();
-       generic_set_cpu_dead(cpu);
-       mb();
 
        mtspr(SPRN_TCR, 0);
+       mtspr(SPRN_TSR, mfspr(SPRN_TSR));
 
-       __flush_disable_L1();
-       tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
-       mtspr(SPRN_HID0, tmp);
-       isync();
+       generic_set_cpu_dead(cpu);
 
-       /* Enter NAP mode. */
-       tmp = mfmsr();
-       tmp |= MSR_WE;
-       mb();
-       mtmsr(tmp);
-       isync();
+       cur_cpu_spec->cpu_down_flush();
+
+       qoriq_pm_ops->cpu_die(cpu);
 
        while (1)
                ;
 }
+
+static void qoriq_cpu_kill(unsigned int cpu)
+{
+       int i;
+
+       for (i = 0; i < 500; i++) {
+               if (is_cpu_dead(cpu)) {
+#ifdef CONFIG_PPC64
+                       paca[cpu].cpu_start = 0;
+#endif
+                       return;
+               }
+               msleep(20);
+       }
+       pr_err("CPU%d didn't die...\n", cpu);
+}
 #endif
 
+/*
+ * To keep it compatible with old boot program which uses
+ * cache-inhibit spin table, we need to flush the cache
+ * before accessing spin table to invalidate any staled data.
+ * We also need to flush the cache after writing to spin
+ * table to push data out.
+ */
 static inline void flush_spin_table(void *spin_table)
 {
        flush_dcache_range((ulong)spin_table,
@@ -173,78 +180,28 @@ static inline u32 read_spin_table_addr_l(void *spin_table)
 static void wake_hw_thread(void *info)
 {
        void fsl_secondary_thread_init(void);
-       unsigned long imsr, inia;
-       int nr = *(const int *)info;
+       unsigned long inia;
+       int cpu = *(const int *)info;
 
-       imsr = MSR_KERNEL;
        inia = *(unsigned long *)fsl_secondary_thread_init;
-
-       if (cpu_thread_in_core(nr) == 0) {
-               /* For when we boot on a secondary thread with kdump */
-               mttmr(TMRN_IMSR0, imsr);
-               mttmr(TMRN_INIA0, inia);
-               mtspr(SPRN_TENS, TEN_THREAD(0));
-       } else {
-               mttmr(TMRN_IMSR1, imsr);
-               mttmr(TMRN_INIA1, inia);
-               mtspr(SPRN_TENS, TEN_THREAD(1));
-       }
-
-       smp_generic_kick_cpu(nr);
+       book3e_start_thread(cpu_thread_in_core(cpu), inia);
 }
 #endif
 
-static int smp_85xx_kick_cpu(int nr)
+static int smp_85xx_start_cpu(int cpu)
 {
-       unsigned long flags;
-       const u64 *cpu_rel_addr;
-       __iomem struct epapr_spin_table *spin_table;
+       int ret = 0;
        struct device_node *np;
-       int hw_cpu = get_hard_smp_processor_id(nr);
+       const u64 *cpu_rel_addr;
+       unsigned long flags;
        int ioremappable;
-       int ret = 0;
-
-       WARN_ON(nr < 0 || nr >= NR_CPUS);
-       WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
-
-       pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
-
-#ifdef CONFIG_PPC64
-       /* Threads don't use the spin table */
-       if (cpu_thread_in_core(nr) != 0) {
-               int primary = cpu_first_thread_sibling(nr);
-
-               if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
-                       return -ENOENT;
-
-               if (cpu_thread_in_core(nr) != 1) {
-                       pr_err("%s: cpu %d: invalid hw thread %d\n",
-                              __func__, nr, cpu_thread_in_core(nr));
-                       return -ENOENT;
-               }
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       struct epapr_spin_table __iomem *spin_table;
 
-               if (!cpu_online(primary)) {
-                       pr_err("%s: cpu %d: primary %d not online\n",
-                              __func__, nr, primary);
-                       return -ENOENT;
-               }
-
-               smp_call_function_single(primary, wake_hw_thread, &nr, 0);
-               return 0;
-       } else if (cpu_thread_in_core(boot_cpuid) != 0 &&
-                  cpu_first_thread_sibling(boot_cpuid) == nr) {
-               if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
-                       return -ENOENT;
-
-               smp_call_function_single(boot_cpuid, wake_hw_thread, &nr, 0);
-       }
-#endif
-
-       np = of_get_cpu_node(nr, NULL);
+       np = of_get_cpu_node(cpu, NULL);
        cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
-
-       if (cpu_rel_addr == NULL) {
-               printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
+       if (!cpu_rel_addr) {
+               pr_err("No cpu-release-addr for cpu %d\n", cpu);
                return -ENOENT;
        }
 
@@ -264,28 +221,18 @@ static int smp_85xx_kick_cpu(int nr)
                spin_table = phys_to_virt(*cpu_rel_addr);
 
        local_irq_save(flags);
-#ifdef CONFIG_PPC32
-#ifdef CONFIG_HOTPLUG_CPU
-       /* Corresponding to generic_set_cpu_dead() */
-       generic_set_cpu_up(nr);
+       hard_irq_disable();
 
-       if (system_state == SYSTEM_RUNNING) {
-               /*
-                * To keep it compatible with old boot program which uses
-                * cache-inhibit spin table, we need to flush the cache
-                * before accessing spin table to invalidate any staled data.
-                * We also need to flush the cache after writing to spin
-                * table to push data out.
-                */
-               flush_spin_table(spin_table);
-               out_be32(&spin_table->addr_l, 0);
-               flush_spin_table(spin_table);
+       if (qoriq_pm_ops)
+               qoriq_pm_ops->cpu_up_prepare(cpu);
 
+       /* if cpu is not spinning, reset it */
+       if (read_spin_table_addr_l(spin_table) != 1) {
                /*
                 * We don't set the BPTR register here since it already points
                 * to the boot page properly.
                 */
-               mpic_reset_core(nr);
+               mpic_reset_core(cpu);
 
                /*
                 * wait until core is ready...
@@ -295,40 +242,23 @@ static int smp_85xx_kick_cpu(int nr)
                if (!spin_event_timeout(
                                read_spin_table_addr_l(spin_table) == 1,
                                10000, 100)) {
-                       pr_err("%s: timeout waiting for core %d to reset\n",
-                                                       __func__, hw_cpu);
-                       ret = -ENOENT;
-                       goto out;
+                       pr_err("timeout waiting for cpu %d to reset\n",
+                               hw_cpu);
+                       ret = -EAGAIN;
+                       goto err;
                }
-
-               /*  clear the acknowledge status */
-               __secondary_hold_acknowledge = -1;
        }
-#endif
-       flush_spin_table(spin_table);
-       out_be32(&spin_table->pir, hw_cpu);
-       out_be32(&spin_table->addr_l, __pa(__early_start));
-       flush_spin_table(spin_table);
-
-       /* Wait a bit for the CPU to ack. */
-       if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
-                                       10000, 100)) {
-               pr_err("%s: timeout waiting for core %d to ack\n",
-                                               __func__, hw_cpu);
-               ret = -ENOENT;
-               goto out;
-       }
-out:
-#else
-       smp_generic_kick_cpu(nr);
 
        flush_spin_table(spin_table);
        out_be32(&spin_table->pir, hw_cpu);
+#ifdef CONFIG_PPC64
        out_be64((u64 *)(&spin_table->addr_h),
                __pa(ppc_function_entry(generic_secondary_smp_init)));
-       flush_spin_table(spin_table);
+#else
+       out_be32(&spin_table->addr_l, __pa(__early_start));
 #endif
-
+       flush_spin_table(spin_table);
+err:
        local_irq_restore(flags);
 
        if (ioremappable)
@@ -337,6 +267,81 @@ out:
        return ret;
 }
 
+static int smp_85xx_kick_cpu(int nr)
+{
+       int ret = 0;
+#ifdef CONFIG_PPC64
+       int primary = nr;
+#endif
+
+       WARN_ON(nr < 0 || nr >= num_possible_cpus());
+
+       pr_debug("kick CPU #%d\n", nr);
+
+#ifdef CONFIG_PPC64
+       if (threads_per_core == 2) {
+               if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
+                       return -ENOENT;
+
+               booting_thread_hwid = cpu_thread_in_core(nr);
+               primary = cpu_first_thread_sibling(nr);
+
+               if (qoriq_pm_ops)
+                       qoriq_pm_ops->cpu_up_prepare(nr);
+
+               /*
+                * If either thread in the core is online, use it to start
+                * the other.
+                */
+               if (cpu_online(primary)) {
+                       smp_call_function_single(primary,
+                                       wake_hw_thread, &nr, 1);
+                       goto done;
+               } else if (cpu_online(primary + 1)) {
+                       smp_call_function_single(primary + 1,
+                                       wake_hw_thread, &nr, 1);
+                       goto done;
+               }
+
+               /*
+                * If getting here, it means both threads in the core are
+                * offline. So start the primary thread, then it will start
+                * the thread specified in booting_thread_hwid, the one
+                * corresponding to nr.
+                */
+
+       } else if (threads_per_core == 1) {
+               /*
+                * If one core has only one thread, set booting_thread_hwid to
+                * an invalid value.
+                */
+               booting_thread_hwid = INVALID_THREAD_HWID;
+
+       } else if (threads_per_core > 2) {
+               pr_err("Do not support more than 2 threads per CPU.");
+               return -EINVAL;
+       }
+
+       ret = smp_85xx_start_cpu(primary);
+       if (ret)
+               return ret;
+
+done:
+       paca[nr].cpu_start = 1;
+       generic_set_cpu_up(nr);
+
+       return ret;
+#else
+       ret = smp_85xx_start_cpu(nr);
+       if (ret)
+               return ret;
+
+       generic_set_cpu_up(nr);
+
+       return ret;
+#endif
+}
+
 struct smp_ops_t smp_85xx_ops = {
        .kick_cpu = smp_85xx_kick_cpu,
        .cpu_bootable = smp_generic_cpu_bootable,
@@ -359,7 +364,7 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
        local_irq_disable();
 
        if (secondary) {
-               __flush_disable_L1();
+               cur_cpu_spec->cpu_down_flush();
                atomic_inc(&kexec_down_cpus);
                /* loop forever */
                while (1);
@@ -467,16 +472,6 @@ static void smp_85xx_setup_cpu(int cpu_nr)
        smp_85xx_basic_setup(cpu_nr);
 }
 
-static const struct of_device_id mpc85xx_smp_guts_ids[] = {
-       { .compatible = "fsl,mpc8572-guts", },
-       { .compatible = "fsl,p1020-guts", },
-       { .compatible = "fsl,p1021-guts", },
-       { .compatible = "fsl,p1022-guts", },
-       { .compatible = "fsl,p1023-guts", },
-       { .compatible = "fsl,p2020-guts", },
-       {},
-};
-
 void __init mpc85xx_smp_init(void)
 {
        struct device_node *np;
@@ -500,22 +495,21 @@ void __init mpc85xx_smp_init(void)
                smp_85xx_ops.probe = NULL;
        }
 
-       np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
-       if (np) {
-               guts = of_iomap(np, 0);
-               of_node_put(np);
-               if (!guts) {
-                       pr_err("%s: Could not map guts node address\n",
-                                                               __func__);
-                       return;
-               }
+#ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_FSL_CORENET_RCPM
+       fsl_rcpm_init();
+#endif
+
+#ifdef CONFIG_FSL_PMC
+       mpc85xx_setup_pmc();
+#endif
+       if (qoriq_pm_ops) {
                smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
                smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
-#ifdef CONFIG_HOTPLUG_CPU
                ppc_md.cpu_die = smp_85xx_mach_cpu_die;
-#endif
+               smp_85xx_ops.cpu_die = qoriq_cpu_kill;
        }
-
+#endif
        smp_ops = &smp_85xx_ops;
 
 #ifdef CONFIG_KEXEC
index e2b4493..0b20ae3 100644 (file)
@@ -5,6 +5,7 @@
 
 #ifdef CONFIG_SMP
 void __init mpc85xx_smp_init(void);
+int __init mpc85xx_setup_pmc(void);
 #else
 static inline void mpc85xx_smp_init(void)
 {
index ede815d..2d889ad 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the PowerPC 86xx linux kernel.
 #
 
-obj-y                          := pic.o
+obj-y                          := pic.o common.o
 obj-$(CONFIG_SMP)              += mpc86xx_smp.o
 obj-$(CONFIG_MPC8641_HPCN)     += mpc86xx_hpcn.o
 obj-$(CONFIG_SBC8641D)         += sbc8641d.o
diff --git a/arch/powerpc/platforms/86xx/common.c b/arch/powerpc/platforms/86xx/common.c
new file mode 100644 (file)
index 0000000..0f7b7fc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Routines common to most mpc86xx-based boards.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_platform.h>
+#include <asm/synch.h>
+
+#include "mpc86xx.h"
+
+static const struct of_device_id mpc86xx_common_ids[] __initconst = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       { .compatible = "simple-bus", },
+       { .name = "localbus", },
+       { .compatible = "gianfar", },
+       { .compatible = "fsl,mpc8641-pcie", },
+       {},
+};
+
+int __init mpc86xx_common_publish_devices(void)
+{
+       return of_platform_bus_probe(NULL, mpc86xx_common_ids, NULL);
+}
+
+long __init mpc86xx_time_init(void)
+{
+       unsigned int temp;
+
+       /* Set the time base to zero */
+       mtspr(SPRN_TBWL, 0);
+       mtspr(SPRN_TBWU, 0);
+
+       temp = mfspr(SPRN_HID0);
+       temp |= HID0_TBEN;
+       mtspr(SPRN_HID0, temp);
+       isync();
+
+       return 0;
+}
index bf17933..8e63b75 100644 (file)
@@ -197,37 +197,7 @@ static int __init gef_ppc9a_probe(void)
        return 0;
 }
 
-static long __init mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
-static const struct of_device_id of_bus_ids[] __initconst = {
-       { .compatible = "simple-bus", },
-       { .compatible = "gianfar", },
-       { .compatible = "fsl,mpc8641-pcie", },
-       {},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-       printk(KERN_DEBUG "Probe platform devices\n");
-       of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-       return 0;
-}
-machine_arch_initcall(gef_ppc9a, declare_of_platform_devices);
+machine_arch_initcall(gef_ppc9a, mpc86xx_common_publish_devices);
 
 define_machine(gef_ppc9a) {
        .name                   = "GE PPC9A",
index 8facf58..0e0be94 100644 (file)
@@ -184,37 +184,7 @@ static int __init gef_sbc310_probe(void)
        return 0;
 }
 
-static long __init mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
-static const struct of_device_id of_bus_ids[] __initconst = {
-       { .compatible = "simple-bus", },
-       { .compatible = "gianfar", },
-       { .compatible = "fsl,mpc8641-pcie", },
-       {},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-       printk(KERN_DEBUG "Probe platform devices\n");
-       of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-       return 0;
-}
-machine_arch_initcall(gef_sbc310, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc310, mpc86xx_common_publish_devices);
 
 define_machine(gef_sbc310) {
        .name                   = "GE SBC310",
index 8c9058d..e8292b4 100644 (file)
@@ -174,37 +174,7 @@ static int __init gef_sbc610_probe(void)
        return 0;
 }
 
-static long __init mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
-static const struct of_device_id of_bus_ids[] __initconst = {
-       { .compatible = "simple-bus", },
-       { .compatible = "gianfar", },
-       { .compatible = "fsl,mpc8641-pcie", },
-       {},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-       printk(KERN_DEBUG "Probe platform devices\n");
-       of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-       return 0;
-}
-machine_arch_initcall(gef_sbc610, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc610, mpc86xx_common_publish_devices);
 
 define_machine(gef_sbc610) {
        .name                   = "GE SBC610",
index 437a9c3..957473e 100644 (file)
@@ -88,12 +88,10 @@ static inline void mpc8610_suspend_init(void) { }
 static const struct of_device_id mpc8610_ids[] __initconst = {
        { .compatible = "fsl,mpc8610-immr", },
        { .compatible = "fsl,mpc8610-guts", },
-       { .compatible = "simple-bus", },
        /* So that the DMA channel nodes can be probed individually: */
        { .compatible = "fsl,eloplus-dma", },
        /* PCI controllers */
        { .compatible = "fsl,mpc8610-pci", },
-       { .compatible = "fsl,mpc8641-pcie", },
        {}
 };
 
@@ -105,6 +103,8 @@ static int __init mpc8610_declare_of_platform_devices(void)
        /* Enable wakeup on PIXIS' event IRQ. */
        mpc8610_suspend_init();
 
+       mpc86xx_common_publish_devices();
+
        /* Without this call, the SSI device driver won't get probed. */
        of_platform_bus_probe(NULL, mpc8610_ids, NULL);
 
@@ -327,22 +327,6 @@ static int __init mpc86xx_hpcd_probe(void)
        return 0;
 }
 
-static long __init mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
 define_machine(mpc86xx_hpcd) {
        .name                   = "MPC86xx HPCD",
        .probe                  = mpc86xx_hpcd_probe,
index 08efb57..53500db 100644 (file)
@@ -17,5 +17,7 @@
 
 extern void mpc86xx_smp_init(void);
 extern void mpc86xx_init_irq(void);
+extern long mpc86xx_time_init(void);
+extern int mpc86xx_common_publish_devices(void);
 
 #endif /* __MPC86XX_H__ */
index 07ccb1b..e508481 100644 (file)
@@ -110,33 +110,14 @@ static int __init mpc86xx_hpcn_probe(void)
        return 0;
 }
 
-static long __init
-mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
 static const struct of_device_id of_bus_ids[] __initconst = {
-       { .compatible = "simple-bus", },
        { .compatible = "fsl,srio", },
-       { .compatible = "gianfar", },
-       { .compatible = "fsl,mpc8641-pcie", },
        {},
 };
 
 static int __init declare_of_platform_devices(void)
 {
+       mpc86xx_common_publish_devices();
        of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
        return 0;
index 6810b71..2a9cf27 100644 (file)
@@ -75,37 +75,7 @@ static int __init sbc8641_probe(void)
        return 0;
 }
 
-static long __init
-mpc86xx_time_init(void)
-{
-       unsigned int temp;
-
-       /* Set the time base to zero */
-       mtspr(SPRN_TBWL, 0);
-       mtspr(SPRN_TBWU, 0);
-
-       temp = mfspr(SPRN_HID0);
-       temp |= HID0_TBEN;
-       mtspr(SPRN_HID0, temp);
-       asm volatile("isync");
-
-       return 0;
-}
-
-static const struct of_device_id of_bus_ids[] __initconst = {
-       { .compatible = "simple-bus", },
-       { .compatible = "gianfar", },
-       { .compatible = "fsl,mpc8641-pcie", },
-       {},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-       of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-       return 0;
-}
-machine_arch_initcall(sbc8641, declare_of_platform_devices);
+machine_arch_initcall(sbc8641, mpc86xx_common_publish_devices);
 
 define_machine(sbc8641) {
        .name                   = "SBC8641D",
index b290b63..5ad1202 100644 (file)
  *   Processor: 0x80000000 - 0x807fffff -> PCI I/O: 0x00000000 - 0x007fffff
  *   Processor: 0xc0000000 - 0xdfffffff -> PCI MEM: 0x00000000 - 0x1fffffff
  *   PCI MEM:   0x80000000 -> Processor System Memory: 0x00000000
- *   EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
  *
  * MAP B (CHRP Map)
  *   Processor: 0xfe000000 - 0xfebfffff -> PCI I/O: 0x00000000 - 0x00bfffff
  *   Processor: 0x80000000 - 0xbfffffff -> PCI MEM: 0x80000000 - 0xbfffffff
  *   PCI MEM:   0x00000000 -> Processor System Memory: 0x00000000
- *   EUMB mapped to: ioremap_base - 0x00100000 (ioremap_base - 1 MB)
  */
 
 /*
 #define MPC10X_EUMB_WP_OFFSET          0x000ff000 /* Data path diagnostic, watchpoint reg offset */
 #define MPC10X_EUMB_WP_SIZE            0x00001000 /* Data path diagnostic, watchpoint reg size */
 
-/*
- * Define some recommended places to put the EUMB regs.
- * For both maps, recommend putting the EUMB from 0xeff00000 to 0xefffffff.
- */
-extern unsigned long                   ioremap_base;
-#define        MPC10X_MAPA_EUMB_BASE           (ioremap_base - MPC10X_EUMB_SIZE)
-#define        MPC10X_MAPB_EUMB_BASE           MPC10X_MAPA_EUMB_BASE
-
 enum ppc_sys_devices {
        MPC10X_IIC1,
        MPC10X_DMA0,
index 52c6ce1..1eb7b45 100644 (file)
@@ -2,7 +2,7 @@ CFLAGS_bootx_init.o             += -fPIC
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
-CFLAGS_REMOVE_bootx_init.o = -pg -mno-sched-epilog
+CFLAGS_REMOVE_bootx_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
 endif
 
 obj-y                          += pic.o setup.o time.o feature.o pci.o \
index 6be1a4a..cc5347e 100644 (file)
@@ -23,7 +23,7 @@
  * when going to sleep, when doing a PMU based cpufreq transition,
  * or when "offlining" a CPU on SMP machines. This code is over
  * paranoid, but I've had enough issues with various CPU revs and
- * bugs that I decided it was worth beeing over cautious
+ * bugs that I decided it was worth being over cautious
  */
 
 _GLOBAL(flush_disable_caches)
index 4882bfd..1e02328 100644 (file)
@@ -198,7 +198,7 @@ static long ohare_htw_scc_enable(struct device_node *node, long param,
                        if (htw) {
                                /* Side effect: this will also power up the
                                 * modem, but it's too messy to figure out on which
-                                * ports this controls the tranceiver and on which
+                                * ports this controls the transceiver and on which
                                 * it controls the modem
                                 */
                                if (trans)
@@ -463,7 +463,7 @@ static long heathrow_sound_enable(struct device_node *node, long param,
        unsigned long           flags;
 
        /* B&W G3 and Yikes don't support that properly (the
-        * sound appear to never come back after beeing shut down).
+        * sound appear to never come back after being shut down).
         */
        if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
            pmac_mb.model_id == PMAC_TYPE_YIKES)
@@ -2770,7 +2770,7 @@ set_initial_features(void)
         * but I'm not too sure it was audited for side-effects on other
         * ohare based machines...
         * Since I still have difficulties figuring the right way to
-        * differenciate them all and since that hack was there for a long
+        * differentiate them all and since that hack was there for a long
         * time, I'll keep it around
         */
        if (macio_chips[0].type == macio_ohare) {
index f1516b5..cd9711e 100644 (file)
@@ -5,7 +5,7 @@ obj-y                   += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
 obj-y                  += opal-kmsg.o
 
 obj-$(CONFIG_SMP)      += smp.o subcore.o subcore-asm.o
-obj-$(CONFIG_PCI)      += pci.o pci-p5ioc2.o pci-ioda.o npu-dma.o
+obj-$(CONFIG_PCI)      += pci.o pci-ioda.o npu-dma.o
 obj-$(CONFIG_EEH)      += eeh-powernv.o
 obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
 obj-$(CONFIG_MEMORY_FAILURE)   += opal-memory-errors.o
index 87f47e5..950b3e5 100644 (file)
@@ -167,42 +167,26 @@ static int pnv_eeh_dbgfs_get(void *data, int offset, u64 *val)
        return 0;
 }
 
-static int pnv_eeh_outb_dbgfs_set(void *data, u64 val)
-{
-       return pnv_eeh_dbgfs_set(data, 0xD10, val);
-}
-
-static int pnv_eeh_outb_dbgfs_get(void *data, u64 *val)
-{
-       return pnv_eeh_dbgfs_get(data, 0xD10, val);
-}
-
-static int pnv_eeh_inbA_dbgfs_set(void *data, u64 val)
-{
-       return pnv_eeh_dbgfs_set(data, 0xD90, val);
-}
-
-static int pnv_eeh_inbA_dbgfs_get(void *data, u64 *val)
-{
-       return pnv_eeh_dbgfs_get(data, 0xD90, val);
-}
-
-static int pnv_eeh_inbB_dbgfs_set(void *data, u64 val)
-{
-       return pnv_eeh_dbgfs_set(data, 0xE10, val);
-}
+#define PNV_EEH_DBGFS_ENTRY(name, reg)                         \
+static int pnv_eeh_dbgfs_set_##name(void *data, u64 val)       \
+{                                                              \
+       return pnv_eeh_dbgfs_set(data, reg, val);               \
+}                                                              \
+                                                               \
+static int pnv_eeh_dbgfs_get_##name(void *data, u64 *val)      \
+{                                                              \
+       return pnv_eeh_dbgfs_get(data, reg, val);               \
+}                                                              \
+                                                               \
+DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_dbgfs_ops_##name,              \
+                       pnv_eeh_dbgfs_get_##name,               \
+                        pnv_eeh_dbgfs_set_##name,              \
+                       "0x%llx\n")
+
+PNV_EEH_DBGFS_ENTRY(outb, 0xD10);
+PNV_EEH_DBGFS_ENTRY(inbA, 0xD90);
+PNV_EEH_DBGFS_ENTRY(inbB, 0xE10);
 
-static int pnv_eeh_inbB_dbgfs_get(void *data, u64 *val)
-{
-       return pnv_eeh_dbgfs_get(data, 0xE10, val);
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_outb_dbgfs_ops, pnv_eeh_outb_dbgfs_get,
-                       pnv_eeh_outb_dbgfs_set, "0x%llx\n");
-DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbA_dbgfs_ops, pnv_eeh_inbA_dbgfs_get,
-                       pnv_eeh_inbA_dbgfs_set, "0x%llx\n");
-DEFINE_SIMPLE_ATTRIBUTE(pnv_eeh_inbB_dbgfs_ops, pnv_eeh_inbB_dbgfs_get,
-                       pnv_eeh_inbB_dbgfs_set, "0x%llx\n");
 #endif /* CONFIG_DEBUG_FS */
 
 /**
@@ -268,13 +252,13 @@ static int pnv_eeh_post_init(void)
 
                debugfs_create_file("err_injct_outbound", 0600,
                                    phb->dbgfs, hose,
-                                   &pnv_eeh_outb_dbgfs_ops);
+                                   &pnv_eeh_dbgfs_ops_outb);
                debugfs_create_file("err_injct_inboundA", 0600,
                                    phb->dbgfs, hose,
-                                   &pnv_eeh_inbA_dbgfs_ops);
+                                   &pnv_eeh_dbgfs_ops_inbA);
                debugfs_create_file("err_injct_inboundB", 0600,
                                    phb->dbgfs, hose,
-                                   &pnv_eeh_inbB_dbgfs_ops);
+                                   &pnv_eeh_dbgfs_ops_inbB);
 #endif /* CONFIG_DEBUG_FS */
        }
 
@@ -387,6 +371,7 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
        edev->mode      &= 0xFFFFFF00;
        edev->pcix_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_PCIX);
        edev->pcie_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_EXP);
+       edev->af_cap   = pnv_eeh_find_cap(pdn, PCI_CAP_ID_AF);
        edev->aer_cap  = pnv_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR);
        if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) {
                edev->mode |= EEH_DEV_BRIDGE;
@@ -895,6 +880,120 @@ void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
        }
 }
 
+static void pnv_eeh_wait_for_pending(struct pci_dn *pdn, const char *type,
+                                    int pos, u16 mask)
+{
+       struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+       int i, status = 0;
+
+       /* Wait for Transaction Pending bit to be cleared */
+       for (i = 0; i < 4; i++) {
+               eeh_ops->read_config(pdn, pos, 2, &status);
+               if (!(status & mask))
+                       return;
+
+               msleep((1 << i) * 100);
+       }
+
+       pr_warn("%s: Pending transaction while issuing %sFLR to %04x:%02x:%02x.%01x\n",
+               __func__, type,
+               edev->phb->global_number, pdn->busno,
+               PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
+}
+
+static int pnv_eeh_do_flr(struct pci_dn *pdn, int option)
+{
+       struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+       u32 reg = 0;
+
+       if (WARN_ON(!edev->pcie_cap))
+               return -ENOTTY;
+
+       eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP, 4, &reg);
+       if (!(reg & PCI_EXP_DEVCAP_FLR))
+               return -ENOTTY;
+
+       switch (option) {
+       case EEH_RESET_HOT:
+       case EEH_RESET_FUNDAMENTAL:
+               pnv_eeh_wait_for_pending(pdn, "",
+                                        edev->pcie_cap + PCI_EXP_DEVSTA,
+                                        PCI_EXP_DEVSTA_TRPND);
+               eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                    4, &reg);
+               reg |= PCI_EXP_DEVCTL_BCR_FLR;
+               eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                     4, reg);
+               msleep(EEH_PE_RST_HOLD_TIME);
+               break;
+       case EEH_RESET_DEACTIVATE:
+               eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                    4, &reg);
+               reg &= ~PCI_EXP_DEVCTL_BCR_FLR;
+               eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                     4, reg);
+               msleep(EEH_PE_RST_SETTLE_TIME);
+               break;
+       }
+
+       return 0;
+}
+
+static int pnv_eeh_do_af_flr(struct pci_dn *pdn, int option)
+{
+       struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+       u32 cap = 0;
+
+       if (WARN_ON(!edev->af_cap))
+               return -ENOTTY;
+
+       eeh_ops->read_config(pdn, edev->af_cap + PCI_AF_CAP, 1, &cap);
+       if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
+               return -ENOTTY;
+
+       switch (option) {
+       case EEH_RESET_HOT:
+       case EEH_RESET_FUNDAMENTAL:
+               /*
+                * Wait for Transaction Pending bit to clear. A word-aligned
+                * test is used, so we use the conrol offset rather than status
+                * and shift the test bit to match.
+                */
+               pnv_eeh_wait_for_pending(pdn, "AF",
+                                        edev->af_cap + PCI_AF_CTRL,
+                                        PCI_AF_STATUS_TP << 8);
+               eeh_ops->write_config(pdn, edev->af_cap + PCI_AF_CTRL,
+                                     1, PCI_AF_CTRL_FLR);
+               msleep(EEH_PE_RST_HOLD_TIME);
+               break;
+       case EEH_RESET_DEACTIVATE:
+               eeh_ops->write_config(pdn, edev->af_cap + PCI_AF_CTRL, 1, 0);
+               msleep(EEH_PE_RST_SETTLE_TIME);
+               break;
+       }
+
+       return 0;
+}
+
+static int pnv_eeh_reset_vf_pe(struct eeh_pe *pe, int option)
+{
+       struct eeh_dev *edev;
+       struct pci_dn *pdn;
+       int ret;
+
+       /* The VF PE should have only one child device */
+       edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list);
+       pdn = eeh_dev_to_pdn(edev);
+       if (!pdn)
+               return -ENXIO;
+
+       ret = pnv_eeh_do_flr(pdn, option);
+       if (!ret)
+               return ret;
+
+       return pnv_eeh_do_af_flr(pdn, option);
+}
+
 /**
  * pnv_eeh_reset - Reset the specified PE
  * @pe: EEH PE
@@ -956,7 +1055,9 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option)
                }
 
                bus = eeh_pe_bus_get(pe);
-               if (pci_is_root_bus(bus) ||
+               if (pe->type & EEH_PE_VF)
+                       ret = pnv_eeh_reset_vf_pe(pe, option);
+               else if (pci_is_root_bus(bus) ||
                        pci_is_root_bus(bus->parent))
                        ret = pnv_eeh_root_reset(hose, option);
                else
@@ -1095,6 +1196,14 @@ static inline bool pnv_eeh_cfg_blocked(struct pci_dn *pdn)
        if (!edev || !edev->pe)
                return false;
 
+       /*
+        * We will issue FLR or AF FLR to all VFs, which are contained
+        * in VF PE. It relies on the EEH PCI config accessors. So we
+        * can't block them during the window.
+        */
+       if (edev->physfn && (edev->pe->state & EEH_PE_RESET))
+               return false;
+
        if (edev->pe->state & EEH_PE_CFG_BLOCKED)
                return true;
 
@@ -1479,6 +1588,65 @@ static int pnv_eeh_next_error(struct eeh_pe **pe)
        return ret;
 }
 
+static int pnv_eeh_restore_vf_config(struct pci_dn *pdn)
+{
+       struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+       u32 devctl, cmd, cap2, aer_capctl;
+       int old_mps;
+
+       if (edev->pcie_cap) {
+               /* Restore MPS */
+               old_mps = (ffs(pdn->mps) - 8) << 5;
+               eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                    2, &devctl);
+               devctl &= ~PCI_EXP_DEVCTL_PAYLOAD;
+               devctl |= old_mps;
+               eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                     2, devctl);
+
+               /* Disable Completion Timeout */
+               eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP2,
+                                    4, &cap2);
+               if (cap2 & 0x10) {
+                       eeh_ops->read_config(pdn,
+                                            edev->pcie_cap + PCI_EXP_DEVCTL2,
+                                            4, &cap2);
+                       cap2 |= 0x10;
+                       eeh_ops->write_config(pdn,
+                                             edev->pcie_cap + PCI_EXP_DEVCTL2,
+                                             4, cap2);
+               }
+       }
+
+       /* Enable SERR and parity checking */
+       eeh_ops->read_config(pdn, PCI_COMMAND, 2, &cmd);
+       cmd |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+       eeh_ops->write_config(pdn, PCI_COMMAND, 2, cmd);
+
+       /* Enable report various errors */
+       if (edev->pcie_cap) {
+               eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                    2, &devctl);
+               devctl &= ~PCI_EXP_DEVCTL_CERE;
+               devctl |= (PCI_EXP_DEVCTL_NFERE |
+                          PCI_EXP_DEVCTL_FERE |
+                          PCI_EXP_DEVCTL_URRE);
+               eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
+                                     2, devctl);
+       }
+
+       /* Enable ECRC generation and check */
+       if (edev->pcie_cap && edev->aer_cap) {
+               eeh_ops->read_config(pdn, edev->aer_cap + PCI_ERR_CAP,
+                                    4, &aer_capctl);
+               aer_capctl |= (PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+               eeh_ops->write_config(pdn, edev->aer_cap + PCI_ERR_CAP,
+                                     4, aer_capctl);
+       }
+
+       return 0;
+}
+
 static int pnv_eeh_restore_config(struct pci_dn *pdn)
 {
        struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
@@ -1488,9 +1656,21 @@ static int pnv_eeh_restore_config(struct pci_dn *pdn)
        if (!edev)
                return -EEXIST;
 
-       phb = edev->phb->private_data;
-       ret = opal_pci_reinit(phb->opal_id,
-                             OPAL_REINIT_PCI_DEV, edev->config_addr);
+       /*
+        * We have to restore the PCI config space after reset since the
+        * firmware can't see SRIOV VFs.
+        *
+        * FIXME: The MPS, error routing rules, timeout setting are worthy
+        * to be exported by firmware in extendible way.
+        */
+       if (edev->physfn) {
+               ret = pnv_eeh_restore_vf_config(pdn);
+       } else {
+               phb = edev->phb->private_data;
+               ret = opal_pci_reinit(phb->opal_id,
+                                     OPAL_REINIT_PCI_DEV, edev->config_addr);
+       }
+
        if (ret) {
                pr_warn("%s: Can't reinit PCI dev 0x%x (%lld)\n",
                        __func__, edev->config_addr, ret);
@@ -1519,6 +1699,40 @@ static struct eeh_ops pnv_eeh_ops = {
        .restore_config         = pnv_eeh_restore_config
 };
 
+void pcibios_bus_add_device(struct pci_dev *pdev)
+{
+       struct pci_dn *pdn = pci_get_pdn(pdev);
+
+       if (!pdev->is_virtfn)
+               return;
+
+       /*
+        * The following operations will fail if VF's sysfs files
+        * aren't created or its resources aren't finalized.
+        */
+       eeh_add_device_early(pdn);
+       eeh_add_device_late(pdev);
+       eeh_sysfs_add_device(pdev);
+}
+
+#ifdef CONFIG_PCI_IOV
+static void pnv_pci_fixup_vf_mps(struct pci_dev *pdev)
+{
+       struct pci_dn *pdn = pci_get_pdn(pdev);
+       int parent_mps;
+
+       if (!pdev->is_virtfn)
+               return;
+
+       /* Synchronize MPS for VF and PF */
+       parent_mps = pcie_get_mps(pdev->physfn);
+       if ((128 << pdev->pcie_mpss) >= parent_mps)
+               pcie_set_mps(pdev, parent_mps);
+       pdn->mps = pcie_get_mps(pdev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pnv_pci_fixup_vf_mps);
+#endif /* CONFIG_PCI_IOV */
+
 /**
  * eeh_powernv_init - Register platform dependent EEH operations
  *
index 15bfbcd..fcc8b68 100644 (file)
@@ -35,9 +35,9 @@ int pnv_save_sprs_for_winkle(void)
        int rc;
 
        /*
-        * hid0, hid1, hid4, hid5, hmeer and lpcr values are symmetric accross
+        * hid0, hid1, hid4, hid5, hmeer and lpcr values are symmetric across
         * all cpus at boot. Get these reg values of current cpu and use the
-        * same accross all cpus.
+        * same across all cpus.
         */
        uint64_t lpcr_val = mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1;
        uint64_t hid0_val = mfspr(SPRN_HID0);
@@ -185,7 +185,7 @@ static ssize_t store_fastsleep_workaround_applyonce(struct device *dev,
         * fastsleep workaround needs to be left in 'applied' state on all
         * the cores. Do this by-
         * 1. Patching out the call to 'undo' workaround in fastsleep exit path
-        * 2. Sending ipi to all the cores which have atleast one online thread
+        * 2. Sending ipi to all the cores which have at least one online thread
         * 3. Patching out the call to 'apply' workaround in fastsleep entry
         * path
         * There is no need to send ipi to cores which have all threads
index e85aa90..7229acd 100644 (file)
@@ -278,7 +278,7 @@ static void pnv_npu_disable_bypass(struct pnv_ioda_pe *npe)
 
 /*
  * Enable/disable bypass mode on the NPU. The NPU only supports one
- * window per link, so bypass needs to be explicity enabled or
+ * window per link, so bypass needs to be explicitly enabled or
  * disabled. Unlike for a PHB3 bypass and non-bypass modes can't be
  * active at the same time.
  */
index 44ed78a..39d6ff9 100644 (file)
@@ -31,26 +31,25 @@ struct memcons {
        __be32 in_cons;
 };
 
-static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
-                               struct bin_attribute *bin_attr, char *to,
-                               loff_t pos, size_t count)
+static struct memcons *opal_memcons = NULL;
+
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
 {
-       struct memcons *mc = bin_attr->private;
        const char *conbuf;
        ssize_t ret;
        size_t first_read = 0;
        uint32_t out_pos, avail;
 
-       if (!mc)
+       if (!opal_memcons)
                return -ENODEV;
 
-       out_pos = be32_to_cpu(ACCESS_ONCE(mc->out_pos));
+       out_pos = be32_to_cpu(ACCESS_ONCE(opal_memcons->out_pos));
 
        /* Now we've read out_pos, put a barrier in before reading the new
         * data it points to in conbuf. */
        smp_rmb();
 
-       conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
+       conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));
 
        /* When the buffer has wrapped, read from the out_pos marker to the end
         * of the buffer, and then read the remaining data as in the un-wrapped
@@ -58,7 +57,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
        if (out_pos & MEMCONS_OUT_POS_WRAP) {
 
                out_pos &= MEMCONS_OUT_POS_MASK;
-               avail = be32_to_cpu(mc->obuf_size) - out_pos;
+               avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;
 
                ret = memory_read_from_buffer(to, count, &pos,
                                conbuf + out_pos, avail);
@@ -76,7 +75,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
        }
 
        /* Sanity check. The firmware should not do this to us. */
-       if (out_pos > be32_to_cpu(mc->obuf_size)) {
+       if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
                pr_err("OPAL: memory console corruption. Aborting read.\n");
                return -EINVAL;
        }
@@ -91,6 +90,13 @@ out:
        return ret;
 }
 
+static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
+                               struct bin_attribute *bin_attr, char *to,
+                               loff_t pos, size_t count)
+{
+       return opal_msglog_copy(to, pos, count);
+}
+
 static struct bin_attribute opal_msglog_attr = {
        .attr = {.name = "msglog", .mode = 0444},
        .read = opal_msglog_read
@@ -117,7 +123,15 @@ void __init opal_msglog_init(void)
                return;
        }
 
-       opal_msglog_attr.private = mc;
+       opal_memcons = mc;
+}
+
+void __init opal_msglog_sysfs_init(void)
+{
+       if (!opal_memcons) {
+               pr_warn("OPAL: message log initialisation failed, not creating sysfs entry\n");
+               return;
+       }
 
        if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
                pr_warn("OPAL: sysfs file creation failed\n");
index 4e0da5a..0256d07 100644 (file)
@@ -724,6 +724,9 @@ static int __init opal_init(void)
                of_node_put(leds);
        }
 
+       /* Initialise OPAL message log interface */
+       opal_msglog_init();
+
        /* Create "opal" kobject under /sys/firmware */
        rc = opal_sysfs_init();
        if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
                opal_platform_dump_init();
                /* Setup system parameters interface */
                opal_sys_param_init();
-               /* Setup message log interface. */
-               opal_msglog_init();
+               /* Setup message log sysfs interface. */
+               opal_msglog_sysfs_init();
        }
 
        /* Initialize platform devices: IPMI backend, PRD & flash interface */
index f90dc04..c5baaf3 100644 (file)
@@ -872,9 +872,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
                if (!res->flags || !res->parent)
                        continue;
 
-               if (!pnv_pci_is_mem_pref_64(res->flags))
-                       continue;
-
                /*
                 * The actual IOV BAR range is determined by the start address
                 * and the actual size for num_vfs VFs BAR.  This check is to
@@ -903,9 +900,6 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
                if (!res->flags || !res->parent)
                        continue;
 
-               if (!pnv_pci_is_mem_pref_64(res->flags))
-                       continue;
-
                size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
                res2 = *res;
                res->start += size * offset;
@@ -1196,29 +1190,36 @@ static void pnv_pci_ioda_setup_PEs(void)
 }
 
 #ifdef CONFIG_PCI_IOV
-static int pnv_pci_vf_release_m64(struct pci_dev *pdev)
+static int pnv_pci_vf_release_m64(struct pci_dev *pdev, u16 num_vfs)
 {
        struct pci_bus        *bus;
        struct pci_controller *hose;
        struct pnv_phb        *phb;
        struct pci_dn         *pdn;
        int                    i, j;
+       int                    m64_bars;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
        phb = hose->private_data;
        pdn = pci_get_pdn(pdev);
 
+       if (pdn->m64_single_mode)
+               m64_bars = num_vfs;
+       else
+               m64_bars = 1;
+
        for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
-               for (j = 0; j < M64_PER_IOV; j++) {
-                       if (pdn->m64_wins[i][j] == IODA_INVALID_M64)
+               for (j = 0; j < m64_bars; j++) {
+                       if (pdn->m64_map[j][i] == IODA_INVALID_M64)
                                continue;
                        opal_pci_phb_mmio_enable(phb->opal_id,
-                               OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 0);
-                       clear_bit(pdn->m64_wins[i][j], &phb->ioda.m64_bar_alloc);
-                       pdn->m64_wins[i][j] = IODA_INVALID_M64;
+                               OPAL_M64_WINDOW_TYPE, pdn->m64_map[j][i], 0);
+                       clear_bit(pdn->m64_map[j][i], &phb->ioda.m64_bar_alloc);
+                       pdn->m64_map[j][i] = IODA_INVALID_M64;
                }
 
+       kfree(pdn->m64_map);
        return 0;
 }
 
@@ -1235,8 +1236,7 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
        int                    total_vfs;
        resource_size_t        size, start;
        int                    pe_num;
-       int                    vf_groups;
-       int                    vf_per_group;
+       int                    m64_bars;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
@@ -1244,29 +1244,26 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
        pdn = pci_get_pdn(pdev);
        total_vfs = pci_sriov_get_totalvfs(pdev);
 
-       /* Initialize the m64_wins to IODA_INVALID_M64 */
-       for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
-               for (j = 0; j < M64_PER_IOV; j++)
-                       pdn->m64_wins[i][j] = IODA_INVALID_M64;
+       if (pdn->m64_single_mode)
+               m64_bars = num_vfs;
+       else
+               m64_bars = 1;
+
+       pdn->m64_map = kmalloc(sizeof(*pdn->m64_map) * m64_bars, GFP_KERNEL);
+       if (!pdn->m64_map)
+               return -ENOMEM;
+       /* Initialize the m64_map to IODA_INVALID_M64 */
+       for (i = 0; i < m64_bars ; i++)
+               for (j = 0; j < PCI_SRIOV_NUM_BARS; j++)
+                       pdn->m64_map[i][j] = IODA_INVALID_M64;
 
-       if (pdn->m64_per_iov == M64_PER_IOV) {
-               vf_groups = (num_vfs <= M64_PER_IOV) ? num_vfs: M64_PER_IOV;
-               vf_per_group = (num_vfs <= M64_PER_IOV)? 1:
-                       roundup_pow_of_two(num_vfs) / pdn->m64_per_iov;
-       } else {
-               vf_groups = 1;
-               vf_per_group = 1;
-       }
 
        for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
                res = &pdev->resource[i + PCI_IOV_RESOURCES];
                if (!res->flags || !res->parent)
                        continue;
 
-               if (!pnv_pci_is_mem_pref_64(res->flags))
-                       continue;
-
-               for (j = 0; j < vf_groups; j++) {
+               for (j = 0; j < m64_bars; j++) {
                        do {
                                win = find_next_zero_bit(&phb->ioda.m64_bar_alloc,
                                                phb->ioda.m64_bar_idx + 1, 0);
@@ -1275,12 +1272,11 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
                                        goto m64_failed;
                        } while (test_and_set_bit(win, &phb->ioda.m64_bar_alloc));
 
-                       pdn->m64_wins[i][j] = win;
+                       pdn->m64_map[j][i] = win;
 
-                       if (pdn->m64_per_iov == M64_PER_IOV) {
+                       if (pdn->m64_single_mode) {
                                size = pci_iov_resource_size(pdev,
                                                        PCI_IOV_RESOURCES + i);
-                               size = size * vf_per_group;
                                start = res->start + size * j;
                        } else {
                                size = resource_size(res);
@@ -1288,16 +1284,16 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
                        }
 
                        /* Map the M64 here */
-                       if (pdn->m64_per_iov == M64_PER_IOV) {
-                               pe_num = pdn->offset + j;
+                       if (pdn->m64_single_mode) {
+                               pe_num = pdn->pe_num_map[j];
                                rc = opal_pci_map_pe_mmio_window(phb->opal_id,
                                                pe_num, OPAL_M64_WINDOW_TYPE,
-                                               pdn->m64_wins[i][j], 0);
+                                               pdn->m64_map[j][i], 0);
                        }
 
                        rc = opal_pci_set_phb_mem_window(phb->opal_id,
                                                 OPAL_M64_WINDOW_TYPE,
-                                                pdn->m64_wins[i][j],
+                                                pdn->m64_map[j][i],
                                                 start,
                                                 0, /* unused */
                                                 size);
@@ -1309,12 +1305,12 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
                                goto m64_failed;
                        }
 
-                       if (pdn->m64_per_iov == M64_PER_IOV)
+                       if (pdn->m64_single_mode)
                                rc = opal_pci_phb_mmio_enable(phb->opal_id,
-                                    OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 2);
+                                    OPAL_M64_WINDOW_TYPE, pdn->m64_map[j][i], 2);
                        else
                                rc = opal_pci_phb_mmio_enable(phb->opal_id,
-                                    OPAL_M64_WINDOW_TYPE, pdn->m64_wins[i][j], 1);
+                                    OPAL_M64_WINDOW_TYPE, pdn->m64_map[j][i], 1);
 
                        if (rc != OPAL_SUCCESS) {
                                dev_err(&pdev->dev, "Failed to enable M64 window #%d: %llx\n",
@@ -1326,7 +1322,7 @@ static int pnv_pci_vf_assign_m64(struct pci_dev *pdev, u16 num_vfs)
        return 0;
 
 m64_failed:
-       pnv_pci_vf_release_m64(pdev);
+       pnv_pci_vf_release_m64(pdev, num_vfs);
        return -EBUSY;
 }
 
@@ -1353,15 +1349,13 @@ static void pnv_pci_ioda2_release_dma_pe(struct pci_dev *dev, struct pnv_ioda_pe
        iommu_free_table(tbl, of_node_full_name(dev->dev.of_node));
 }
 
-static void pnv_ioda_release_vf_PE(struct pci_dev *pdev, u16 num_vfs)
+static void pnv_ioda_release_vf_PE(struct pci_dev *pdev)
 {
        struct pci_bus        *bus;
        struct pci_controller *hose;
        struct pnv_phb        *phb;
        struct pnv_ioda_pe    *pe, *pe_n;
        struct pci_dn         *pdn;
-       u16                    vf_index;
-       int64_t                rc;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
@@ -1371,35 +1365,6 @@ static void pnv_ioda_release_vf_PE(struct pci_dev *pdev, u16 num_vfs)
        if (!pdev->is_physfn)
                return;
 
-       if (pdn->m64_per_iov == M64_PER_IOV && num_vfs > M64_PER_IOV) {
-               int   vf_group;
-               int   vf_per_group;
-               int   vf_index1;
-
-               vf_per_group = roundup_pow_of_two(num_vfs) / pdn->m64_per_iov;
-
-               for (vf_group = 0; vf_group < M64_PER_IOV; vf_group++)
-                       for (vf_index = vf_group * vf_per_group;
-                               vf_index < (vf_group + 1) * vf_per_group &&
-                               vf_index < num_vfs;
-                               vf_index++)
-                               for (vf_index1 = vf_group * vf_per_group;
-                                       vf_index1 < (vf_group + 1) * vf_per_group &&
-                                       vf_index1 < num_vfs;
-                                       vf_index1++){
-
-                                       rc = opal_pci_set_peltv(phb->opal_id,
-                                               pdn->offset + vf_index,
-                                               pdn->offset + vf_index1,
-                                               OPAL_REMOVE_PE_FROM_DOMAIN);
-
-                                       if (rc)
-                                           dev_warn(&pdev->dev, "%s: Failed to unlink same group PE#%d(%lld)\n",
-                                               __func__,
-                                               pdn->offset + vf_index1, rc);
-                               }
-       }
-
        list_for_each_entry_safe(pe, pe_n, &phb->ioda.pe_list, list) {
                if (pe->parent_dev != pdev)
                        continue;
@@ -1424,7 +1389,7 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev)
        struct pnv_phb        *phb;
        struct pci_dn         *pdn;
        struct pci_sriov      *iov;
-       u16 num_vfs;
+       u16                    num_vfs, i;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
@@ -1434,18 +1399,25 @@ void pnv_pci_sriov_disable(struct pci_dev *pdev)
        num_vfs = pdn->num_vfs;
 
        /* Release VF PEs */
-       pnv_ioda_release_vf_PE(pdev, num_vfs);
+       pnv_ioda_release_vf_PE(pdev);
 
        if (phb->type == PNV_PHB_IODA2) {
-               if (pdn->m64_per_iov == 1)
-                       pnv_pci_vf_resource_shift(pdev, -pdn->offset);
+               if (!pdn->m64_single_mode)
+                       pnv_pci_vf_resource_shift(pdev, -*pdn->pe_num_map);
 
                /* Release M64 windows */
-               pnv_pci_vf_release_m64(pdev);
+               pnv_pci_vf_release_m64(pdev, num_vfs);
 
                /* Release PE numbers */
-               bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs);
-               pdn->offset = 0;
+               if (pdn->m64_single_mode) {
+                       for (i = 0; i < num_vfs; i++) {
+                               if (pdn->pe_num_map[i] != IODA_INVALID_PE)
+                                       pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
+                       }
+               } else
+                       bitmap_clear(phb->ioda.pe_alloc, *pdn->pe_num_map, num_vfs);
+               /* Releasing pe_num_map */
+               kfree(pdn->pe_num_map);
        }
 }
 
@@ -1460,7 +1432,6 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)
        int                    pe_num;
        u16                    vf_index;
        struct pci_dn         *pdn;
-       int64_t                rc;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
@@ -1472,7 +1443,10 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)
 
        /* Reserve PE for each VF */
        for (vf_index = 0; vf_index < num_vfs; vf_index++) {
-               pe_num = pdn->offset + vf_index;
+               if (pdn->m64_single_mode)
+                       pe_num = pdn->pe_num_map[vf_index];
+               else
+                       pe_num = *pdn->pe_num_map + vf_index;
 
                pe = &phb->ioda.pe_array[pe_num];
                pe->pe_number = pe_num;
@@ -1505,37 +1479,6 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)
 
                pnv_pci_ioda2_setup_dma_pe(phb, pe);
        }
-
-       if (pdn->m64_per_iov == M64_PER_IOV && num_vfs > M64_PER_IOV) {
-               int   vf_group;
-               int   vf_per_group;
-               int   vf_index1;
-
-               vf_per_group = roundup_pow_of_two(num_vfs) / pdn->m64_per_iov;
-
-               for (vf_group = 0; vf_group < M64_PER_IOV; vf_group++) {
-                       for (vf_index = vf_group * vf_per_group;
-                            vf_index < (vf_group + 1) * vf_per_group &&
-                            vf_index < num_vfs;
-                            vf_index++) {
-                               for (vf_index1 = vf_group * vf_per_group;
-                                    vf_index1 < (vf_group + 1) * vf_per_group &&
-                                    vf_index1 < num_vfs;
-                                    vf_index1++) {
-
-                                       rc = opal_pci_set_peltv(phb->opal_id,
-                                               pdn->offset + vf_index,
-                                               pdn->offset + vf_index1,
-                                               OPAL_ADD_PE_TO_DOMAIN);
-
-                                       if (rc)
-                                           dev_warn(&pdev->dev, "%s: Failed to link same group PE#%d(%lld)\n",
-                                               __func__,
-                                               pdn->offset + vf_index1, rc);
-                               }
-                       }
-               }
-       }
 }
 
 int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
@@ -1545,6 +1488,7 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
        struct pnv_phb        *phb;
        struct pci_dn         *pdn;
        int                    ret;
+       u16                    i;
 
        bus = pdev->bus;
        hose = pci_bus_to_host(bus);
@@ -1552,20 +1496,59 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
        pdn = pci_get_pdn(pdev);
 
        if (phb->type == PNV_PHB_IODA2) {
+               if (!pdn->vfs_expanded) {
+                       dev_info(&pdev->dev, "don't support this SRIOV device"
+                               " with non 64bit-prefetchable IOV BAR\n");
+                       return -ENOSPC;
+               }
+
+               /*
+                * When M64 BARs functions in Single PE mode, the number of VFs
+                * could be enabled must be less than the number of M64 BARs.
+                */
+               if (pdn->m64_single_mode && num_vfs > phb->ioda.m64_bar_idx) {
+                       dev_info(&pdev->dev, "Not enough M64 BAR for VFs\n");
+                       return -EBUSY;
+               }
+
+               /* Allocating pe_num_map */
+               if (pdn->m64_single_mode)
+                       pdn->pe_num_map = kmalloc(sizeof(*pdn->pe_num_map) * num_vfs,
+                                       GFP_KERNEL);
+               else
+                       pdn->pe_num_map = kmalloc(sizeof(*pdn->pe_num_map), GFP_KERNEL);
+
+               if (!pdn->pe_num_map)
+                       return -ENOMEM;
+
+               if (pdn->m64_single_mode)
+                       for (i = 0; i < num_vfs; i++)
+                               pdn->pe_num_map[i] = IODA_INVALID_PE;
+
                /* Calculate available PE for required VFs */
-               mutex_lock(&phb->ioda.pe_alloc_mutex);
-               pdn->offset = bitmap_find_next_zero_area(
-                       phb->ioda.pe_alloc, phb->ioda.total_pe,
-                       0, num_vfs, 0);
-               if (pdn->offset >= phb->ioda.total_pe) {
+               if (pdn->m64_single_mode) {
+                       for (i = 0; i < num_vfs; i++) {
+                               pdn->pe_num_map[i] = pnv_ioda_alloc_pe(phb);
+                               if (pdn->pe_num_map[i] == IODA_INVALID_PE) {
+                                       ret = -EBUSY;
+                                       goto m64_failed;
+                               }
+                       }
+               } else {
+                       mutex_lock(&phb->ioda.pe_alloc_mutex);
+                       *pdn->pe_num_map = bitmap_find_next_zero_area(
+                               phb->ioda.pe_alloc, phb->ioda.total_pe,
+                               0, num_vfs, 0);
+                       if (*pdn->pe_num_map >= phb->ioda.total_pe) {
+                               mutex_unlock(&phb->ioda.pe_alloc_mutex);
+                               dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
+                               kfree(pdn->pe_num_map);
+                               return -EBUSY;
+                       }
+                       bitmap_set(phb->ioda.pe_alloc, *pdn->pe_num_map, num_vfs);
                        mutex_unlock(&phb->ioda.pe_alloc_mutex);
-                       dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
-                       pdn->offset = 0;
-                       return -EBUSY;
                }
-               bitmap_set(phb->ioda.pe_alloc, pdn->offset, num_vfs);
                pdn->num_vfs = num_vfs;
-               mutex_unlock(&phb->ioda.pe_alloc_mutex);
 
                /* Assign M64 window accordingly */
                ret = pnv_pci_vf_assign_m64(pdev, num_vfs);
@@ -1579,8 +1562,8 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
                 * the IOV BAR according to the PE# allocated to the VFs.
                 * Otherwise, the PE# for the VF will conflict with others.
                 */
-               if (pdn->m64_per_iov == 1) {
-                       ret = pnv_pci_vf_resource_shift(pdev, pdn->offset);
+               if (!pdn->m64_single_mode) {
+                       ret = pnv_pci_vf_resource_shift(pdev, *pdn->pe_num_map);
                        if (ret)
                                goto m64_failed;
                }
@@ -1592,8 +1575,16 @@ int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
        return 0;
 
 m64_failed:
-       bitmap_clear(phb->ioda.pe_alloc, pdn->offset, num_vfs);
-       pdn->offset = 0;
+       if (pdn->m64_single_mode) {
+               for (i = 0; i < num_vfs; i++) {
+                       if (pdn->pe_num_map[i] != IODA_INVALID_PE)
+                               pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
+               }
+       } else
+               bitmap_clear(phb->ioda.pe_alloc, *pdn->pe_num_map, num_vfs);
+
+       /* Releasing pe_num_map */
+       kfree(pdn->pe_num_map);
 
        return ret;
 }
@@ -1612,8 +1603,7 @@ int pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
        /* Allocate PCI data */
        add_dev_pci_data(pdev);
 
-       pnv_pci_sriov_enable(pdev, num_vfs);
-       return 0;
+       return pnv_pci_sriov_enable(pdev, num_vfs);
 }
 #endif /* CONFIG_PCI_IOV */
 
@@ -2851,45 +2841,58 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { }
 #ifdef CONFIG_PCI_IOV
 static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
 {
-       struct pci_controller *hose;
-       struct pnv_phb *phb;
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
+       const resource_size_t gate = phb->ioda.m64_segsize >> 2;
        struct resource *res;
        int i;
-       resource_size_t size;
+       resource_size_t size, total_vf_bar_sz;
        struct pci_dn *pdn;
        int mul, total_vfs;
 
        if (!pdev->is_physfn || pdev->is_added)
                return;
 
-       hose = pci_bus_to_host(pdev->bus);
-       phb = hose->private_data;
-
        pdn = pci_get_pdn(pdev);
        pdn->vfs_expanded = 0;
+       pdn->m64_single_mode = false;
 
        total_vfs = pci_sriov_get_totalvfs(pdev);
-       pdn->m64_per_iov = 1;
        mul = phb->ioda.total_pe;
+       total_vf_bar_sz = 0;
 
        for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
                res = &pdev->resource[i + PCI_IOV_RESOURCES];
                if (!res->flags || res->parent)
                        continue;
                if (!pnv_pci_is_mem_pref_64(res->flags)) {
-                       dev_warn(&pdev->dev, " non M64 VF BAR%d: %pR\n",
+                       dev_warn(&pdev->dev, "Don't support SR-IOV with"
+                                       " non M64 VF BAR%d: %pR. \n",
                                 i, res);
-                       continue;
+                       goto truncate_iov;
                }
 
-               size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);
+               total_vf_bar_sz += pci_iov_resource_size(pdev,
+                               i + PCI_IOV_RESOURCES);
 
-               /* bigger than 64M */
-               if (size > (1 << 26)) {
-                       dev_info(&pdev->dev, "PowerNV: VF BAR%d: %pR IOV size is bigger than 64M, roundup power2\n",
-                                i, res);
-                       pdn->m64_per_iov = M64_PER_IOV;
+               /*
+                * If bigger than quarter of M64 segment size, just round up
+                * power of two.
+                *
+                * Generally, one M64 BAR maps one IOV BAR. To avoid conflict
+                * with other devices, IOV BAR size is expanded to be
+                * (total_pe * VF_BAR_size).  When VF_BAR_size is half of M64
+                * segment size , the expanded size would equal to half of the
+                * whole M64 space size, which will exhaust the M64 Space and
+                * limit the system flexibility.  This is a design decision to
+                * set the boundary to quarter of the M64 segment size.
+                */
+               if (total_vf_bar_sz > gate) {
                        mul = roundup_pow_of_two(total_vfs);
+                       dev_info(&pdev->dev,
+                               "VF BAR Total IOV size %llx > %llx, roundup to %d VFs\n",
+                               total_vf_bar_sz, gate, mul);
+                       pdn->m64_single_mode = true;
                        break;
                }
        }
@@ -2898,20 +2901,31 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
                res = &pdev->resource[i + PCI_IOV_RESOURCES];
                if (!res->flags || res->parent)
                        continue;
-               if (!pnv_pci_is_mem_pref_64(res->flags)) {
-                       dev_warn(&pdev->dev, "Skipping expanding VF BAR%d: %pR\n",
-                                i, res);
-                       continue;
-               }
 
-               dev_dbg(&pdev->dev, " Fixing VF BAR%d: %pR to\n", i, res);
                size = pci_iov_resource_size(pdev, i + PCI_IOV_RESOURCES);
+               /*
+                * On PHB3, the minimum size alignment of M64 BAR in single
+                * mode is 32MB.
+                */
+               if (pdn->m64_single_mode && (size < SZ_32M))
+                       goto truncate_iov;
+               dev_dbg(&pdev->dev, " Fixing VF BAR%d: %pR to\n", i, res);
                res->end = res->start + size * mul - 1;
                dev_dbg(&pdev->dev, "                       %pR\n", res);
                dev_info(&pdev->dev, "VF BAR%d: %pR (expanded to %d VFs for PE alignment)",
                         i, res, mul);
        }
        pdn->vfs_expanded = mul;
+
+       return;
+
+truncate_iov:
+       /* To save MMIO space, IOV BAR is truncated. */
+       for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+               res = &pdev->resource[i + PCI_IOV_RESOURCES];
+               res->flags = 0;
+               res->end = res->start - 1;
+       }
 }
 #endif /* CONFIG_PCI_IOV */
 
@@ -3125,18 +3139,35 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
 static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev,
                                                      int resno)
 {
+       struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+       struct pnv_phb *phb = hose->private_data;
        struct pci_dn *pdn = pci_get_pdn(pdev);
-       resource_size_t align, iov_align;
-
-       iov_align = resource_size(&pdev->resource[resno]);
-       if (iov_align)
-               return iov_align;
+       resource_size_t align;
 
+       /*
+        * On PowerNV platform, IOV BAR is mapped by M64 BAR to enable the
+        * SR-IOV. While from hardware perspective, the range mapped by M64
+        * BAR should be size aligned.
+        *
+        * When IOV BAR is mapped with M64 BAR in Single PE mode, the extra
+        * powernv-specific hardware restriction is gone. But if just use the
+        * VF BAR size as the alignment, PF BAR / VF BAR may be allocated with
+        * in one segment of M64 #15, which introduces the PE conflict between
+        * PF and VF. Based on this, the minimum alignment of an IOV BAR is
+        * m64_segsize.
+        *
+        * This function returns the total IOV BAR size if M64 BAR is in
+        * Shared PE mode or just VF BAR size if not.
+        * If the M64 BAR is in Single PE mode, return the VF BAR size or
+        * M64 segment size if IOV BAR size is less.
+        */
        align = pci_iov_resource_size(pdev, resno);
-       if (pdn->vfs_expanded)
-               return pdn->vfs_expanded * align;
+       if (!pdn->vfs_expanded)
+               return align;
+       if (pdn->m64_single_mode)
+               return max(align, (resource_size_t)phb->ioda.m64_segsize);
 
-       return align;
+       return pdn->vfs_expanded * align;
 }
 #endif /* CONFIG_PCI_IOV */
 
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
deleted file mode 100644 (file)
index f2bdfea..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Support PCI/PCIe on PowerNV platforms
- *
- * Currently supports only P5IOC2
- *
- * Copyright 2011 Benjamin Herrenschmidt, IBM Corp.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/msi.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/msi_bitmap.h>
-#include <asm/ppc-pci.h>
-#include <asm/opal.h>
-#include <asm/iommu.h>
-#include <asm/tce.h>
-
-#include "powernv.h"
-#include "pci.h"
-
-/* For now, use a fixed amount of TCE memory for each p5ioc2
- * hub, 16M will do
- */
-#define P5IOC2_TCE_MEMORY      0x01000000
-
-#ifdef CONFIG_PCI_MSI
-static int pnv_pci_p5ioc2_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
-                                   unsigned int hwirq, unsigned int virq,
-                                   unsigned int is_64, struct msi_msg *msg)
-{
-       if (WARN_ON(!is_64))
-               return -ENXIO;
-       msg->data = hwirq - phb->msi_base;
-       msg->address_hi = 0x10000000;
-       msg->address_lo = 0;
-
-       return 0;
-}
-
-static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb)
-{
-       unsigned int count;
-       const __be32 *prop = of_get_property(phb->hose->dn,
-                                            "ibm,opal-msi-ranges", NULL);
-       if (!prop)
-               return;
-
-       /* Don't do MSI's on p5ioc2 PCI-X are they are not properly
-        * verified in HW
-        */
-       if (of_device_is_compatible(phb->hose->dn, "ibm,p5ioc2-pcix"))
-               return;
-       phb->msi_base = be32_to_cpup(prop);
-       count = be32_to_cpup(prop + 1);
-       if (msi_bitmap_alloc(&phb->msi_bmp, count, phb->hose->dn)) {
-               pr_err("PCI %d: Failed to allocate MSI bitmap !\n",
-                      phb->hose->global_number);
-               return;
-       }
-       phb->msi_setup = pnv_pci_p5ioc2_msi_setup;
-       phb->msi32_support = 0;
-       pr_info(" Allocated bitmap for %d MSIs (base IRQ 0x%x)\n",
-               count, phb->msi_base);
-}
-#else
-static void pnv_pci_init_p5ioc2_msis(struct pnv_phb *phb) { }
-#endif /* CONFIG_PCI_MSI */
-
-static struct iommu_table_ops pnv_p5ioc2_iommu_ops = {
-       .set = pnv_tce_build,
-#ifdef CONFIG_IOMMU_API
-       .exchange = pnv_tce_xchg,
-#endif
-       .clear = pnv_tce_free,
-       .get = pnv_tce_get,
-};
-
-static void pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
-                                        struct pci_dev *pdev)
-{
-       struct iommu_table *tbl = phb->p5ioc2.table_group.tables[0];
-
-       if (!tbl->it_map) {
-               tbl->it_ops = &pnv_p5ioc2_iommu_ops;
-               iommu_init_table(tbl, phb->hose->node);
-               iommu_register_group(&phb->p5ioc2.table_group,
-                               pci_domain_nr(phb->hose->bus), phb->opal_id);
-               INIT_LIST_HEAD_RCU(&tbl->it_group_list);
-               pnv_pci_link_table_and_group(phb->hose->node, 0,
-                               tbl, &phb->p5ioc2.table_group);
-       }
-
-       set_iommu_table_base(&pdev->dev, tbl);
-       iommu_add_device(&pdev->dev);
-}
-
-static const struct pci_controller_ops pnv_pci_p5ioc2_controller_ops = {
-       .dma_dev_setup = pnv_pci_dma_dev_setup,
-#ifdef CONFIG_PCI_MSI
-       .setup_msi_irqs = pnv_setup_msi_irqs,
-       .teardown_msi_irqs = pnv_teardown_msi_irqs,
-#endif
-};
-
-static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id,
-                                          void *tce_mem, u64 tce_size)
-{
-       struct pnv_phb *phb;
-       const __be64 *prop64;
-       u64 phb_id;
-       int64_t rc;
-       static int primary = 1;
-       struct iommu_table_group *table_group;
-       struct iommu_table *tbl;
-
-       pr_info(" Initializing p5ioc2 PHB %s\n", np->full_name);
-
-       prop64 = of_get_property(np, "ibm,opal-phbid", NULL);
-       if (!prop64) {
-               pr_err("  Missing \"ibm,opal-phbid\" property !\n");
-               return;
-       }
-       phb_id = be64_to_cpup(prop64);
-       pr_devel("  PHB-ID  : 0x%016llx\n", phb_id);
-       pr_devel("  TCE AT  : 0x%016lx\n", __pa(tce_mem));
-       pr_devel("  TCE SZ  : 0x%016llx\n", tce_size);
-
-       rc = opal_pci_set_phb_tce_memory(phb_id, __pa(tce_mem), tce_size);
-       if (rc != OPAL_SUCCESS) {
-               pr_err("  Failed to set TCE memory, OPAL error %lld\n", rc);
-               return;
-       }
-
-       phb = memblock_virt_alloc(sizeof(struct pnv_phb), 0);
-       phb->hose = pcibios_alloc_controller(np);
-       if (!phb->hose) {
-               pr_err("  Failed to allocate PCI controller\n");
-               return;
-       }
-
-       spin_lock_init(&phb->lock);
-       phb->hose->first_busno = 0;
-       phb->hose->last_busno = 0xff;
-       phb->hose->private_data = phb;
-       phb->hose->controller_ops = pnv_pci_p5ioc2_controller_ops;
-       phb->hub_id = hub_id;
-       phb->opal_id = phb_id;
-       phb->type = PNV_PHB_P5IOC2;
-       phb->model = PNV_PHB_MODEL_P5IOC2;
-
-       phb->regs = of_iomap(np, 0);
-
-       if (phb->regs == NULL)
-               pr_err("  Failed to map registers !\n");
-       else {
-               pr_devel("  P_BUID     = 0x%08x\n", in_be32(phb->regs + 0x100));
-               pr_devel("  P_IOSZ     = 0x%08x\n", in_be32(phb->regs + 0x1b0));
-               pr_devel("  P_IO_ST    = 0x%08x\n", in_be32(phb->regs + 0x1e0));
-               pr_devel("  P_MEM1_H   = 0x%08x\n", in_be32(phb->regs + 0x1a0));
-               pr_devel("  P_MEM1_L   = 0x%08x\n", in_be32(phb->regs + 0x190));
-               pr_devel("  P_MSZ1_L   = 0x%08x\n", in_be32(phb->regs + 0x1c0));
-               pr_devel("  P_MEM_ST   = 0x%08x\n", in_be32(phb->regs + 0x1d0));
-               pr_devel("  P_MEM2_H   = 0x%08x\n", in_be32(phb->regs + 0x2c0));
-               pr_devel("  P_MEM2_L   = 0x%08x\n", in_be32(phb->regs + 0x2b0));
-               pr_devel("  P_MSZ2_H   = 0x%08x\n", in_be32(phb->regs + 0x2d0));
-               pr_devel("  P_MSZ2_L   = 0x%08x\n", in_be32(phb->regs + 0x2e0));
-       }
-
-       /* Interpret the "ranges" property */
-       /* This also maps the I/O region and sets isa_io/mem_base */
-       pci_process_bridge_OF_ranges(phb->hose, np, primary);
-       primary = 0;
-
-       phb->hose->ops = &pnv_pci_ops;
-
-       /* Setup MSI support */
-       pnv_pci_init_p5ioc2_msis(phb);
-
-       /* Setup TCEs */
-       phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup;
-       pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table,
-                                 tce_mem, tce_size, 0,
-                                 IOMMU_PAGE_SHIFT_4K);
-       /*
-        * We do not allocate iommu_table as we do not support
-        * hotplug or SRIOV on P5IOC2 and therefore iommu_free_table()
-        * should not be called for phb->p5ioc2.table_group.tables[0] ever.
-        */
-       tbl = phb->p5ioc2.table_group.tables[0] = &phb->p5ioc2.iommu_table;
-       table_group = &phb->p5ioc2.table_group;
-       table_group->tce32_start = tbl->it_offset << tbl->it_page_shift;
-       table_group->tce32_size = tbl->it_size << tbl->it_page_shift;
-}
-
-void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
-{
-       struct device_node *phbn;
-       const __be64 *prop64;
-       u64 hub_id;
-       void *tce_mem;
-       uint64_t tce_per_phb;
-       int64_t rc;
-       int phb_count = 0;
-
-       pr_info("Probing p5ioc2 IO-Hub %s\n", np->full_name);
-
-       prop64 = of_get_property(np, "ibm,opal-hubid", NULL);
-       if (!prop64) {
-               pr_err(" Missing \"ibm,opal-hubid\" property !\n");
-               return;
-       }
-       hub_id = be64_to_cpup(prop64);
-       pr_info(" HUB-ID : 0x%016llx\n", hub_id);
-
-       /* Count child PHBs and calculate TCE space per PHB */
-       for_each_child_of_node(np, phbn) {
-               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
-                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex"))
-                       phb_count++;
-       }
-
-       if (phb_count <= 0) {
-               pr_info(" No PHBs for Hub %s\n", np->full_name);
-               return;
-       }
-
-       tce_per_phb = __rounddown_pow_of_two(P5IOC2_TCE_MEMORY / phb_count);
-       pr_info(" Allocating %lld MB of TCE memory per PHB\n",
-               tce_per_phb >> 20);
-
-       /* Currently allocate 16M of TCE memory for every Hub
-        *
-        * XXX TODO: Make it chip local if possible
-        */
-       tce_mem = memblock_virt_alloc(P5IOC2_TCE_MEMORY, P5IOC2_TCE_MEMORY);
-       pr_debug(" TCE    : 0x%016lx..0x%016lx\n",
-               __pa(tce_mem), __pa(tce_mem) + P5IOC2_TCE_MEMORY - 1);
-       rc = opal_pci_set_hub_tce_memory(hub_id, __pa(tce_mem),
-                                       P5IOC2_TCE_MEMORY);
-       if (rc != OPAL_SUCCESS) {
-               pr_err(" Failed to allocate TCE memory, OPAL error %lld\n", rc);
-               return;
-       }
-
-       /* Initialize PHBs */
-       for_each_child_of_node(np, phbn) {
-               if (of_device_is_compatible(phbn, "ibm,p5ioc2-pcix") ||
-                   of_device_is_compatible(phbn, "ibm,p5ioc2-pciex")) {
-                       pnv_pci_init_p5ioc2_phb(phbn, hub_id,
-                                       tce_mem, tce_per_phb);
-                       tce_mem += tce_per_phb;
-               }
-       }
-}
index b1ef84a..73c8dc2 100644 (file)
@@ -380,10 +380,7 @@ static void pnv_pci_config_check_eeh(struct pci_dn *pdn)
         */
        pe_no = pdn->pe_number;
        if (pe_no == IODA_INVALID_PE) {
-               if (phb->type == PNV_PHB_P5IOC2)
-                       pe_no = 0;
-               else
-                       pe_no = phb->ioda.reserved_pe;
+               pe_no = phb->ioda.reserved_pe;
        }
 
        /*
@@ -805,7 +802,6 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM, 0x3b9, pnv_p7ioc_rc_quirk);
 void __init pnv_pci_init(void)
 {
        struct device_node *np;
-       bool found_ioda = false;
 
        pci_add_flags(PCI_CAN_SKIP_ISA_ALIGN);
 
@@ -813,20 +809,11 @@ void __init pnv_pci_init(void)
        if (!firmware_has_feature(FW_FEATURE_OPAL))
                return;
 
-       /* Look for IODA IO-Hubs. We don't support mixing IODA
-        * and p5ioc2 due to the need to change some global
-        * probing flags
-        */
+       /* Look for IODA IO-Hubs. */
        for_each_compatible_node(np, NULL, "ibm,ioda-hub") {
                pnv_pci_init_ioda_hub(np);
-               found_ioda = true;
        }
 
-       /* Look for p5ioc2 IO-Hubs */
-       if (!found_ioda)
-               for_each_compatible_node(np, NULL, "ibm,p5ioc2")
-                       pnv_pci_init_p5ioc2_hub(np);
-
        /* Look for ioda2 built-in PHB3's */
        for_each_compatible_node(np, NULL, "ibm,ioda2-phb")
                pnv_pci_init_ioda2_phb(np);
index 00691a9..3f814f3 100644 (file)
@@ -4,16 +4,14 @@
 struct pci_dn;
 
 enum pnv_phb_type {
-       PNV_PHB_P5IOC2  = 0,
-       PNV_PHB_IODA1   = 1,
-       PNV_PHB_IODA2   = 2,
-       PNV_PHB_NPU     = 3,
+       PNV_PHB_IODA1   = 0,
+       PNV_PHB_IODA2   = 1,
+       PNV_PHB_NPU     = 2,
 };
 
 /* Precise PHB model for error management */
 enum pnv_phb_model {
        PNV_PHB_MODEL_UNKNOWN,
-       PNV_PHB_MODEL_P5IOC2,
        PNV_PHB_MODEL_P7IOC,
        PNV_PHB_MODEL_PHB3,
        PNV_PHB_MODEL_NPU,
@@ -121,81 +119,74 @@ struct pnv_phb {
        void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
        int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt);
 
-       union {
-               struct {
-                       struct iommu_table iommu_table;
-                       struct iommu_table_group table_group;
-               } p5ioc2;
-
-               struct {
-                       /* Global bridge info */
-                       unsigned int            total_pe;
-                       unsigned int            reserved_pe;
-
-                       /* 32-bit MMIO window */
-                       unsigned int            m32_size;
-                       unsigned int            m32_segsize;
-                       unsigned int            m32_pci_base;
-
-                       /* 64-bit MMIO window */
-                       unsigned int            m64_bar_idx;
-                       unsigned long           m64_size;
-                       unsigned long           m64_segsize;
-                       unsigned long           m64_base;
-                       unsigned long           m64_bar_alloc;
-
-                       /* IO ports */
-                       unsigned int            io_size;
-                       unsigned int            io_segsize;
-                       unsigned int            io_pci_base;
-
-                       /* PE allocation bitmap */
-                       unsigned long           *pe_alloc;
-                       /* PE allocation mutex */
-                       struct mutex            pe_alloc_mutex;
-
-                       /* M32 & IO segment maps */
-                       unsigned int            *m32_segmap;
-                       unsigned int            *io_segmap;
-                       struct pnv_ioda_pe      *pe_array;
-
-                       /* IRQ chip */
-                       int                     irq_chip_init;
-                       struct irq_chip         irq_chip;
-
-                       /* Sorted list of used PE's based
-                        * on the sequence of creation
-                        */
-                       struct list_head        pe_list;
-                       struct mutex            pe_list_mutex;
-
-                       /* Reverse map of PEs, will have to extend if
-                        * we are to support more than 256 PEs, indexed
-                        * bus { bus, devfn }
-                        */
-                       unsigned char           pe_rmap[0x10000];
-
-                       /* 32-bit TCE tables allocation */
-                       unsigned long           tce32_count;
-
-                       /* Total "weight" for the sake of DMA resources
-                        * allocation
-                        */
-                       unsigned int            dma_weight;
-                       unsigned int            dma_pe_count;
-
-                       /* Sorted list of used PE's, sorted at
-                        * boot for resource allocation purposes
-                        */
-                       struct list_head        pe_dma_list;
-
-                       /* TCE cache invalidate registers (physical and
-                        * remapped)
-                        */
-                       phys_addr_t             tce_inval_reg_phys;
-                       __be64 __iomem          *tce_inval_reg;
-               } ioda;
-       };
+       struct {
+               /* Global bridge info */
+               unsigned int            total_pe;
+               unsigned int            reserved_pe;
+
+               /* 32-bit MMIO window */
+               unsigned int            m32_size;
+               unsigned int            m32_segsize;
+               unsigned int            m32_pci_base;
+
+               /* 64-bit MMIO window */
+               unsigned int            m64_bar_idx;
+               unsigned long           m64_size;
+               unsigned long           m64_segsize;
+               unsigned long           m64_base;
+               unsigned long           m64_bar_alloc;
+
+               /* IO ports */
+               unsigned int            io_size;
+               unsigned int            io_segsize;
+               unsigned int            io_pci_base;
+
+               /* PE allocation bitmap */
+               unsigned long           *pe_alloc;
+               /* PE allocation mutex */
+               struct mutex            pe_alloc_mutex;
+
+               /* M32 & IO segment maps */
+               unsigned int            *m32_segmap;
+               unsigned int            *io_segmap;
+               struct pnv_ioda_pe      *pe_array;
+
+               /* IRQ chip */
+               int                     irq_chip_init;
+               struct irq_chip         irq_chip;
+
+               /* Sorted list of used PE's based
+                * on the sequence of creation
+                */
+               struct list_head        pe_list;
+               struct mutex            pe_list_mutex;
+
+               /* Reverse map of PEs, will have to extend if
+                * we are to support more than 256 PEs, indexed
+                * bus { bus, devfn }
+                */
+               unsigned char           pe_rmap[0x10000];
+
+               /* 32-bit TCE tables allocation */
+               unsigned long           tce32_count;
+
+               /* Total "weight" for the sake of DMA resources
+                * allocation
+                */
+               unsigned int            dma_weight;
+               unsigned int            dma_pe_count;
+
+               /* Sorted list of used PE's, sorted at
+                * boot for resource allocation purposes
+                */
+               struct list_head        pe_dma_list;
+
+               /* TCE cache invalidate registers (physical and
+                * remapped)
+                */
+               phys_addr_t             tce_inval_reg_phys;
+               __be64 __iomem          *tce_inval_reg;
+       } ioda;
 
        /* PHB and hub status structure */
        union {
@@ -232,7 +223,6 @@ extern void pnv_pci_unlink_table_and_group(struct iommu_table *tbl,
 extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
                                      void *tce_mem, u64 tce_size,
                                      u64 dma_offset, unsigned page_shift);
-extern void pnv_pci_init_p5ioc2_hub(struct device_node *np);
 extern void pnv_pci_init_ioda_hub(struct device_node *np);
 extern void pnv_pci_init_ioda2_phb(struct device_node *np);
 extern void pnv_pci_init_npu_phb(struct device_node *np);
index 503a73f..0babef1 100644 (file)
@@ -407,7 +407,7 @@ static DEVICE_ATTR(subcores_per_core, 0644,
 
 static int subcore_init(void)
 {
-       if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+       if (!cpu_has_feature(CPU_FTR_SUBCORE))
                return 0;
 
        /*
index 20b46a1..09bf24d 100644 (file)
  *
  */
 
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
 #include <asm/io.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
@@ -56,39 +62,8 @@ struct debug_block {
        u8 pkt[1520];
 } __packed;
 
-struct ethhdr {
-       u8 dest[6];
-       u8 src[6];
-       u16 type;
-} __packed;
-
-struct vlantag {
-       u16 vlan;
-       u16 subtype;
-} __packed;
-
-struct iphdr {
-       u8 ver_len;
-       u8 dscp_ecn;
-       u16 total_length;
-       u16 ident;
-       u16 frag_off_flags;
-       u8 ttl;
-       u8 proto;
-       u16 checksum;
-       u32 src;
-       u32 dest;
-} __packed;
-
-struct udphdr {
-       u16 src;
-       u16 dest;
-       u16 len;
-       u16 checksum;
-} __packed;
-
 static __iomem struct ethhdr *h_eth;
-static __iomem struct vlantag *h_vlan;
+static __iomem struct vlan_hdr *h_vlan;
 static __iomem struct iphdr *h_ip;
 static __iomem struct udphdr *h_udp;
 
@@ -173,8 +148,8 @@ static void gelic_debug_init(void)
 
        h_eth = (struct ethhdr *)dbg.pkt;
 
-       memset(&h_eth->dest, 0xff, 6);
-       memcpy(&h_eth->src, &mac, 6);
+       eth_broadcast_addr(h_eth->h_dest);
+       memcpy(&h_eth->h_source, &mac, ETH_ALEN);
 
        header_size = sizeof(struct ethhdr);
 
@@ -183,28 +158,29 @@ static void gelic_debug_init(void)
                                 GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
                                 &vlan_id, &v2);
        if (!result) {
-               h_eth->type = 0x8100;
+               h_eth->h_proto= ETH_P_8021Q;
 
-               header_size += sizeof(struct vlantag);
-               h_vlan = (struct vlantag *)(h_eth + 1);
-               h_vlan->vlan = vlan_id;
-               h_vlan->subtype = 0x0800;
+               header_size += sizeof(struct vlan_hdr);
+               h_vlan = (struct vlan_hdr *)(h_eth + 1);
+               h_vlan->h_vlan_TCI = vlan_id;
+               h_vlan->h_vlan_encapsulated_proto = ETH_P_IP;
                h_ip = (struct iphdr *)(h_vlan + 1);
        } else {
-               h_eth->type = 0x0800;
+               h_eth->h_proto= 0x0800;
                h_ip = (struct iphdr *)(h_eth + 1);
        }
 
        header_size += sizeof(struct iphdr);
-       h_ip->ver_len = 0x45;
+       h_ip->version = 4;
+       h_ip->ihl = 5;
        h_ip->ttl = 10;
-       h_ip->proto = 0x11;
-       h_ip->src = 0x00000000;
-       h_ip->dest = 0xffffffff;
+       h_ip->protocol = 0x11;
+       h_ip->saddr = 0x00000000;
+       h_ip->daddr = 0xffffffff;
 
        header_size += sizeof(struct udphdr);
        h_udp = (struct udphdr *)(h_ip + 1);
-       h_udp->src = GELIC_DEBUG_PORT;
+       h_udp->source = GELIC_DEBUG_PORT;
        h_udp->dest = GELIC_DEBUG_PORT;
 
        pmsgc = pmsg = (char *)(h_udp + 1);
@@ -225,16 +201,16 @@ static void gelic_sendbuf(int msgsize)
        int i;
 
        dbg.descr.buf_size = header_size + msgsize;
-       h_ip->total_length = msgsize + sizeof(struct udphdr) +
+       h_ip->tot_len = msgsize + sizeof(struct udphdr) +
                             sizeof(struct iphdr);
        h_udp->len = msgsize + sizeof(struct udphdr);
 
-       h_ip->checksum = 0;
+       h_ip->check = 0;
        sum = 0;
        p = (u16 *)h_ip;
        for (i = 0; i < 5; i++)
                sum += *p++;
-       h_ip->checksum = ~(sum + (sum >> 16));
+       h_ip->check = ~(sum + (sum >> 16));
 
        dbg.descr.dmac_cmd_status = GELIC_DESCR_DMA_CMD_NO_CHKSUM |
                                    GELIC_DESCR_TX_DMA_FRAME_TAIL;
index 638c406..b831638 100644 (file)
@@ -78,7 +78,7 @@ struct ps3_bmp {
 /**
  * struct ps3_private - a per cpu data structure
  * @bmp: ps3_bmp structure
- * @bmp_lock: Syncronize access to bmp.
+ * @bmp_lock: Synchronize access to bmp.
  * @ipi_debug_brk_mask: Mask for debug break IPIs
  * @ppe_id: HV logical_ppe_id
  * @thread_id: HV thread_id
index 849b29b..74da18d 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/plpar_wrappers.h>
 
 /**
- * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
+ * hvc_get_chars - retrieve characters from firmware for denoted vterm adapter
  * @vtermno: The vtermno or unit_address of the adapter from which to fetch the
  *     data.
  * @buf: The character buffer into which to put the character data fetched from
index 477290a..2415a0d 100644 (file)
@@ -505,8 +505,8 @@ static void pSeries_lpar_hugepage_invalidate(unsigned long vsid,
 }
 #endif
 
-static void pSeries_lpar_hpte_removebolted(unsigned long ea,
-                                          int psize, int ssize)
+static int pSeries_lpar_hpte_removebolted(unsigned long ea,
+                                         int psize, int ssize)
 {
        unsigned long vpn;
        unsigned long slot, vsid;
@@ -515,11 +515,14 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
        vpn = hpt_vpn(ea, vsid, ssize);
 
        slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
-       BUG_ON(slot == -1);
+       if (slot == -1)
+               return -ENOENT;
+
        /*
         * lpar doesn't use the passed actual page size
         */
        pSeries_lpar_hpte_invalidate(slot, vpn, psize, 0, ssize, 0);
+       return 0;
 }
 
 /*
index 36df46e..6e944fc 100644 (file)
@@ -515,7 +515,7 @@ static void __init pSeries_setup_arch(void)
 
        fwnmi_init();
 
-       /* By default, only probe PCI (can be overriden by rtas_pci) */
+       /* By default, only probe PCI (can be overridden by rtas_pci) */
        pci_add_flags(PCI_PROBE_ONLY);
 
        /* Find and initialize PCI host bridges */
diff --git a/arch/powerpc/scripts/gcc-check-mprofile-kernel.sh b/arch/powerpc/scripts/gcc-check-mprofile-kernel.sh
new file mode 100755 (executable)
index 0000000..c658d8c
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+set -e
+set -o pipefail
+
+# To debug, uncomment the following line
+# set -x
+
+# Test whether the compile option -mprofile-kernel exists and generates
+# profiling code (ie. a call to _mcount()).
+echo "int func() { return 0; }" | \
+    $* -S -x c -O2 -p -mprofile-kernel - -o - 2> /dev/null | \
+    grep -q "_mcount"
+
+# Test whether the notrace attribute correctly suppresses calls to _mcount().
+
+echo -e "#include <linux/compiler.h>\nnotrace int func() { return 0; }" | \
+    $* -S -x c -O2 -p -mprofile-kernel - -o - 2> /dev/null | \
+    grep -q "_mcount" && \
+    exit 1
+
+echo "OK"
+exit 0
index a19332a..52dc165 100644 (file)
@@ -40,3 +40,8 @@ config SCOM_DEBUGFS
 config GE_FPGA
        bool
        default n
+
+config FSL_CORENET_RCPM
+       bool
+       help
+         This option enables support for RCPM (Run Control/Power Management).
index bd6bd72..a254824 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_MMIO_NVRAM)      += mmio_nvram.o
 obj-$(CONFIG_FSL_SOC)          += fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)          += fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)          += fsl_pmc.o
+obj-$(CONFIG_FSL_CORENET_RCPM) += fsl_rcpm.o
 obj-$(CONFIG_FSL_LBC)          += fsl_lbc.o
 obj-$(CONFIG_FSL_GTM)          += fsl_gtm.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)      += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
index 5e6ff38..8ed6536 100644 (file)
@@ -228,7 +228,10 @@ void __init cpm_reset(void)
         * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
         */
        siu_conf = immr_map(im_siu_conf);
-       out_be32(&siu_conf->sc_sdcr, 1);
+       if ((mfspr(SPRN_IMMR) & 0xffff) == 0x0900) /* MPC885 */
+               out_be32(&siu_conf->sc_sdcr, 0x40);
+       else
+               out_be32(&siu_conf->sc_sdcr, 1);
        immr_unmap(siu_conf);
 
        cpm_muram_init();
index 47f7810..424b67f 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/mod_devicetable.h>
+#include <linux/syscore_ops.h>
 #include <asm/prom.h>
 #include <asm/fsl_lbc.h>
 
@@ -352,24 +353,42 @@ err:
 #ifdef CONFIG_SUSPEND
 
 /* save lbc registers */
-static int fsl_lbc_suspend(struct platform_device *pdev, pm_message_t state)
+static int fsl_lbc_syscore_suspend(void)
 {
-       struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
-       struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+       struct fsl_lbc_ctrl *ctrl;
+       struct fsl_lbc_regs __iomem *lbc;
+
+       ctrl = fsl_lbc_ctrl_dev;
+       if (!ctrl)
+               goto out;
+
+       lbc = ctrl->regs;
+       if (!lbc)
+               goto out;
 
        ctrl->saved_regs = kmalloc(sizeof(struct fsl_lbc_regs), GFP_KERNEL);
        if (!ctrl->saved_regs)
                return -ENOMEM;
 
        _memcpy_fromio(ctrl->saved_regs, lbc, sizeof(struct fsl_lbc_regs));
+
+out:
        return 0;
 }
 
 /* restore lbc registers */
-static int fsl_lbc_resume(struct platform_device *pdev)
+static void fsl_lbc_syscore_resume(void)
 {
-       struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&pdev->dev);
-       struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+       struct fsl_lbc_ctrl *ctrl;
+       struct fsl_lbc_regs __iomem *lbc;
+
+       ctrl = fsl_lbc_ctrl_dev;
+       if (!ctrl)
+               goto out;
+
+       lbc = ctrl->regs;
+       if (!lbc)
+               goto out;
 
        if (ctrl->saved_regs) {
                _memcpy_toio(lbc, ctrl->saved_regs,
@@ -377,7 +396,9 @@ static int fsl_lbc_resume(struct platform_device *pdev)
                kfree(ctrl->saved_regs);
                ctrl->saved_regs = NULL;
        }
-       return 0;
+
+out:
+       return;
 }
 #endif /* CONFIG_SUSPEND */
 
@@ -389,20 +410,26 @@ static const struct of_device_id fsl_lbc_match[] = {
        {},
 };
 
+#ifdef CONFIG_SUSPEND
+static struct syscore_ops lbc_syscore_pm_ops = {
+       .suspend = fsl_lbc_syscore_suspend,
+       .resume = fsl_lbc_syscore_resume,
+};
+#endif
+
 static struct platform_driver fsl_lbc_ctrl_driver = {
        .driver = {
                .name = "fsl-lbc",
                .of_match_table = fsl_lbc_match,
        },
        .probe = fsl_lbc_ctrl_probe,
-#ifdef CONFIG_SUSPEND
-       .suspend     = fsl_lbc_suspend,
-       .resume      = fsl_lbc_resume,
-#endif
 };
 
 static int __init fsl_lbc_init(void)
 {
+#ifdef CONFIG_SUSPEND
+       register_syscore_ops(&lbc_syscore_pm_ops);
+#endif
        return platform_driver_register(&fsl_lbc_ctrl_driver);
 }
 subsys_initcall(fsl_lbc_init);
index c69e88e..85729f4 100644 (file)
@@ -575,7 +575,7 @@ int fsl_add_bridge(struct platform_device *pdev, int is_primary)
        if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
                /* use fsl_indirect_read_config for PCIe */
                hose->ops = &fsl_indirect_pcie_ops;
-               /* For PCIE read HEADER_TYPE to identify controler mode */
+               /* For PCIE read HEADER_TYPE to identify controller mode */
                early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
                if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
                        goto no_bridge;
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
new file mode 100644 (file)
index 0000000..9259a94
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * RCPM(Run Control/Power Management) support
+ *
+ * Copyright 2012-2015 Freescale Semiconductor Inc.
+ *
+ * Author: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/export.h>
+
+#include <asm/io.h>
+#include <linux/fsl/guts.h>
+#include <asm/cputhreads.h>
+#include <asm/fsl_pm.h>
+#include <asm/smp.h>
+
+static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs;
+static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs;
+static unsigned int fsl_supported_pm_modes;
+
+static void rcpm_v1_irq_mask(int cpu)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       setbits32(&rcpm_v1_regs->cpmimr, mask);
+       setbits32(&rcpm_v1_regs->cpmcimr, mask);
+       setbits32(&rcpm_v1_regs->cpmmcmr, mask);
+       setbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_mask(int cpu)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       setbits32(&rcpm_v2_regs->tpmimr0, mask);
+       setbits32(&rcpm_v2_regs->tpmcimr0, mask);
+       setbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+       setbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v1_irq_unmask(int cpu)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       clrbits32(&rcpm_v1_regs->cpmimr, mask);
+       clrbits32(&rcpm_v1_regs->cpmcimr, mask);
+       clrbits32(&rcpm_v1_regs->cpmmcmr, mask);
+       clrbits32(&rcpm_v1_regs->cpmnmimr, mask);
+}
+
+static void rcpm_v2_irq_unmask(int cpu)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       clrbits32(&rcpm_v2_regs->tpmimr0, mask);
+       clrbits32(&rcpm_v2_regs->tpmcimr0, mask);
+       clrbits32(&rcpm_v2_regs->tpmmcmr0, mask);
+       clrbits32(&rcpm_v2_regs->tpmnmimr0, mask);
+}
+
+static void rcpm_v1_set_ip_power(bool enable, u32 mask)
+{
+       if (enable)
+               setbits32(&rcpm_v1_regs->ippdexpcr, mask);
+       else
+               clrbits32(&rcpm_v1_regs->ippdexpcr, mask);
+}
+
+static void rcpm_v2_set_ip_power(bool enable, u32 mask)
+{
+       if (enable)
+               setbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
+       else
+               clrbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
+}
+
+static void rcpm_v1_cpu_enter_state(int cpu, int state)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       switch (state) {
+       case E500_PM_PH10:
+               setbits32(&rcpm_v1_regs->cdozcr, mask);
+               break;
+       case E500_PM_PH15:
+               setbits32(&rcpm_v1_regs->cnapcr, mask);
+               break;
+       default:
+               pr_warn("Unknown cpu PM state (%d)\n", state);
+               break;
+       }
+}
+
+static void rcpm_v2_cpu_enter_state(int cpu, int state)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       u32 mask = 1 << cpu_core_index_of_thread(cpu);
+
+       switch (state) {
+       case E500_PM_PH10:
+               /* one bit corresponds to one thread for PH10 of 6500 */
+               setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu);
+               break;
+       case E500_PM_PH15:
+               setbits32(&rcpm_v2_regs->pcph15setr, mask);
+               break;
+       case E500_PM_PH20:
+               setbits32(&rcpm_v2_regs->pcph20setr, mask);
+               break;
+       case E500_PM_PH30:
+               setbits32(&rcpm_v2_regs->pcph30setr, mask);
+               break;
+       default:
+               pr_warn("Unknown cpu PM state (%d)\n", state);
+       }
+}
+
+static void rcpm_v1_cpu_die(int cpu)
+{
+       rcpm_v1_cpu_enter_state(cpu, E500_PM_PH15);
+}
+
+#ifdef CONFIG_PPC64
+static void qoriq_disable_thread(int cpu)
+{
+       int thread = cpu_thread_in_core(cpu);
+
+       book3e_stop_thread(thread);
+}
+#endif
+
+static void rcpm_v2_cpu_die(int cpu)
+{
+#ifdef CONFIG_PPC64
+       int primary;
+
+       if (threads_per_core == 2) {
+               primary = cpu_first_thread_sibling(cpu);
+               if (cpu_is_offline(primary) && cpu_is_offline(primary + 1)) {
+                       /* if both threads are offline, put the cpu in PH20 */
+                       rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
+               } else {
+                       /* if only one thread is offline, disable the thread */
+                       qoriq_disable_thread(cpu);
+               }
+       }
+#endif
+
+       if (threads_per_core == 1)
+               rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
+}
+
+static void rcpm_v1_cpu_exit_state(int cpu, int state)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       unsigned int mask = 1 << hw_cpu;
+
+       switch (state) {
+       case E500_PM_PH10:
+               clrbits32(&rcpm_v1_regs->cdozcr, mask);
+               break;
+       case E500_PM_PH15:
+               clrbits32(&rcpm_v1_regs->cnapcr, mask);
+               break;
+       default:
+               pr_warn("Unknown cpu PM state (%d)\n", state);
+               break;
+       }
+}
+
+static void rcpm_v1_cpu_up_prepare(int cpu)
+{
+       rcpm_v1_cpu_exit_state(cpu, E500_PM_PH15);
+       rcpm_v1_irq_unmask(cpu);
+}
+
+static void rcpm_v2_cpu_exit_state(int cpu, int state)
+{
+       int hw_cpu = get_hard_smp_processor_id(cpu);
+       u32 mask = 1 << cpu_core_index_of_thread(cpu);
+
+       switch (state) {
+       case E500_PM_PH10:
+               setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
+               break;
+       case E500_PM_PH15:
+               setbits32(&rcpm_v2_regs->pcph15clrr, mask);
+               break;
+       case E500_PM_PH20:
+               setbits32(&rcpm_v2_regs->pcph20clrr, mask);
+               break;
+       case E500_PM_PH30:
+               setbits32(&rcpm_v2_regs->pcph30clrr, mask);
+               break;
+       default:
+               pr_warn("Unknown cpu PM state (%d)\n", state);
+       }
+}
+
+static void rcpm_v2_cpu_up_prepare(int cpu)
+{
+       rcpm_v2_cpu_exit_state(cpu, E500_PM_PH20);
+       rcpm_v2_irq_unmask(cpu);
+}
+
+static int rcpm_v1_plat_enter_state(int state)
+{
+       u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
+       int ret = 0;
+       int result;
+
+       switch (state) {
+       case PLAT_PM_SLEEP:
+               setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);
+
+               /* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
+               result = spin_event_timeout(
+                 !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
+               if (!result) {
+                       pr_err("timeout waiting for SLP bit to be cleared\n");
+                       ret = -ETIMEDOUT;
+               }
+               break;
+       default:
+               pr_warn("Unknown platform PM state (%d)", state);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int rcpm_v2_plat_enter_state(int state)
+{
+       u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr;
+       int ret = 0;
+       int result;
+
+       switch (state) {
+       case PLAT_PM_LPM20:
+               /* clear previous LPM20 status */
+               setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST);
+               /* enter LPM20 status */
+               setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ);
+
+               /* At this point, the device is in LPM20 status. */
+
+               /* resume ... */
+               result = spin_event_timeout(
+                 !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10);
+               if (!result) {
+                       pr_err("timeout waiting for LPM20 bit to be cleared\n");
+                       ret = -ETIMEDOUT;
+               }
+               break;
+       default:
+               pr_warn("Unknown platform PM state (%d)\n", state);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int rcpm_v1_plat_enter_sleep(void)
+{
+       return rcpm_v1_plat_enter_state(PLAT_PM_SLEEP);
+}
+
+static int rcpm_v2_plat_enter_sleep(void)
+{
+       return rcpm_v2_plat_enter_state(PLAT_PM_LPM20);
+}
+
+static void rcpm_common_freeze_time_base(u32 *tben_reg, int freeze)
+{
+       static u32 mask;
+
+       if (freeze) {
+               mask = in_be32(tben_reg);
+               clrbits32(tben_reg, mask);
+       } else {
+               setbits32(tben_reg, mask);
+       }
+
+       /* read back to push the previous write */
+       in_be32(tben_reg);
+}
+
+static void rcpm_v1_freeze_time_base(bool freeze)
+{
+       rcpm_common_freeze_time_base(&rcpm_v1_regs->ctbenr, freeze);
+}
+
+static void rcpm_v2_freeze_time_base(bool freeze)
+{
+       rcpm_common_freeze_time_base(&rcpm_v2_regs->pctbenr, freeze);
+}
+
+static unsigned int rcpm_get_pm_modes(void)
+{
+       return fsl_supported_pm_modes;
+}
+
+static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
+       .irq_mask = rcpm_v1_irq_mask,
+       .irq_unmask = rcpm_v1_irq_unmask,
+       .cpu_enter_state = rcpm_v1_cpu_enter_state,
+       .cpu_exit_state = rcpm_v1_cpu_exit_state,
+       .cpu_up_prepare = rcpm_v1_cpu_up_prepare,
+       .cpu_die = rcpm_v1_cpu_die,
+       .plat_enter_sleep = rcpm_v1_plat_enter_sleep,
+       .set_ip_power = rcpm_v1_set_ip_power,
+       .freeze_time_base = rcpm_v1_freeze_time_base,
+       .get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
+       .irq_mask = rcpm_v2_irq_mask,
+       .irq_unmask = rcpm_v2_irq_unmask,
+       .cpu_enter_state = rcpm_v2_cpu_enter_state,
+       .cpu_exit_state = rcpm_v2_cpu_exit_state,
+       .cpu_up_prepare = rcpm_v2_cpu_up_prepare,
+       .cpu_die = rcpm_v2_cpu_die,
+       .plat_enter_sleep = rcpm_v2_plat_enter_sleep,
+       .set_ip_power = rcpm_v2_set_ip_power,
+       .freeze_time_base = rcpm_v2_freeze_time_base,
+       .get_pm_modes = rcpm_get_pm_modes,
+};
+
+static const struct of_device_id rcpm_matches[] = {
+       {
+               .compatible = "fsl,qoriq-rcpm-1.0",
+               .data = &qoriq_rcpm_v1_ops,
+       },
+       {
+               .compatible = "fsl,qoriq-rcpm-2.0",
+               .data = &qoriq_rcpm_v2_ops,
+       },
+       {
+               .compatible = "fsl,qoriq-rcpm-2.1",
+               .data = &qoriq_rcpm_v2_ops,
+       },
+       {},
+};
+
+int __init fsl_rcpm_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       void __iomem *base;
+
+       np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
+       if (!np)
+               return 0;
+
+       base = of_iomap(np, 0);
+       of_node_put(np);
+       if (!base) {
+               pr_err("of_iomap() error.\n");
+               return -ENOMEM;
+       }
+
+       rcpm_v1_regs = base;
+       rcpm_v2_regs = base;
+
+       /* support sleep by default */
+       fsl_supported_pm_modes = FSL_PM_SLEEP;
+
+       qoriq_pm_ops = match->data;
+
+       return 0;
+}
index b48197a..ffe0ee8 100644 (file)
@@ -570,7 +570,7 @@ int fsl_rio_port_write_init(struct fsl_rio_pw *pw)
        out_be32(&pw->pw_regs->pwsr,
                 (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
 
-       /* Configure port write contoller for snooping enable all reporting,
+       /* Configure port write controller for snooping enable all reporting,
           clear queue full */
        out_be32(&pw->pw_regs->pwmr,
                 RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ);
index 6f99ed3..aa2c186 100644 (file)
@@ -238,7 +238,7 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)
        /* init master interrupt controller */
        outb(0x11, 0x20); /* Start init sequence */
        outb(0x00, 0x21); /* Vector base */
-       outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+       outb(0x04, 0x21); /* edge triggered, Cascade (slave) on IRQ2 */
        outb(0x01, 0x21); /* Select 8086 mode */
 
        /* init slave interrupt controller */
index 2a0452e..afe3c7c 100644 (file)
@@ -2,7 +2,7 @@
  *  arch/powerpc/kernel/mpic.c
  *
  *  Driver for interrupt controllers following the OpenPIC standard, the
- *  common implementation beeing IBM's MPIC. This driver also can deal
+ *  common implementation being IBM's MPIC. This driver also can deal
  *  with various broken implementations of this HW.
  *
  *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
@@ -1657,7 +1657,7 @@ void __init mpic_init(struct mpic *mpic)
                }
        }
 
-       /* FSL mpic error interrupt intialization */
+       /* FSL mpic error interrupt initialization */
        if (mpic->flags & MPIC_FSL_HAS_EIMR)
                mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
 }
index 07a8508..942796f 100644 (file)
@@ -47,6 +47,9 @@
 #include <asm/debug.h>
 #include <asm/hw_breakpoint.h>
 
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
 #include <asm/paca.h>
@@ -119,6 +122,16 @@ static void dump(void);
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long, int);
 static void dump_log_buf(void);
+
+#ifdef CONFIG_PPC_POWERNV
+static void dump_opal_msglog(void);
+#else
+static inline void dump_opal_msglog(void)
+{
+       printf("Machine is not running OPAL firmware.\n");
+}
+#endif
+
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -150,6 +163,7 @@ static int  cpu_cmd(void);
 static void csum(void);
 static void bootcmds(void);
 static void proccall(void);
+static void show_tasks(void);
 void dump_segments(void);
 static void symbol_lookup(void);
 static void xmon_show_stack(unsigned long sp, unsigned long lr,
@@ -202,6 +216,10 @@ Commands:\n\
   df   dump float values\n\
   dd   dump double values\n\
   dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC_POWERNV
+  "\
+  do    dump the OPAL message log\n"
+#endif
 #ifdef CONFIG_PPC64
   "\
   dp[#]        dump paca for current cpu, or cpu #\n\
@@ -221,6 +239,7 @@ Commands:\n\
   mz   zero a block of memory\n\
   mi   show information about memory allocation\n\
   p    call a procedure\n\
+  P    list processes/tasks\n\
   r    print registers\n\
   s    single step\n"
 #ifdef CONFIG_SPU_BASE
@@ -233,7 +252,7 @@ Commands:\n\
 "  S   print special registers\n\
   t    print backtrace\n\
   x    exit monitor and recover\n\
-  X    exit monitor and dont recover\n"
+  X    exit monitor and don't recover\n"
 #if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_BOOK3E)
 "  u   dump segment table or SLB\n"
 #elif defined(CONFIG_PPC_STD_MMU_32)
@@ -950,6 +969,9 @@ cmds(struct pt_regs *excp)
                case 'p':
                        proccall();
                        break;
+               case 'P':
+                       show_tasks();
+                       break;
 #ifdef CONFIG_PPC_STD_MMU
                case 'u':
                        dump_segments();
@@ -2253,6 +2275,8 @@ dump(void)
                last_cmd = "di\n";
        } else if (c == 'l') {
                dump_log_buf();
+       } else if (c == 'o') {
+               dump_opal_msglog();
        } else if (c == 'r') {
                scanhex(&ndump);
                if (ndump == 0)
@@ -2395,6 +2419,45 @@ dump_log_buf(void)
        catch_memory_errors = 0;
 }
 
+#ifdef CONFIG_PPC_POWERNV
+static void dump_opal_msglog(void)
+{
+       unsigned char buf[128];
+       ssize_t res;
+       loff_t pos = 0;
+
+       if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+               printf("Machine is not running OPAL firmware.\n");
+               return;
+       }
+
+       if (setjmp(bus_error_jmp) != 0) {
+               printf("Error dumping OPAL msglog!\n");
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       xmon_start_pagination();
+       while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
+               if (res < 0) {
+                       printf("Error dumping OPAL msglog! Error: %zd\n", res);
+                       break;
+               }
+               buf[res] = '\0';
+               printf("%s", buf);
+               pos += res;
+       }
+       xmon_end_pagination();
+
+       sync();
+       /* wait a little while to see if we get a machine check */
+       __delay(200);
+       catch_memory_errors = 0;
+}
+#endif
+
 /*
  * Memory operations - move, set, print differences
  */
@@ -2508,6 +2571,61 @@ memzcan(void)
                printf("%.8x\n", a - mskip);
 }
 
+static void show_task(struct task_struct *tsk)
+{
+       char state;
+
+       /*
+        * Cloned from kdb_task_state_char(), which is not entirely
+        * appropriate for calling from xmon. This could be moved
+        * to a common, generic, routine used by both.
+        */
+       state = (tsk->state == 0) ? 'R' :
+               (tsk->state < 0) ? 'U' :
+               (tsk->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+               (tsk->state & TASK_STOPPED) ? 'T' :
+               (tsk->state & TASK_TRACED) ? 'C' :
+               (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
+               (tsk->exit_state & EXIT_DEAD) ? 'E' :
+               (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
+
+       printf("%p %016lx %6d %6d %c %2d %s\n", tsk,
+               tsk->thread.ksp,
+               tsk->pid, tsk->parent->pid,
+               state, task_thread_info(tsk)->cpu,
+               tsk->comm);
+}
+
+static void show_tasks(void)
+{
+       unsigned long tskv;
+       struct task_struct *tsk = NULL;
+
+       printf("     task_struct     ->thread.ksp    PID   PPID S  P CMD\n");
+
+       if (scanhex(&tskv))
+               tsk = (struct task_struct *)tskv;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               catch_memory_errors = 0;
+               printf("*** Error dumping task %p\n", tsk);
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       if (tsk)
+               show_task(tsk);
+       else
+               for_each_process(tsk)
+                       show_task(tsk);
+
+       sync();
+       __delay(200);
+       catch_memory_errors = 0;
+}
+
 static void proccall(void)
 {
        unsigned long args[8];
index 17a4f15..7ed20fc 100644 (file)
@@ -1,5 +1,6 @@
 config SUPERH
        def_bool y
+       select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select HAVE_PATA_PLATFORM
        select CLKDEV_LOOKUP
index 89963d1..5e52d53 100644 (file)
@@ -6,6 +6,21 @@ config SOLUTION_ENGINE
 config SH_ALPHA_BOARD
        bool
 
+config SH_DEVICE_TREE
+       bool "Board Described by Device Tree"
+       select OF
+       select OF_EARLY_FLATTREE
+       select CLKSRC_OF
+       select GENERIC_CALIBRATE_DELAY
+       help
+         Select Board Described by Device Tree to build a kernel that
+         does not hard-code any board-specific knowledge but instead uses
+         a device tree blob provided by the boot-loader. You must enable
+         drivers for any hardware you want to use separately. At this
+         time, only boards based on the open-hardware J-Core processors
+         have sufficient driver coverage to use this option; do not
+         select it if you are using original SuperH hardware.
+
 config SH_SOLUTION_ENGINE
        bool "SolutionEngine"
        select SOLUTION_ENGINE
index 975a0f6..cea3003 100644 (file)
@@ -15,3 +15,5 @@ obj-$(CONFIG_SH_TITAN)                += board-titan.o
 obj-$(CONFIG_SH_SH7757LCR)     += board-sh7757lcr.o
 obj-$(CONFIG_SH_APSH4A3A)      += board-apsh4a3a.o
 obj-$(CONFIG_SH_APSH4AD0A)     += board-apsh4ad0a.o
+
+obj-$(CONFIG_SH_DEVICE_TREE)   += of-generic.o
diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
new file mode 100644 (file)
index 0000000..bf3a166
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * SH generic board support, using device tree
+ *
+ * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/of_iommu.h>
+#include <linux/clocksource.h>
+#include <linux/irqchip.h>
+#include <linux/clk-provider.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+
+#ifdef CONFIG_SMP
+
+static void dummy_smp_setup(void)
+{
+}
+
+static void dummy_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+static void dummy_start_cpu(unsigned int cpu, unsigned long entry_point)
+{
+}
+
+static unsigned int dummy_smp_processor_id(void)
+{
+       return 0;
+}
+
+static void dummy_send_ipi(unsigned int cpu, unsigned int message)
+{
+}
+
+static struct plat_smp_ops dummy_smp_ops = {
+       .smp_setup              = dummy_smp_setup,
+       .prepare_cpus           = dummy_prepare_cpus,
+       .start_cpu              = dummy_start_cpu,
+       .smp_processor_id       = dummy_smp_processor_id,
+       .send_ipi               = dummy_send_ipi,
+       .cpu_die                = native_cpu_die,
+       .cpu_disable            = native_cpu_disable,
+       .play_dead              = native_play_dead,
+};
+
+extern const struct of_cpu_method __cpu_method_of_table[];
+const struct of_cpu_method __cpu_method_of_table_sentinel
+       __section(__cpu_method_of_table_end);
+
+static void sh_of_smp_probe(void)
+{
+       struct device_node *np = 0;
+       const char *method = 0;
+       const struct of_cpu_method *m = __cpu_method_of_table;
+
+       pr_info("SH generic board support: scanning for cpus\n");
+
+       init_cpu_possible(cpumask_of(0));
+
+       while ((np = of_find_node_by_type(np, "cpu"))) {
+               const __be32 *cell = of_get_property(np, "reg", NULL);
+               u64 id = -1;
+               if (cell) id = of_read_number(cell, of_n_addr_cells(np));
+               if (id < NR_CPUS) {
+                       if (!method)
+                               of_property_read_string(np, "enable-method", &method);
+                       set_cpu_possible(id, true);
+                       set_cpu_present(id, true);
+                       __cpu_number_map[id] = id;
+                       __cpu_logical_map[id] = id;
+               }
+       }
+       if (!method) {
+               np = of_find_node_by_name(NULL, "cpus");
+               of_property_read_string(np, "enable-method", &method);
+       }
+
+       pr_info("CPU enable method: %s\n", method);
+       if (method)
+               for (; m->method; m++)
+                       if (!strcmp(m->method, method)) {
+                               register_smp_ops(m->ops);
+                               return;
+                       }
+
+       register_smp_ops(&dummy_smp_ops);
+}
+
+#else
+
+static void sh_of_smp_probe(void)
+{
+}
+
+#endif
+
+static void noop(void)
+{
+}
+
+static int noopi(void)
+{
+       return 0;
+}
+
+static void __init sh_of_mem_reserve(void)
+{
+       early_init_fdt_reserve_self();
+       early_init_fdt_scan_reserved_mem();
+}
+
+static void __init sh_of_time_init(void)
+{
+       pr_info("SH generic board support: scanning for clocksource devices\n");
+       clocksource_probe();
+}
+
+static void __init sh_of_setup(char **cmdline_p)
+{
+       unflatten_device_tree();
+
+       board_time_init = sh_of_time_init;
+
+       sh_mv.mv_name = of_flat_dt_get_machine_name();
+       if (!sh_mv.mv_name)
+               sh_mv.mv_name = "Unknown SH model";
+
+       sh_of_smp_probe();
+}
+
+static int sh_of_irq_demux(int irq)
+{
+       /* FIXME: eventually this should not be used at all;
+        * the interrupt controller should set_handle_irq(). */
+       return irq;
+}
+
+static void __init sh_of_init_irq(void)
+{
+       pr_info("SH generic board support: scanning for interrupt controllers\n");
+       irqchip_init();
+}
+
+static int __init sh_of_clk_init(void)
+{
+#ifdef CONFIG_COMMON_CLK
+       /* Disabled pending move to COMMON_CLK framework. */
+       pr_info("SH generic board support: scanning for clk providers\n");
+       of_clk_init(NULL);
+#endif
+       return 0;
+}
+
+static struct sh_machine_vector __initmv sh_of_generic_mv = {
+       .mv_setup       = sh_of_setup,
+       .mv_name        = "devicetree", /* replaced by DT root's model */
+       .mv_irq_demux   = sh_of_irq_demux,
+       .mv_init_irq    = sh_of_init_irq,
+       .mv_clk_init    = sh_of_clk_init,
+       .mv_mode_pins   = noopi,
+       .mv_mem_init    = noop,
+       .mv_mem_reserve = sh_of_mem_reserve,
+};
+
+struct sh_clk_ops;
+
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
+{
+}
+
+void __init plat_irq_setup(void)
+{
+}
+
+static int __init sh_of_device_init(void)
+{
+       pr_info("SH generic board support: populating platform devices\n");
+       if (of_have_populated_dt()) {
+               of_iommu_init();
+               of_platform_populate(NULL, of_default_bus_match_table,
+                                    NULL, NULL);
+       } else {
+               pr_crit("Device tree not populated\n");
+       }
+       return 0;
+}
+arch_initcall_sync(sh_of_device_init);
index 23bc849..6df826e 100644 (file)
@@ -48,7 +48,7 @@ ifeq ($(BITS),64)
        lib1funcs-dir   := $(addsuffix $(BITS), $(lib1funcs-dir))
 endif
 
-KBUILD_CFLAGS += -I$(lib1funcs-dir)
+KBUILD_CFLAGS += -I$(lib1funcs-dir) -DDISABLE_BRANCH_PROFILING
 
 $(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE
        $(call cmd,shipped)
index aac452b..a319745 100644 (file)
@@ -1,5 +1,6 @@
 
 generic-y += bitsperlong.h
+generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += delay.h
diff --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h
deleted file mode 100644 (file)
index c419014..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  Copyright (C) 2010 Paul Mundt <lethal@linux-sh.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-
-#ifndef __CLKDEV__H_
-#define __CLKDEV__H_
-
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/clock.h>
-
-static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
-{
-       if (!slab_is_available())
-               return alloc_bootmem_low_pages(size);
-       else
-               return kzalloc(size, GFP_KERNEL);
-}
-
-#ifndef CONFIG_COMMON_CLK
-#define __clk_put(clk)
-#define __clk_get(clk) ({ 1; })
-#endif
-
-#endif /* __CLKDEV_H__ */
index 78b0d0f..1baf0ba 100644 (file)
@@ -69,6 +69,16 @@ static inline int hard_smp_processor_id(void)
        return mp_ops->smp_processor_id();
 }
 
+struct of_cpu_method {
+       const char *method;
+       struct plat_smp_ops *ops;
+};
+
+#define CPU_METHOD_OF_DECLARE(name, _method, _ops)                     \
+       static const struct of_cpu_method __cpu_method_of_table_##name  \
+               __used __section(__cpu_method_of_table)                 \
+               = { .method = _method, .ops = _ops }
+
 #else
 
 #define hard_smp_processor_id()        (0)
index 2ccf36c..09040fd 100644 (file)
@@ -46,6 +46,5 @@ obj-$(CONFIG_DWARF_UNWINDER)  += dwarf.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_callchain.o
 
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)               += hw_breakpoint.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
 
 ccflags-y := -Werror
index c8a4331..a150595 100644 (file)
@@ -144,9 +144,9 @@ ENTRY(exception_handler)
        mov     #64,r8
        cmp/hs  r8,r9
        bt      interrupt_entry ! vec >= 64 is interrupt
-       mov     #32,r8
+       mov     #31,r8
        cmp/hs  r8,r9
-       bt      trap_entry      ! 64 > vec >= 32  is trap
+       bt      trap_entry      ! 64 > vec >= 31  is trap
 
        mov.l   4f,r8
        mov     r9,r4
@@ -178,9 +178,9 @@ interrupt_entry:
 
 trap_entry:
        mov     #0x30,r8
-       cmp/ge  r8,r9           ! vector 0x20-0x2f is systemcall
+       cmp/ge  r8,r9           ! vector 0x1f-0x2f is systemcall
        bt      1f
-       add     #-0x10,r9       ! convert SH2 to SH3/4 ABI
+       mov     #0x1f,r9        ! convert to unified SH2/3/4 trap number
 1:     
        shll2   r9                      ! TRA
        bra     system_call     ! jump common systemcall entry
index 222742d..da77a8e 100644 (file)
@@ -109,9 +109,9 @@ ENTRY(exception_handler)
        mov     #64,r8
        cmp/hs  r8,r9
        bt      interrupt_entry ! vec >= 64 is interrupt
-       mov     #32,r8
+       mov     #31,r8
        cmp/hs  r8,r9
-       bt      trap_entry      ! 64 > vec >= 32  is trap
+       bt      trap_entry      ! 64 > vec >= 31  is trap
 
        mov.l   4f,r8
        mov     r9,r4
@@ -143,9 +143,9 @@ interrupt_entry:
 
 trap_entry:
        mov     #0x30,r8
-       cmp/ge  r8,r9           ! vector 0x20-0x2f is systemcall
+       cmp/ge  r8,r9           ! vector 0x1f-0x2f is systemcall
        bt      1f
-       add     #-0x10,r9       ! convert SH2 to SH3/4 ABI
+       mov     #0x1f,r9        ! convert to unified SH2/3/4 trap number
 1:     
        shll2   r9                      ! TRA
        bra     system_call     ! jump common systemcall entry
index 13047a4..c001f78 100644 (file)
@@ -268,20 +268,29 @@ debug_trap:
  *     Syscall #: R3
  *     Arguments #0 to #3: R4--R7
  *     Arguments #4 to #6: R0, R1, R2
- *     TRA: (number of arguments + ABI revision) x 4
+ *     TRA: See following table.
  *
- * This code also handles delegating other traps to the BIOS/gdb stub
- * according to:
- *
- * Trap number
  * (TRA>>2)    Purpose
  * --------    -------
  * 0x00-0x0f   original SH-3/4 syscall ABI (not in general use).
  * 0x10-0x1f   general SH-3/4 syscall ABI.
- * 0x20-0x2f   syscall ABI for SH-2 parts.
+ *      0x1f   unified SH-2/3/4 syscall ABI (preferred).
+ * 0x20-0x2f   original SH-2 syscall ABI.
  * 0x30-0x3f   debug traps used by the kernel.
  * 0x40-0xff   Not supported by all parts, so left unhandled.
  *
+ * For making system calls, any trap number in the range for the
+ * given cpu model may be used, but the unified trap number 0x1f is
+ * preferred for compatibility with all models.
+ *
+ * The low bits of the trap number were once documented as matching
+ * the number of arguments, but they were never actually used as such
+ * by the kernel. SH-2 originally used its own separate trap range
+ * because several hardware exceptions fell in the range used for the
+ * SH-3/4 syscall ABI.
+ *
+ * This code also handles delegating other traps to the BIOS/gdb stub.
+ *
  * Note: When we're first called, the TRA value must be shifted
  * right 2 bits in order to get the value that was used as the "trapa"
  * argument.
index 7db2489..974bc15 100644 (file)
@@ -66,6 +66,10 @@ ENTRY(_stext)
        mov     #0, r0
        ldc     r0, r6_bank
 #endif
+
+#ifdef CONFIG_OF
+       mov     r4, r12         ! Store device tree blob pointer in r12
+#endif
        
        /*
         * Prefetch if possible to reduce cache miss penalty.
@@ -314,6 +318,12 @@ ENTRY(_stext)
 10:            
 #endif
 
+#ifdef CONFIG_OF
+       mov.l   8f, r0          ! Make flat device tree available early.
+       jsr     @r0
+        mov    r12, r4
+#endif
+
        !                       Additional CPU initialization
        mov.l   6f, r0
        jsr     @r0
@@ -339,6 +349,9 @@ ENTRY(stack_start)
 5:     .long   start_kernel
 6:     .long   cpu_init
 7:     .long   init_thread_union
+#if defined(CONFIG_OF)
+8:     .long   sh_fdt_init
+#endif
 
 #ifdef CONFIG_PMB
 .LPMB_ADDR:            .long   PMB_ADDR
diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c
deleted file mode 100644 (file)
index cbb7d46..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Dummy local timer
- *
- * Copyright (C) 2008  Paul Mundt
- *
- * cloned from:
- *
- *  linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/smp.h>
-#include <linux/jiffies.h>
-#include <linux/percpu.h>
-#include <linux/clockchips.h>
-#include <linux/hardirq.h>
-#include <linux/irq.h>
-
-static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
-
-/*
- * Used on SMP for either the local timer or SMP_MSG_TIMER
- */
-void local_timer_interrupt(void)
-{
-       struct clock_event_device *clk = this_cpu_ptr(&local_clockevent);
-
-       irq_enter();
-       clk->event_handler(clk);
-       irq_exit();
-}
-
-void local_timer_setup(unsigned int cpu)
-{
-       struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
-
-       clk->name               = "dummy_timer";
-       clk->features           = CLOCK_EVT_FEAT_ONESHOT |
-                                 CLOCK_EVT_FEAT_PERIODIC |
-                                 CLOCK_EVT_FEAT_DUMMY;
-       clk->rating             = 400;
-       clk->mult               = 1;
-       clk->broadcast          = smp_timer_broadcast;
-       clk->cpumask            = cpumask_of(cpu);
-
-       clockevents_register_device(clk);
-}
-
-void local_timer_stop(unsigned int cpu)
-{
-}
index 3f1c18b..5d34605 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -172,6 +174,7 @@ disable:
 #endif
 }
 
+#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
 void calibrate_delay(void)
 {
        struct clk *clk = clk_get(NULL, "cpu_clk");
@@ -187,6 +190,7 @@ void calibrate_delay(void)
                         (loops_per_jiffy/(5000/HZ)) % 100,
                         loops_per_jiffy);
 }
+#endif
 
 void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
                                                unsigned long end_pfn)
@@ -238,6 +242,29 @@ void __init __weak plat_early_device_setup(void)
 {
 }
 
+#ifdef CONFIG_OF
+void __ref sh_fdt_init(phys_addr_t dt_phys)
+{
+       static int done = 0;
+       void *dt_virt;
+
+       /* Avoid calling an __init function on secondary cpus. */
+       if (done) return;
+
+       dt_virt = phys_to_virt(dt_phys);
+
+       if (!dt_virt || !early_init_dt_scan(dt_virt)) {
+               pr_crit("Error: invalid device tree blob"
+                       " at physical address %p\n", (void *)dt_phys);
+
+               while (true)
+                       cpu_relax();
+       }
+
+       done = 1;
+}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
        enable_mmu();
index d77f2f6..0b30b9d 100644 (file)
@@ -34,6 +34,9 @@ DECLARE_EXPORT(__sdivsi3);
 DECLARE_EXPORT(__lshrsi3);
 DECLARE_EXPORT(__ashrsi3);
 DECLARE_EXPORT(__ashlsi3);
+DECLARE_EXPORT(__lshrsi3_r0);
+DECLARE_EXPORT(__ashrsi3_r0);
+DECLARE_EXPORT(__ashlsi3_r0);
 DECLARE_EXPORT(__ashiftrt_r4_6);
 DECLARE_EXPORT(__ashiftrt_r4_7);
 DECLARE_EXPORT(__ashiftrt_r4_8);
index 13f633a..38e7860 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/atomic.h>
+#include <linux/clockchips.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
@@ -140,17 +141,14 @@ int __cpu_disable(void)
         */
        migrate_irqs();
 
-       /*
-        * Stop the local timer for this CPU.
-        */
-       local_timer_stop(cpu);
-
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
         * from the vm mask set of all processes.
         */
        flush_cache_all();
+#ifdef CONFIG_MMU
        local_flush_tlb_all();
+#endif
 
        clear_tasks_mm_cpumask(cpu);
 
@@ -183,8 +181,10 @@ asmlinkage void start_secondary(void)
        atomic_inc(&mm->mm_count);
        atomic_inc(&mm->mm_users);
        current->active_mm = mm;
+#ifdef CONFIG_MMU
        enter_lazy_tlb(mm, current);
        local_flush_tlb_all();
+#endif
 
        per_cpu_trap_init();
 
@@ -194,8 +194,6 @@ asmlinkage void start_secondary(void)
 
        local_irq_enable();
 
-       /* Enable local timers */
-       local_timer_setup(cpu);
        calibrate_delay();
 
        smp_store_cpu_info(cpu);
@@ -285,7 +283,8 @@ void arch_send_call_function_single_ipi(int cpu)
        mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
 }
 
-void smp_timer_broadcast(const struct cpumask *mask)
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+void tick_broadcast(const struct cpumask *mask)
 {
        int cpu;
 
@@ -296,9 +295,10 @@ void smp_timer_broadcast(const struct cpumask *mask)
 static void ipi_timer(void)
 {
        irq_enter();
-       local_timer_interrupt();
+       tick_receive_broadcast();
        irq_exit();
 }
+#endif
 
 void smp_message_recv(unsigned int msg)
 {
@@ -312,9 +312,11 @@ void smp_message_recv(unsigned int msg)
        case SMP_MSG_FUNCTION_SINGLE:
                generic_smp_call_function_single_interrupt();
                break;
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
        case SMP_MSG_TIMER:
                ipi_timer();
                break;
+#endif
        default:
                printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d\n",
                       smp_processor_id(), __func__, msg);
@@ -328,6 +330,8 @@ int setup_profiling_timer(unsigned int multiplier)
        return 0;
 }
 
+#ifdef CONFIG_MMU
+
 static void flush_tlb_all_ipi(void *info)
 {
        local_flush_tlb_all();
@@ -467,3 +471,5 @@ void flush_tlb_one(unsigned long asid, unsigned long vaddr)
        smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1);
        local_flush_tlb_one(asid, vaddr);
 }
+
+#endif
index bd47e9b..70a6434 100644 (file)
@@ -54,21 +54,38 @@ Boston, MA 02110-1301, USA.  */
 !
 ! (none)
 !
+! __ashlsi3_r0
+!
+! Entry:
+!
+! r4: Value to shift
+! r0: Shifts
+!
+! Exit:
+!
+! r0: Result
+!
+! Destroys:
+!
+! (none)
+
+
        .global __ashlsi3
+       .global __ashlsi3_r0
        
        .align  2
 __ashlsi3:
-       mov     #31,r0
-       and     r0,r5
+       mov     r5,r0
+       .align  2
+__ashlsi3_r0:
+       and     #31,r0
+       mov.l   r4,@-r15
+       mov     r0,r4
        mova    ashlsi3_table,r0
-       mov.b   @(r0,r5),r5
-#ifdef __sh1__
-       add     r5,r0
+       mov.b   @(r0,r4),r4
+       add     r4,r0
        jmp     @r0
-#else
-       braf    r5
-#endif
-       mov     r4,r0
+       mov.l   @r15+,r0
 
        .align  2
 ashlsi3_table:
index 6f3cf46..602599d 100644 (file)
@@ -54,22 +54,37 @@ Boston, MA 02110-1301, USA.  */
 !
 ! (none)
 !
+! __ashrsi3_r0
+!
+! Entry:
+!
+! r4: Value to shift
+! r0: Shifts
+!
+! Exit:
+!
+! r0: Result
+!
+! Destroys:
+!
+! (none)
 
        .global __ashrsi3
+       .global __ashrsi3_r0
        
        .align  2
 __ashrsi3:
-       mov     #31,r0
-       and     r0,r5
+       mov     r5,r0
+       .align  2
+__ashrsi3_r0:
+       and     #31,r0
+       mov.l   r4,@-r15
+       mov     r0,r4
        mova    ashrsi3_table,r0
-       mov.b   @(r0,r5),r5
-#ifdef __sh1__
-       add     r5,r0
+       mov.b   @(r0,r4),r4
+       add     r4,r0
        jmp     @r0
-#else
-       braf    r5
-#endif
-       mov     r4,r0
+       mov.l   @r15+,r0
 
        .align  2
 ashrsi3_table:
index 1e7aaa5..f2a6959 100644 (file)
@@ -53,22 +53,38 @@ Boston, MA 02110-1301, USA.  */
 ! Destroys:
 !
 ! (none)
+!
+! __lshrsi3_r0
+!
+! Entry:
+!
+! r0: Value to shift
+! r5: Shifts
+!
+! Exit:
+!
+! r0: Result
+!
+! Destroys:
+!
+! (none)
 !
        .global __lshrsi3
+       .global __lshrsi3_r0
        
        .align  2
 __lshrsi3:
-       mov     #31,r0
-       and     r0,r5
+       mov     r5,r0
+       .align  2
+__lshrsi3_r0:
+       and     #31,r0
+       mov.l   r4,@-r15
+       mov     r0,r4
        mova    lshrsi3_table,r0
-       mov.b   @(r0,r5),r5
-#ifdef __sh1__
-       add     r5,r0
+       mov.b   @(r0,r4),r4
+       add     r4,r0
        jmp     @r0
-#else
-       braf    r5
-#endif
-       mov     r4,r0
+       mov.l   @r15+,r0
 
        .align  2
 lshrsi3_table:
index ec29e14..bf25d7c 100644 (file)
@@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
 
        BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
 
+       preempt_disable();
        pagefault_disable();
 
        idx = FIX_CMAP_END -
@@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr)
        }
 
        pagefault_enable();
+       preempt_enable();
 }
index c4da2df..16688f5 100644 (file)
@@ -560,6 +560,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
        struct device_attach_data *data = _data;
        struct device *dev = data->dev;
        bool async_allowed;
+       int ret;
 
        /*
         * Check if device has already been claimed. This may
@@ -570,8 +571,17 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
        if (dev->driver)
                return -EBUSY;
 
-       if (!driver_match_device(drv, dev))
+       ret = driver_match_device(drv, dev);
+       if (ret == 0) {
+               /* no match */
                return 0;
+       } else if (ret == -EPROBE_DEFER) {
+               dev_dbg(dev, "Device match requests probe deferral\n");
+               driver_deferred_probe_add(dev);
+       } else if (ret < 0) {
+               dev_dbg(dev, "Bus failed to match device: %d", ret);
+               return ret;
+       } /* ret > 0 means positive match */
 
        async_allowed = driver_allows_async_probing(drv);
 
@@ -691,6 +701,7 @@ void device_initial_probe(struct device *dev)
 static int __driver_attach(struct device *dev, void *data)
 {
        struct device_driver *drv = data;
+       int ret;
 
        /*
         * Lock device and try to bind to it. We drop the error
@@ -702,8 +713,17 @@ static int __driver_attach(struct device *dev, void *data)
         * is an error.
         */
 
-       if (!driver_match_device(drv, dev))
+       ret = driver_match_device(drv, dev);
+       if (ret == 0) {
+               /* no match */
                return 0;
+       } else if (ret == -EPROBE_DEFER) {
+               dev_dbg(dev, "Device match requests probe deferral\n");
+               driver_deferred_probe_add(dev);
+       } else if (ret < 0) {
+               dev_dbg(dev, "Bus failed to match device: %d", ret);
+               return ret;
+       } /* ret > 0 means positive match */
 
        if (dev->parent)        /* Needed for USB */
                device_lock(dev->parent);
index 786be8f..1f63547 100644 (file)
@@ -136,7 +136,6 @@ static bool bcma_is_core_needed_early(u16 core_id)
        return false;
 }
 
-#if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS)
 static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
                                                     struct bcma_device *core)
 {
@@ -184,7 +183,7 @@ static unsigned int bcma_of_get_irq(struct platform_device *parent,
        struct of_phandle_args out_irq;
        int ret;
 
-       if (!parent || !parent->dev.of_node)
+       if (!IS_ENABLED(CONFIG_OF_IRQ) || !parent || !parent->dev.of_node)
                return 0;
 
        ret = bcma_of_irq_parse(parent, core, &out_irq, num);
@@ -202,23 +201,15 @@ static void bcma_of_fill_device(struct platform_device *parent,
 {
        struct device_node *node;
 
+       if (!IS_ENABLED(CONFIG_OF_IRQ))
+               return;
+
        node = bcma_of_find_child_device(parent, core);
        if (node)
                core->dev.of_node = node;
 
        core->irq = bcma_of_get_irq(parent, core, 0);
 }
-#else
-static void bcma_of_fill_device(struct platform_device *parent,
-                               struct bcma_device *core)
-{
-}
-static inline unsigned int bcma_of_get_irq(struct platform_device *parent,
-                                          struct bcma_device *core, int num)
-{
-       return 0;
-}
-#endif /* CONFIG_OF */
 
 unsigned int bcma_core_irq(struct bcma_device *core, int num)
 {
index 779b6ff..eb20b94 100644 (file)
@@ -353,11 +353,25 @@ void clkdev_drop(struct clk_lookup *cl)
 }
 EXPORT_SYMBOL(clkdev_drop);
 
+static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
+                                               const char *con_id,
+                                               const char *dev_id, ...)
+{
+       struct clk_lookup *cl;
+       va_list ap;
+
+       va_start(ap, dev_id);
+       cl = vclkdev_create(hw, con_id, dev_id, ap);
+       va_end(ap);
+
+       return cl;
+}
+
 /**
  * clk_register_clkdev - register one clock lookup for a struct clk
  * @clk: struct clk to associate with all clk_lookups
  * @con_id: connection ID string on device
- * @dev_id: format string describing device name
+ * @dev_id: string describing device name
  *
  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
  * clkdev.
@@ -368,17 +382,22 @@ EXPORT_SYMBOL(clkdev_drop);
  * after clk_register().
  */
 int clk_register_clkdev(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...)
+       const char *dev_id)
 {
        struct clk_lookup *cl;
-       va_list ap;
 
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
-       va_start(ap, dev_fmt);
-       cl = vclkdev_create(__clk_get_hw(clk), con_id, dev_fmt, ap);
-       va_end(ap);
+       /*
+        * Since dev_id can be NULL, and NULL is handled specially, we must
+        * pass it as either a NULL format string, or with "%s".
+        */
+       if (dev_id)
+               cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, "%s",
+                                          dev_id);
+       else
+               cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, NULL);
 
        return cl ? 0 : -ENOMEM;
 }
index f25cd79..11bfee8 100644 (file)
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) "psci: " fmt
 
 #include <linux/arm-smccc.h>
+#include <linux/cpuidle.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/of.h>
 #include <linux/printk.h>
 #include <linux/psci.h>
 #include <linux/reboot.h>
+#include <linux/slab.h>
 #include <linux/suspend.h>
 
 #include <uapi/linux/psci.h>
 
+#include <asm/cpuidle.h>
 #include <asm/cputype.h>
 #include <asm/system_misc.h>
 #include <asm/smp_plat.h>
@@ -244,6 +247,123 @@ static int __init psci_features(u32 psci_func_id)
                              psci_func_id, 0, 0);
 }
 
+#ifdef CONFIG_CPU_IDLE
+static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+
+static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+{
+       int i, ret, count = 0;
+       u32 *psci_states;
+       struct device_node *state_node;
+
+       /*
+        * If the PSCI cpu_suspend function hook has not been initialized
+        * idle states must not be enabled, so bail out
+        */
+       if (!psci_ops.cpu_suspend)
+               return -EOPNOTSUPP;
+
+       /* Count idle states */
+       while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states",
+                                             count))) {
+               count++;
+               of_node_put(state_node);
+       }
+
+       if (!count)
+               return -ENODEV;
+
+       psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
+       if (!psci_states)
+               return -ENOMEM;
+
+       for (i = 0; i < count; i++) {
+               u32 state;
+
+               state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
+
+               ret = of_property_read_u32(state_node,
+                                          "arm,psci-suspend-param",
+                                          &state);
+               if (ret) {
+                       pr_warn(" * %s missing arm,psci-suspend-param property\n",
+                               state_node->full_name);
+                       of_node_put(state_node);
+                       goto free_mem;
+               }
+
+               of_node_put(state_node);
+               pr_debug("psci-power-state %#x index %d\n", state, i);
+               if (!psci_power_state_is_valid(state)) {
+                       pr_warn("Invalid PSCI power state %#x\n", state);
+                       ret = -EINVAL;
+                       goto free_mem;
+               }
+               psci_states[i] = state;
+       }
+       /* Idle states parsed correctly, initialize per-cpu pointer */
+       per_cpu(psci_power_state, cpu) = psci_states;
+       return 0;
+
+free_mem:
+       kfree(psci_states);
+       return ret;
+}
+
+int psci_cpu_init_idle(unsigned int cpu)
+{
+       struct device_node *cpu_node;
+       int ret;
+
+       cpu_node = of_get_cpu_node(cpu, NULL);
+       if (!cpu_node)
+               return -ENODEV;
+
+       ret = psci_dt_cpu_init_idle(cpu_node, cpu);
+
+       of_node_put(cpu_node);
+
+       return ret;
+}
+
+static int psci_suspend_finisher(unsigned long index)
+{
+       u32 *state = __this_cpu_read(psci_power_state);
+
+       return psci_ops.cpu_suspend(state[index - 1],
+                                   virt_to_phys(cpu_resume));
+}
+
+int psci_cpu_suspend_enter(unsigned long index)
+{
+       int ret;
+       u32 *state = __this_cpu_read(psci_power_state);
+       /*
+        * idle state index 0 corresponds to wfi, should never be called
+        * from the cpu_suspend operations
+        */
+       if (WARN_ON_ONCE(!index))
+               return -EINVAL;
+
+       if (!psci_power_state_loses_context(state[index - 1]))
+               ret = psci_ops.cpu_suspend(state[index - 1], 0);
+       else
+               ret = cpu_suspend(index, psci_suspend_finisher);
+
+       return ret;
+}
+
+/* ARM specific CPU idle operations */
+#ifdef CONFIG_ARM
+static struct cpuidle_ops psci_cpuidle_ops __initdata = {
+       .suspend = psci_cpu_suspend_enter,
+       .init = psci_dt_cpu_init_idle,
+};
+
+CPUIDLE_METHOD_OF_DECLARE(psci, "arm,psci", &psci_cpuidle_ops);
+#endif
+#endif
+
 static int psci_system_suspend(unsigned long unused)
 {
        return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
index 693fb7c..f8f659f 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
+#include <linux/ktime.h>
 #include <linux/mISDNif.h>
 #include <linux/export.h>
 #include "core.h"
@@ -45,15 +46,15 @@ static u_int *debug;
 static LIST_HEAD(iclock_list);
 static DEFINE_RWLOCK(iclock_lock);
 static u16 iclock_count;               /* counter of last clock */
-static struct timeval iclock_tv;       /* time stamp of last clock */
-static int iclock_tv_valid;            /* already received one timestamp */
+static ktime_t iclock_timestamp;       /* time stamp of last clock */
+static int iclock_timestamp_valid;     /* already received one timestamp */
 static struct mISDNclock *iclock_current;
 
 void
 mISDN_init_clock(u_int *dp)
 {
        debug = dp;
-       do_gettimeofday(&iclock_tv);
+       iclock_timestamp = ktime_get();
 }
 
 static void
@@ -86,7 +87,7 @@ select_iclock(void)
        }
        if (bestclock != iclock_current) {
                /* no clock received yet */
-               iclock_tv_valid = 0;
+               iclock_timestamp_valid = 0;
        }
        iclock_current = bestclock;
 }
@@ -139,12 +140,11 @@ mISDN_unregister_clock(struct mISDNclock *iclock)
 EXPORT_SYMBOL(mISDN_unregister_clock);
 
 void
-mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv)
+mISDN_clock_update(struct mISDNclock *iclock, int samples, ktime_t *timestamp)
 {
        u_long          flags;
-       struct timeval  tv_now;
-       time_t          elapsed_sec;
-       int             elapsed_8000th;
+       ktime_t         timestamp_now;
+       u16             delta;
 
        write_lock_irqsave(&iclock_lock, flags);
        if (iclock_current != iclock) {
@@ -156,33 +156,27 @@ mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv)
                write_unlock_irqrestore(&iclock_lock, flags);
                return;
        }
-       if (iclock_tv_valid) {
+       if (iclock_timestamp_valid) {
                /* increment sample counter by given samples */
                iclock_count += samples;
-               if (tv) { /* tv must be set, if function call is delayed */
-                       iclock_tv.tv_sec = tv->tv_sec;
-                       iclock_tv.tv_usec = tv->tv_usec;
-               } else
-                       do_gettimeofday(&iclock_tv);
+               if (timestamp) { /* timestamp must be set, if function call is delayed */
+                       iclock_timestamp = *timestamp;
+               } else  {
+                       iclock_timestamp = ktime_get();
+               }
        } else {
                /* calc elapsed time by system clock */
-               if (tv) { /* tv must be set, if function call is delayed */
-                       tv_now.tv_sec = tv->tv_sec;
-                       tv_now.tv_usec = tv->tv_usec;
-               } else
-                       do_gettimeofday(&tv_now);
-               elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
-               elapsed_8000th = (tv_now.tv_usec / 125)
-                       - (iclock_tv.tv_usec / 125);
-               if (elapsed_8000th < 0) {
-                       elapsed_sec -= 1;
-                       elapsed_8000th += 8000;
+               if (timestamp) { /* timestamp must be set, if function call is delayed */
+                       timestamp_now = *timestamp;
+               } else {
+                       timestamp_now = ktime_get();
                }
+               delta = ktime_divns(ktime_sub(timestamp_now, iclock_timestamp),
+                               (NSEC_PER_SEC / 8000));
                /* add elapsed time to counter and set new timestamp */
-               iclock_count += elapsed_sec * 8000 + elapsed_8000th;
-               iclock_tv.tv_sec = tv_now.tv_sec;
-               iclock_tv.tv_usec = tv_now.tv_usec;
-               iclock_tv_valid = 1;
+               iclock_count += delta;
+               iclock_timestamp = timestamp_now;
+               iclock_timestamp_valid = 1;
                if (*debug & DEBUG_CLOCK)
                        printk("Received first clock from source '%s'.\n",
                               iclock_current ? iclock_current->name : "nothing");
@@ -195,22 +189,17 @@ unsigned short
 mISDN_clock_get(void)
 {
        u_long          flags;
-       struct timeval  tv_now;
-       time_t          elapsed_sec;
-       int             elapsed_8000th;
+       ktime_t         timestamp_now;
+       u16             delta;
        u16             count;
 
        read_lock_irqsave(&iclock_lock, flags);
        /* calc elapsed time by system clock */
-       do_gettimeofday(&tv_now);
-       elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
-       elapsed_8000th = (tv_now.tv_usec / 125) - (iclock_tv.tv_usec / 125);
-       if (elapsed_8000th < 0) {
-               elapsed_sec -= 1;
-               elapsed_8000th += 8000;
-       }
+       timestamp_now = ktime_get();
+       delta = ktime_divns(ktime_sub(timestamp_now, iclock_timestamp),
+                       (NSEC_PER_SEC / 8000));
        /* add elapsed time to counter */
-       count = iclock_count + elapsed_sec * 8000 + elapsed_8000th;
+       count = iclock_count + delta;
        read_unlock_irqrestore(&iclock_lock, flags);
        return count;
 }
index c331272..5361197 100644 (file)
 
 struct vb2_dc_conf {
        struct device           *dev;
+       struct dma_attrs        attrs;
 };
 
 struct vb2_dc_buf {
        struct device                   *dev;
        void                            *vaddr;
        unsigned long                   size;
+       void                            *cookie;
        dma_addr_t                      dma_addr;
+       struct dma_attrs                attrs;
        enum dma_data_direction         dma_dir;
        struct sg_table                 *dma_sgt;
        struct frame_vector             *vec;
@@ -131,7 +134,8 @@ static void vb2_dc_put(void *buf_priv)
                sg_free_table(buf->sgt_base);
                kfree(buf->sgt_base);
        }
-       dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+       dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
+                       &buf->attrs);
        put_device(buf->dev);
        kfree(buf);
 }
@@ -147,14 +151,18 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size,
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
-       buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr,
-                                               GFP_KERNEL | gfp_flags);
-       if (!buf->vaddr) {
+       buf->attrs = conf->attrs;
+       buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr,
+                                       GFP_KERNEL | gfp_flags, &buf->attrs);
+       if (!buf->cookie) {
                dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
                kfree(buf);
                return ERR_PTR(-ENOMEM);
        }
 
+       if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->attrs))
+               buf->vaddr = buf->cookie;
+
        /* Prevent the device from being released while the buffer is used */
        buf->dev = get_device(dev);
        buf->size = size;
@@ -185,8 +193,8 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
         */
        vma->vm_pgoff = 0;
 
-       ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
-               buf->dma_addr, buf->size);
+       ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
+               buf->dma_addr, buf->size, &buf->attrs);
 
        if (ret) {
                pr_err("Remapping memory failed, error: %d\n", ret);
@@ -329,7 +337,7 @@ static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 {
        struct vb2_dc_buf *buf = dbuf->priv;
 
-       return buf->vaddr + pgnum * PAGE_SIZE;
+       return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
 }
 
 static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
@@ -368,8 +376,8 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
                return NULL;
        }
 
-       ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
-               buf->size);
+       ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+               buf->size, &buf->attrs);
        if (ret < 0) {
                dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
                kfree(sgt);
@@ -721,7 +729,8 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
 
-void *vb2_dma_contig_init_ctx(struct device *dev)
+void *vb2_dma_contig_init_ctx_attrs(struct device *dev,
+                                   struct dma_attrs *attrs)
 {
        struct vb2_dc_conf *conf;
 
@@ -730,10 +739,12 @@ void *vb2_dma_contig_init_ctx(struct device *dev)
                return ERR_PTR(-ENOMEM);
 
        conf->dev = dev;
+       if (attrs)
+               conf->attrs = *attrs;
 
        return conf;
 }
-EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx);
+EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx_attrs);
 
 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
 {
index be2ac5c..8a55c1a 100644 (file)
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_PPC_WERROR)    += -Werror
 cxl-y                          += main.o file.o irq.o fault.o native.o
 cxl-y                          += context.o sysfs.o debugfs.o pci.o trace.o
 cxl-y                          += vphb.o api.o
+cxl-$(CONFIG_PPC_PSERIES)      += flash.o guest.o of.o hcalls.o
 obj-$(CONFIG_CXL)              += cxl.o
 obj-$(CONFIG_CXL_BASE)         += base.o
 
index ea3eeb7..2107c94 100644 (file)
@@ -51,8 +51,6 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev)
        if (rc)
                goto err_mapping;
 
-       cxl_assign_psn_space(ctx);
-
        return ctx;
 
 err_mapping:
@@ -78,7 +76,6 @@ struct device *cxl_get_phys_dev(struct pci_dev *dev)
 
        return afu->adapter->dev.parent;
 }
-EXPORT_SYMBOL_GPL(cxl_get_phys_dev);
 
 int cxl_release_context(struct cxl_context *ctx)
 {
@@ -91,28 +88,11 @@ int cxl_release_context(struct cxl_context *ctx)
 }
 EXPORT_SYMBOL_GPL(cxl_release_context);
 
-int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num)
-{
-       if (num == 0)
-               num = ctx->afu->pp_irqs;
-       return afu_allocate_irqs(ctx, num);
-}
-EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs);
-
-void cxl_free_afu_irqs(struct cxl_context *ctx)
-{
-       afu_irq_name_free(ctx);
-       cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
-}
-EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
-
 static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num)
 {
        __u16 range;
        int r;
 
-       WARN_ON(num == 0);
-
        for (r = 0; r < CXL_IRQ_RANGES; r++) {
                range = ctx->irqs.range[r];
                if (num < range) {
@@ -123,6 +103,44 @@ static irq_hw_number_t cxl_find_afu_irq(struct cxl_context *ctx, int num)
        return 0;
 }
 
+int cxl_allocate_afu_irqs(struct cxl_context *ctx, int num)
+{
+       int res;
+       irq_hw_number_t hwirq;
+
+       if (num == 0)
+               num = ctx->afu->pp_irqs;
+       res = afu_allocate_irqs(ctx, num);
+       if (!res && !cpu_has_feature(CPU_FTR_HVMODE)) {
+               /* In a guest, the PSL interrupt is not multiplexed. It was
+                * allocated above, and we need to set its handler
+                */
+               hwirq = cxl_find_afu_irq(ctx, 0);
+               if (hwirq)
+                       cxl_map_irq(ctx->afu->adapter, hwirq, cxl_ops->psl_interrupt, ctx, "psl");
+       }
+       return res;
+}
+EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs);
+
+void cxl_free_afu_irqs(struct cxl_context *ctx)
+{
+       irq_hw_number_t hwirq;
+       unsigned int virq;
+
+       if (!cpu_has_feature(CPU_FTR_HVMODE)) {
+               hwirq = cxl_find_afu_irq(ctx, 0);
+               if (hwirq) {
+                       virq = irq_find_mapping(NULL, hwirq);
+                       if (virq)
+                               cxl_unmap_irq(virq, ctx);
+               }
+       }
+       afu_irq_name_free(ctx);
+       cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+}
+EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
+
 int cxl_map_afu_irq(struct cxl_context *ctx, int num,
                    irq_handler_t handler, void *cookie, char *name)
 {
@@ -178,7 +196,7 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
 
        cxl_ctx_get();
 
-       if ((rc = cxl_attach_process(ctx, kernel, wed , 0))) {
+       if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
                put_pid(ctx->pid);
                cxl_ctx_put();
                goto out;
@@ -193,7 +211,7 @@ EXPORT_SYMBOL_GPL(cxl_start_context);
 
 int cxl_process_element(struct cxl_context *ctx)
 {
-       return ctx->pe;
+       return ctx->external_pe;
 }
 EXPORT_SYMBOL_GPL(cxl_process_element);
 
@@ -207,7 +225,6 @@ EXPORT_SYMBOL_GPL(cxl_stop_context);
 void cxl_set_master(struct cxl_context *ctx)
 {
        ctx->master = true;
-       cxl_assign_psn_space(ctx);
 }
 EXPORT_SYMBOL_GPL(cxl_set_master);
 
@@ -325,15 +342,11 @@ EXPORT_SYMBOL_GPL(cxl_start_work);
 
 void __iomem *cxl_psa_map(struct cxl_context *ctx)
 {
-       struct cxl_afu *afu = ctx->afu;
-       int rc;
-
-       rc = cxl_afu_check_and_enable(afu);
-       if (rc)
+       if (ctx->status != STARTED)
                return NULL;
 
        pr_devel("%s: psn_phys%llx size:%llx\n",
-                __func__, afu->psn_phys, afu->adapter->ps_size);
+               __func__, ctx->psn_phys, ctx->psn_size);
        return ioremap(ctx->psn_phys, ctx->psn_size);
 }
 EXPORT_SYMBOL_GPL(cxl_psa_map);
@@ -349,11 +362,11 @@ int cxl_afu_reset(struct cxl_context *ctx)
        struct cxl_afu *afu = ctx->afu;
        int rc;
 
-       rc = __cxl_afu_reset(afu);
+       rc = cxl_ops->afu_reset(afu);
        if (rc)
                return rc;
 
-       return cxl_afu_check_and_enable(afu);
+       return cxl_ops->afu_check_and_enable(afu);
 }
 EXPORT_SYMBOL_GPL(cxl_afu_reset);
 
@@ -363,3 +376,11 @@ void cxl_perst_reloads_same_image(struct cxl_afu *afu,
        afu->adapter->perst_same_image = perst_reloads_same_image;
 }
 EXPORT_SYMBOL_GPL(cxl_perst_reloads_same_image);
+
+ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count)
+{
+       struct cxl_afu *afu = cxl_pci_to_afu(dev);
+
+       return cxl_ops->read_adapter_vpd(afu->adapter, buf, count);
+}
+EXPORT_SYMBOL_GPL(cxl_read_adapter_vpd);
index a9f0dd3..9b90ec6 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/rcupdate.h>
 #include <asm/errno.h>
 #include <misc/cxl-base.h>
+#include <linux/of_platform.h>
 #include "cxl.h"
 
 /* protected by rcu */
@@ -84,3 +85,34 @@ void unregister_cxl_calls(struct cxl_calls *calls)
        synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(unregister_cxl_calls);
+
+int cxl_update_properties(struct device_node *dn,
+                         struct property *new_prop)
+{
+       return of_update_property(dn, new_prop);
+}
+EXPORT_SYMBOL_GPL(cxl_update_properties);
+
+static int __init cxl_base_init(void)
+{
+       struct device_node *np = NULL;
+       struct platform_device *dev;
+       int count = 0;
+
+       /*
+        * Scan for compatible devices in guest only
+        */
+       if (cpu_has_feature(CPU_FTR_HVMODE))
+               return 0;
+
+       while ((np = of_find_compatible_node(np, NULL,
+                                    "ibm,coherent-platform-facility"))) {
+               dev = of_platform_device_create(np, NULL, NULL);
+               if (dev)
+                       count++;
+       }
+       pr_devel("Found %d cxl device(s)\n", count);
+       return 0;
+}
+
+module_init(cxl_base_init);
index 262b88e..10370f2 100644 (file)
@@ -95,7 +95,12 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
                return i;
 
        ctx->pe = i;
-       ctx->elem = &ctx->afu->spa[i];
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               ctx->elem = &ctx->afu->native->spa[i];
+               ctx->external_pe = ctx->pe;
+       } else {
+               ctx->external_pe = -1; /* assigned when attaching */
+       }
        ctx->pe_inserted = false;
 
        /*
@@ -214,8 +219,8 @@ int __detach_context(struct cxl_context *ctx)
        /* Only warn if we detached while the link was OK.
         * If detach fails when hw is down, we don't care.
         */
-       WARN_ON(cxl_detach_process(ctx) &&
-               cxl_adapter_link_ok(ctx->afu->adapter));
+       WARN_ON(cxl_ops->detach_process(ctx) &&
+               cxl_ops->link_ok(ctx->afu->adapter, ctx->afu));
        flush_work(&ctx->fault_work); /* Only needed for dedicated process */
 
        /* release the reference to the group leader and mm handling pid */
index a521bc7..38e21cf 100644 (file)
@@ -324,6 +324,10 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An     = {0x0A0};
 #define CXL_MODE_TIME_SLICED 0x4
 #define CXL_SUPPORTED_MODES (CXL_MODE_DEDICATED | CXL_MODE_DIRECTED)
 
+#define CXL_DEV_MINORS 13   /* 1 control + 4 AFUs * 3 (dedicated/master/shared) */
+#define CXL_CARD_MINOR(adapter) (adapter->adapter_num * CXL_DEV_MINORS)
+#define CXL_DEVT_ADAPTER(dev) (MINOR(dev) / CXL_DEV_MINORS)
+
 enum cxl_context_status {
        CLOSED,
        OPENED,
@@ -336,6 +340,12 @@ enum prefault_modes {
        CXL_PREFAULT_ALL,
 };
 
+enum cxl_attrs {
+       CXL_ADAPTER_ATTRS,
+       CXL_AFU_MASTER_ATTRS,
+       CXL_AFU_ATTRS,
+};
+
 struct cxl_sste {
        __be64 esid_data;
        __be64 vsid_data;
@@ -344,18 +354,46 @@ struct cxl_sste {
 #define to_cxl_adapter(d) container_of(d, struct cxl, dev)
 #define to_cxl_afu(d) container_of(d, struct cxl_afu, dev)
 
-struct cxl_afu {
+struct cxl_afu_native {
+       void __iomem *p1n_mmio;
+       void __iomem *afu_desc_mmio;
        irq_hw_number_t psl_hwirq;
+       unsigned int psl_virq;
+       struct mutex spa_mutex;
+       /*
+        * Only the first part of the SPA is used for the process element
+        * linked list. The only other part that software needs to worry about
+        * is sw_command_status, which we store a separate pointer to.
+        * Everything else in the SPA is only used by hardware
+        */
+       struct cxl_process_element *spa;
+       __be64 *sw_command_status;
+       unsigned int spa_size;
+       int spa_order;
+       int spa_max_procs;
+       u64 pp_offset;
+};
+
+struct cxl_afu_guest {
+       u64 handle;
+       phys_addr_t p2n_phys;
+       u64 p2n_size;
+       int max_ints;
+       struct mutex recovery_lock;
+       int previous_state;
+};
+
+struct cxl_afu {
+       struct cxl_afu_native *native;
+       struct cxl_afu_guest *guest;
        irq_hw_number_t serr_hwirq;
-       char *err_irq_name;
-       char *psl_irq_name;
        unsigned int serr_virq;
-       void __iomem *p1n_mmio;
+       char *psl_irq_name;
+       char *err_irq_name;
        void __iomem *p2n_mmio;
        phys_addr_t psn_phys;
-       u64 pp_offset;
        u64 pp_size;
-       void __iomem *afu_desc_mmio;
+
        struct cxl *adapter;
        struct device dev;
        struct cdev afu_cdev_s, afu_cdev_m, afu_cdev_d;
@@ -363,26 +401,12 @@ struct cxl_afu {
        struct idr contexts_idr;
        struct dentry *debugfs;
        struct mutex contexts_lock;
-       struct mutex spa_mutex;
        spinlock_t afu_cntl_lock;
 
        /* AFU error buffer fields and bin attribute for sysfs */
        u64 eb_len, eb_offset;
        struct bin_attribute attr_eb;
 
-       /*
-        * Only the first part of the SPA is used for the process element
-        * linked list. The only other part that software needs to worry about
-        * is sw_command_status, which we store a separate pointer to.
-        * Everything else in the SPA is only used by hardware
-        */
-       struct cxl_process_element *spa;
-       __be64 *sw_command_status;
-       unsigned int spa_size;
-       int spa_order;
-       int spa_max_procs;
-       unsigned int psl_virq;
-
        /* pointer to the vphb */
        struct pci_controller *phb;
 
@@ -421,6 +445,12 @@ struct cxl_irq_name {
        char *name;
 };
 
+struct irq_avail {
+       irq_hw_number_t offset;
+       irq_hw_number_t range;
+       unsigned long   *bitmap;
+};
+
 /*
  * This is a cxl context.  If the PSL is in dedicated mode, there will be one
  * of these per AFU.  If in AFU directed there can be lots of these.
@@ -476,7 +506,19 @@ struct cxl_context {
 
        struct cxl_process_element *elem;
 
-       int pe; /* process element handle */
+       /*
+        * pe is the process element handle, assigned by this driver when the
+        * context is initialized.
+        *
+        * external_pe is the PE shown outside of cxl.
+        * On bare-metal, pe=external_pe, because we decide what the handle is.
+        * In a guest, we only find out about the pe used by pHyp when the
+        * context is attached, and that's the value we want to report outside
+        * of cxl.
+        */
+       int pe;
+       int external_pe;
+
        u32 irq_count;
        bool pe_inserted;
        bool master;
@@ -488,11 +530,34 @@ struct cxl_context {
        struct rcu_head rcu;
 };
 
-struct cxl {
+struct cxl_native {
+       u64 afu_desc_off;
+       u64 afu_desc_size;
        void __iomem *p1_mmio;
        void __iomem *p2_mmio;
        irq_hw_number_t err_hwirq;
        unsigned int err_virq;
+       u64 ps_off;
+};
+
+struct cxl_guest {
+       struct platform_device *pdev;
+       int irq_nranges;
+       struct cdev cdev;
+       irq_hw_number_t irq_base_offset;
+       struct irq_avail *irq_avail;
+       spinlock_t irq_alloc_lock;
+       u64 handle;
+       char *status;
+       u16 vendor;
+       u16 device;
+       u16 subsystem_vendor;
+       u16 subsystem;
+};
+
+struct cxl {
+       struct cxl_native *native;
+       struct cxl_guest *guest;
        spinlock_t afu_list_lock;
        struct cxl_afu *afu[CXL_MAX_SLICES];
        struct device dev;
@@ -503,9 +568,6 @@ struct cxl {
        struct bin_attribute cxl_attr;
        int adapter_num;
        int user_irqs;
-       u64 afu_desc_off;
-       u64 afu_desc_size;
-       u64 ps_off;
        u64 ps_size;
        u16 psl_rev;
        u16 base_image;
@@ -519,13 +581,15 @@ struct cxl {
        bool perst_same_image;
 };
 
-int cxl_alloc_one_irq(struct cxl *adapter);
-void cxl_release_one_irq(struct cxl *adapter, int hwirq);
-int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsigned int num);
-void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);
-int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq);
+int cxl_pci_alloc_one_irq(struct cxl *adapter);
+void cxl_pci_release_one_irq(struct cxl *adapter, int hwirq);
+int cxl_pci_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsigned int num);
+void cxl_pci_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter);
+int cxl_pci_setup_irq(struct cxl *adapter, unsigned int hwirq, unsigned int virq);
 int cxl_update_image_control(struct cxl *adapter);
-int cxl_reset(struct cxl *adapter);
+int cxl_pci_reset(struct cxl *adapter);
+void cxl_pci_release_afu(struct device *dev);
+ssize_t cxl_pci_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len);
 
 /* common == phyp + powernv */
 struct cxl_process_element_common {
@@ -555,29 +619,32 @@ struct cxl_process_element {
        __be32 software_state;
 } __packed;
 
-static inline bool cxl_adapter_link_ok(struct cxl *cxl)
+static inline bool cxl_adapter_link_ok(struct cxl *cxl, struct cxl_afu *afu)
 {
        struct pci_dev *pdev;
 
-       pdev = to_pci_dev(cxl->dev.parent);
-       return !pci_channel_offline(pdev);
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               pdev = to_pci_dev(cxl->dev.parent);
+               return !pci_channel_offline(pdev);
+       }
+       return true;
 }
 
 static inline void __iomem *_cxl_p1_addr(struct cxl *cxl, cxl_p1_reg_t reg)
 {
        WARN_ON(!cpu_has_feature(CPU_FTR_HVMODE));
-       return cxl->p1_mmio + cxl_reg_off(reg);
+       return cxl->native->p1_mmio + cxl_reg_off(reg);
 }
 
 static inline void cxl_p1_write(struct cxl *cxl, cxl_p1_reg_t reg, u64 val)
 {
-       if (likely(cxl_adapter_link_ok(cxl)))
+       if (likely(cxl_adapter_link_ok(cxl, NULL)))
                out_be64(_cxl_p1_addr(cxl, reg), val);
 }
 
 static inline u64 cxl_p1_read(struct cxl *cxl, cxl_p1_reg_t reg)
 {
-       if (likely(cxl_adapter_link_ok(cxl)))
+       if (likely(cxl_adapter_link_ok(cxl, NULL)))
                return in_be64(_cxl_p1_addr(cxl, reg));
        else
                return ~0ULL;
@@ -586,18 +653,18 @@ static inline u64 cxl_p1_read(struct cxl *cxl, cxl_p1_reg_t reg)
 static inline void __iomem *_cxl_p1n_addr(struct cxl_afu *afu, cxl_p1n_reg_t reg)
 {
        WARN_ON(!cpu_has_feature(CPU_FTR_HVMODE));
-       return afu->p1n_mmio + cxl_reg_off(reg);
+       return afu->native->p1n_mmio + cxl_reg_off(reg);
 }
 
 static inline void cxl_p1n_write(struct cxl_afu *afu, cxl_p1n_reg_t reg, u64 val)
 {
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
+       if (likely(cxl_adapter_link_ok(afu->adapter, afu)))
                out_be64(_cxl_p1n_addr(afu, reg), val);
 }
 
 static inline u64 cxl_p1n_read(struct cxl_afu *afu, cxl_p1n_reg_t reg)
 {
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
+       if (likely(cxl_adapter_link_ok(afu->adapter, afu)))
                return in_be64(_cxl_p1n_addr(afu, reg));
        else
                return ~0ULL;
@@ -610,39 +677,19 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu *afu, cxl_p2n_reg_t reg
 
 static inline void cxl_p2n_write(struct cxl_afu *afu, cxl_p2n_reg_t reg, u64 val)
 {
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
+       if (likely(cxl_adapter_link_ok(afu->adapter, afu)))
                out_be64(_cxl_p2n_addr(afu, reg), val);
 }
 
 static inline u64 cxl_p2n_read(struct cxl_afu *afu, cxl_p2n_reg_t reg)
 {
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
+       if (likely(cxl_adapter_link_ok(afu->adapter, afu)))
                return in_be64(_cxl_p2n_addr(afu, reg));
        else
                return ~0ULL;
 }
 
-static inline u64 cxl_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off)
-{
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
-               return in_le64((afu)->afu_desc_mmio + (afu)->crs_offset +
-                              ((cr) * (afu)->crs_len) + (off));
-       else
-               return ~0ULL;
-}
-
-static inline u32 cxl_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off)
-{
-       if (likely(cxl_adapter_link_ok(afu->adapter)))
-               return in_le32((afu)->afu_desc_mmio + (afu)->crs_offset +
-                              ((cr) * (afu)->crs_len) + (off));
-       else
-               return 0xffffffff;
-}
-u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off);
-u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off);
-
-ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
+ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
                                loff_t off, size_t count);
 
 
@@ -652,13 +699,14 @@ struct cxl_calls {
 };
 int register_cxl_calls(struct cxl_calls *calls);
 void unregister_cxl_calls(struct cxl_calls *calls);
+int cxl_update_properties(struct device_node *dn, struct property *new_prop);
 
-int cxl_alloc_adapter_nr(struct cxl *adapter);
 void cxl_remove_adapter_nr(struct cxl *adapter);
 
 int cxl_alloc_spa(struct cxl_afu *afu);
 void cxl_release_spa(struct cxl_afu *afu);
 
+dev_t cxl_get_dev(void);
 int cxl_file_init(void);
 void cxl_file_exit(void);
 int cxl_register_adapter(struct cxl *adapter);
@@ -679,21 +727,19 @@ void cxl_sysfs_afu_remove(struct cxl_afu *afu);
 int cxl_sysfs_afu_m_add(struct cxl_afu *afu);
 void cxl_sysfs_afu_m_remove(struct cxl_afu *afu);
 
-int cxl_afu_activate_mode(struct cxl_afu *afu, int mode);
-int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode);
-int cxl_afu_deactivate_mode(struct cxl_afu *afu);
+struct cxl *cxl_alloc_adapter(void);
+struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice);
 int cxl_afu_select_best_mode(struct cxl_afu *afu);
 
-int cxl_register_psl_irq(struct cxl_afu *afu);
-void cxl_release_psl_irq(struct cxl_afu *afu);
-int cxl_register_psl_err_irq(struct cxl *adapter);
-void cxl_release_psl_err_irq(struct cxl *adapter);
-int cxl_register_serr_irq(struct cxl_afu *afu);
-void cxl_release_serr_irq(struct cxl_afu *afu);
+int cxl_native_register_psl_irq(struct cxl_afu *afu);
+void cxl_native_release_psl_irq(struct cxl_afu *afu);
+int cxl_native_register_psl_err_irq(struct cxl *adapter);
+void cxl_native_release_psl_err_irq(struct cxl *adapter);
+int cxl_native_register_serr_irq(struct cxl_afu *afu);
+void cxl_native_release_serr_irq(struct cxl_afu *afu);
 int afu_register_irqs(struct cxl_context *ctx, u32 count);
 void afu_release_irqs(struct cxl_context *ctx, void *cookie);
 void afu_irq_name_free(struct cxl_context *ctx);
-irqreturn_t cxl_slice_irq_err(int irq, void *data);
 
 int cxl_debugfs_init(void);
 void cxl_debugfs_exit(void);
@@ -707,6 +753,7 @@ void cxl_prefault(struct cxl_context *ctx, u64 wed);
 
 struct cxl *get_cxl_adapter(int num);
 int cxl_alloc_sst(struct cxl_context *ctx);
+void cxl_dump_debug_buffer(void *addr, size_t size);
 
 void init_cxl_native(void);
 
@@ -720,40 +767,54 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
 void cxl_unmap_irq(unsigned int virq, void *cookie);
 int __detach_context(struct cxl_context *ctx);
 
-/* This matches the layout of the H_COLLECT_CA_INT_INFO retbuf */
+/*
+ * This must match the layout of the H_COLLECT_CA_INT_INFO retbuf defined
+ * in PAPR.
+ * A word about endianness: a pointer to this structure is passed when
+ * calling the hcall. However, it is not a block of memory filled up by
+ * the hypervisor. The return values are found in registers, and copied
+ * one by one when returning from the hcall. See the end of the call to
+ * plpar_hcall9() in hvCall.S
+ * As a consequence:
+ * - we don't need to do any endianness conversion
+ * - the pid and tid are an exception. They are 32-bit values returned in
+ *   the same 64-bit register. So we do need to worry about byte ordering.
+ */
 struct cxl_irq_info {
        u64 dsisr;
        u64 dar;
        u64 dsr;
+#ifndef CONFIG_CPU_LITTLE_ENDIAN
        u32 pid;
        u32 tid;
+#else
+       u32 tid;
+       u32 pid;
+#endif
        u64 afu_err;
        u64 errstat;
-       u64 padding[3]; /* to match the expected retbuf size for plpar_hcall9 */
+       u64 proc_handle;
+       u64 padding[2]; /* to match the expected retbuf size for plpar_hcall9 */
 };
 
 void cxl_assign_psn_space(struct cxl_context *ctx);
-int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed,
-                           u64 amr);
-int cxl_detach_process(struct cxl_context *ctx);
-
-int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info);
-int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask);
+irqreturn_t cxl_irq(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info);
+int cxl_register_one_irq(struct cxl *adapter, irq_handler_t handler,
+                       void *cookie, irq_hw_number_t *dest_hwirq,
+                       unsigned int *dest_virq, const char *name);
 
 int cxl_check_error(struct cxl_afu *afu);
 int cxl_afu_slbia(struct cxl_afu *afu);
 int cxl_tlb_slb_invalidate(struct cxl *adapter);
 int cxl_afu_disable(struct cxl_afu *afu);
-int __cxl_afu_reset(struct cxl_afu *afu);
-int cxl_afu_check_and_enable(struct cxl_afu *afu);
 int cxl_psl_purge(struct cxl_afu *afu);
 
 void cxl_stop_trace(struct cxl *cxl);
 int cxl_pci_vphb_add(struct cxl_afu *afu);
-void cxl_pci_vphb_reconfigure(struct cxl_afu *afu);
 void cxl_pci_vphb_remove(struct cxl_afu *afu);
 
 extern struct pci_driver cxl_pci_driver;
+extern struct platform_driver cxl_of_driver;
 int afu_allocate_irqs(struct cxl_context *ctx, u32 count);
 
 int afu_open(struct inode *inode, struct file *file);
@@ -764,4 +825,61 @@ unsigned int afu_poll(struct file *file, struct poll_table_struct *poll);
 ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off);
 extern const struct file_operations afu_fops;
 
+struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_device *dev);
+void cxl_guest_remove_adapter(struct cxl *adapter);
+int cxl_of_read_adapter_handle(struct cxl *adapter, struct device_node *np);
+int cxl_of_read_adapter_properties(struct cxl *adapter, struct device_node *np);
+ssize_t cxl_guest_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len);
+ssize_t cxl_guest_read_afu_vpd(struct cxl_afu *afu, void *buf, size_t len);
+int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_np);
+void cxl_guest_remove_afu(struct cxl_afu *afu);
+int cxl_of_read_afu_handle(struct cxl_afu *afu, struct device_node *afu_np);
+int cxl_of_read_afu_properties(struct cxl_afu *afu, struct device_node *afu_np);
+int cxl_guest_add_chardev(struct cxl *adapter);
+void cxl_guest_remove_chardev(struct cxl *adapter);
+void cxl_guest_reload_module(struct cxl *adapter);
+int cxl_of_probe(struct platform_device *pdev);
+
+struct cxl_backend_ops {
+       struct module *module;
+       int (*adapter_reset)(struct cxl *adapter);
+       int (*alloc_one_irq)(struct cxl *adapter);
+       void (*release_one_irq)(struct cxl *adapter, int hwirq);
+       int (*alloc_irq_ranges)(struct cxl_irq_ranges *irqs,
+                               struct cxl *adapter, unsigned int num);
+       void (*release_irq_ranges)(struct cxl_irq_ranges *irqs,
+                               struct cxl *adapter);
+       int (*setup_irq)(struct cxl *adapter, unsigned int hwirq,
+                       unsigned int virq);
+       irqreturn_t (*handle_psl_slice_error)(struct cxl_context *ctx,
+                                       u64 dsisr, u64 errstat);
+       irqreturn_t (*psl_interrupt)(int irq, void *data);
+       int (*ack_irq)(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask);
+       int (*attach_process)(struct cxl_context *ctx, bool kernel,
+                       u64 wed, u64 amr);
+       int (*detach_process)(struct cxl_context *ctx);
+       bool (*support_attributes)(const char *attr_name, enum cxl_attrs type);
+       bool (*link_ok)(struct cxl *cxl, struct cxl_afu *afu);
+       void (*release_afu)(struct device *dev);
+       ssize_t (*afu_read_err_buffer)(struct cxl_afu *afu, char *buf,
+                               loff_t off, size_t count);
+       int (*afu_check_and_enable)(struct cxl_afu *afu);
+       int (*afu_activate_mode)(struct cxl_afu *afu, int mode);
+       int (*afu_deactivate_mode)(struct cxl_afu *afu, int mode);
+       int (*afu_reset)(struct cxl_afu *afu);
+       int (*afu_cr_read8)(struct cxl_afu *afu, int cr_idx, u64 offset, u8 *val);
+       int (*afu_cr_read16)(struct cxl_afu *afu, int cr_idx, u64 offset, u16 *val);
+       int (*afu_cr_read32)(struct cxl_afu *afu, int cr_idx, u64 offset, u32 *val);
+       int (*afu_cr_read64)(struct cxl_afu *afu, int cr_idx, u64 offset, u64 *val);
+       int (*afu_cr_write8)(struct cxl_afu *afu, int cr_idx, u64 offset, u8 val);
+       int (*afu_cr_write16)(struct cxl_afu *afu, int cr_idx, u64 offset, u16 val);
+       int (*afu_cr_write32)(struct cxl_afu *afu, int cr_idx, u64 offset, u32 val);
+       ssize_t (*read_adapter_vpd)(struct cxl *adapter, void *buf, size_t count);
+};
+extern const struct cxl_backend_ops cxl_native_ops;
+extern const struct cxl_backend_ops cxl_guest_ops;
+extern const struct cxl_backend_ops *cxl_ops;
+
+/* check if the given pci_dev is on the the cxl vphb bus */
+bool cxl_pci_is_vphb_device(struct pci_dev *dev);
 #endif
index 18df6f4..5751899 100644 (file)
@@ -118,6 +118,10 @@ void cxl_debugfs_afu_remove(struct cxl_afu *afu)
 int __init cxl_debugfs_init(void)
 {
        struct dentry *ent;
+
+       if (!cpu_has_feature(CPU_FTR_HVMODE))
+               return 0;
+
        ent = debugfs_create_dir("cxl", NULL);
        if (IS_ERR(ent))
                return PTR_ERR(ent);
index 81c3f75..9a8650b 100644 (file)
@@ -101,7 +101,7 @@ static void cxl_ack_ae(struct cxl_context *ctx)
 {
        unsigned long flags;
 
-       cxl_ack_irq(ctx, CXL_PSL_TFC_An_AE, 0);
+       cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_AE, 0);
 
        spin_lock_irqsave(&ctx->lock, flags);
        ctx->pending_fault = true;
@@ -125,7 +125,7 @@ static int cxl_handle_segment_miss(struct cxl_context *ctx,
        else {
 
                mb(); /* Order seg table write to TFC MMIO write */
-               cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
+               cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
        }
 
        return IRQ_HANDLED;
@@ -163,7 +163,7 @@ static void cxl_handle_page_fault(struct cxl_context *ctx,
        local_irq_restore(flags);
 
        pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe);
-       cxl_ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
+       cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_R, 0);
 }
 
 /*
@@ -254,14 +254,17 @@ void cxl_handle_fault(struct work_struct *fault_work)
        u64 dar = ctx->dar;
        struct mm_struct *mm = NULL;
 
-       if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr ||
-           cxl_p2n_read(ctx->afu, CXL_PSL_DAR_An) != dar ||
-           cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) != ctx->pe) {
-               /* Most likely explanation is harmless - a dedicated process
-                * has detached and these were cleared by the PSL purge, but
-                * warn about it just in case */
-               dev_notice(&ctx->afu->dev, "cxl_handle_fault: Translation fault regs changed\n");
-               return;
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               if (cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An) != dsisr ||
+                   cxl_p2n_read(ctx->afu, CXL_PSL_DAR_An) != dar ||
+                   cxl_p2n_read(ctx->afu, CXL_PSL_PEHandle_An) != ctx->pe) {
+                       /* Most likely explanation is harmless - a dedicated
+                        * process has detached and these were cleared by the
+                        * PSL purge, but warn about it just in case
+                        */
+                       dev_notice(&ctx->afu->dev, "cxl_handle_fault: Translation fault regs changed\n");
+                       return;
+               }
        }
 
        /* Early return if the context is being / has been detached */
index 783337d..eec468f 100644 (file)
@@ -26,9 +26,7 @@
 #include "trace.h"
 
 #define CXL_NUM_MINORS 256 /* Total to reserve */
-#define CXL_DEV_MINORS 13   /* 1 control + 4 AFUs * 3 (dedicated/master/shared) */
 
-#define CXL_CARD_MINOR(adapter) (adapter->adapter_num * CXL_DEV_MINORS)
 #define CXL_AFU_MINOR_D(afu) (CXL_CARD_MINOR(afu->adapter) + 1 + (3 * afu->slice))
 #define CXL_AFU_MINOR_M(afu) (CXL_AFU_MINOR_D(afu) + 1)
 #define CXL_AFU_MINOR_S(afu) (CXL_AFU_MINOR_D(afu) + 2)
@@ -36,7 +34,6 @@
 #define CXL_AFU_MKDEV_M(afu) MKDEV(MAJOR(cxl_dev), CXL_AFU_MINOR_M(afu))
 #define CXL_AFU_MKDEV_S(afu) MKDEV(MAJOR(cxl_dev), CXL_AFU_MINOR_S(afu))
 
-#define CXL_DEVT_ADAPTER(dev) (MINOR(dev) / CXL_DEV_MINORS)
 #define CXL_DEVT_AFU(dev) ((MINOR(dev) % CXL_DEV_MINORS - 1) / 3)
 
 #define CXL_DEVT_IS_CARD(dev) (MINOR(dev) % CXL_DEV_MINORS == 0)
@@ -79,7 +76,7 @@ static int __afu_open(struct inode *inode, struct file *file, bool master)
        if (!afu->current_mode)
                goto err_put_afu;
 
-       if (!cxl_adapter_link_ok(adapter)) {
+       if (!cxl_ops->link_ok(adapter, afu)) {
                rc = -EIO;
                goto err_put_afu;
        }
@@ -210,8 +207,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
 
        trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
 
-       if ((rc = cxl_attach_process(ctx, false, work.work_element_descriptor,
-                                    amr))) {
+       if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
+                                                       amr))) {
                afu_release_irqs(ctx, ctx);
                goto out;
        }
@@ -222,12 +219,13 @@ out:
        mutex_unlock(&ctx->status_mutex);
        return rc;
 }
+
 static long afu_ioctl_process_element(struct cxl_context *ctx,
                                      int __user *upe)
 {
        pr_devel("%s: pe: %i\n", __func__, ctx->pe);
 
-       if (copy_to_user(upe, &ctx->pe, sizeof(__u32)))
+       if (copy_to_user(upe, &ctx->external_pe, sizeof(__u32)))
                return -EFAULT;
 
        return 0;
@@ -259,7 +257,7 @@ long afu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        if (ctx->status == CLOSED)
                return -EIO;
 
-       if (!cxl_adapter_link_ok(ctx->afu->adapter))
+       if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
                return -EIO;
 
        pr_devel("afu_ioctl\n");
@@ -289,7 +287,7 @@ int afu_mmap(struct file *file, struct vm_area_struct *vm)
        if (ctx->status != STARTED)
                return -EIO;
 
-       if (!cxl_adapter_link_ok(ctx->afu->adapter))
+       if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
                return -EIO;
 
        return cxl_context_iomap(ctx, vm);
@@ -336,7 +334,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count,
        int rc;
        DEFINE_WAIT(wait);
 
-       if (!cxl_adapter_link_ok(ctx->afu->adapter))
+       if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
                return -EIO;
 
        if (count < CXL_READ_MIN_SIZE)
@@ -349,7 +347,7 @@ ssize_t afu_read(struct file *file, char __user *buf, size_t count,
                if (ctx_event_pending(ctx))
                        break;
 
-               if (!cxl_adapter_link_ok(ctx->afu->adapter)) {
+               if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) {
                        rc = -EIO;
                        goto out;
                }
@@ -445,7 +443,8 @@ static const struct file_operations afu_master_fops = {
 
 static char *cxl_devnode(struct device *dev, umode_t *mode)
 {
-       if (CXL_DEVT_IS_CARD(dev->devt)) {
+       if (cpu_has_feature(CPU_FTR_HVMODE) &&
+           CXL_DEVT_IS_CARD(dev->devt)) {
                /*
                 * These minor numbers will eventually be used to program the
                 * PSL and AFUs once we have dynamic reprogramming support
@@ -546,6 +545,11 @@ int cxl_register_adapter(struct cxl *adapter)
        return device_register(&adapter->dev);
 }
 
+dev_t cxl_get_dev(void)
+{
+       return cxl_dev;
+}
+
 int __init cxl_file_init(void)
 {
        int rc;
diff --git a/drivers/misc/cxl/flash.c b/drivers/misc/cxl/flash.c
new file mode 100644 (file)
index 0000000..68dd0b7
--- /dev/null
@@ -0,0 +1,538 @@
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <asm/rtas.h>
+
+#include "cxl.h"
+#include "hcalls.h"
+
+#define DOWNLOAD_IMAGE 1
+#define VALIDATE_IMAGE 2
+
+struct ai_header {
+       u16 version;
+       u8  reserved0[6];
+       u16 vendor;
+       u16 device;
+       u16 subsystem_vendor;
+       u16 subsystem;
+       u64 image_offset;
+       u64 image_length;
+       u8  reserved1[96];
+};
+
+static struct semaphore sem;
+unsigned long *buffer[CXL_AI_MAX_ENTRIES];
+struct sg_list *le;
+static u64 continue_token;
+static unsigned int transfer;
+
+struct update_props_workarea {
+       __be32 phandle;
+       __be32 state;
+       __be64 reserved;
+       __be32 nprops;
+} __packed;
+
+struct update_nodes_workarea {
+       __be32 state;
+       __be64 unit_address;
+       __be32 reserved;
+} __packed;
+
+#define DEVICE_SCOPE 3
+#define NODE_ACTION_MASK       0xff000000
+#define NODE_COUNT_MASK                0x00ffffff
+#define OPCODE_DELETE  0x01000000
+#define OPCODE_UPDATE  0x02000000
+#define OPCODE_ADD     0x03000000
+
+static int rcall(int token, char *buf, s32 scope)
+{
+       int rc;
+
+       spin_lock(&rtas_data_buf_lock);
+
+       memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE);
+       rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, scope);
+       memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);
+
+       spin_unlock(&rtas_data_buf_lock);
+       return rc;
+}
+
+static int update_property(struct device_node *dn, const char *name,
+                          u32 vd, char *value)
+{
+       struct property *new_prop;
+       u32 *val;
+       int rc;
+
+       new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL);
+       if (!new_prop)
+               return -ENOMEM;
+
+       new_prop->name = kstrdup(name, GFP_KERNEL);
+       if (!new_prop->name) {
+               kfree(new_prop);
+               return -ENOMEM;
+       }
+
+       new_prop->length = vd;
+       new_prop->value = kzalloc(new_prop->length, GFP_KERNEL);
+       if (!new_prop->value) {
+               kfree(new_prop->name);
+               kfree(new_prop);
+               return -ENOMEM;
+       }
+       memcpy(new_prop->value, value, vd);
+
+       val = (u32 *)new_prop->value;
+       rc = cxl_update_properties(dn, new_prop);
+       pr_devel("%s: update property (%s, length: %i, value: %#x)\n",
+                 dn->name, name, vd, be32_to_cpu(*val));
+
+       if (rc) {
+               kfree(new_prop->name);
+               kfree(new_prop->value);
+               kfree(new_prop);
+       }
+       return rc;
+}
+
+static int update_node(__be32 phandle, s32 scope)
+{
+       struct update_props_workarea *upwa;
+       struct device_node *dn;
+       int i, rc, ret;
+       char *prop_data;
+       char *buf;
+       int token;
+       u32 nprops;
+       u32 vd;
+
+       token = rtas_token("ibm,update-properties");
+       if (token == RTAS_UNKNOWN_SERVICE)
+               return -EINVAL;
+
+       buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       dn = of_find_node_by_phandle(be32_to_cpu(phandle));
+       if (!dn) {
+               kfree(buf);
+               return -ENOENT;
+       }
+
+       upwa = (struct update_props_workarea *)&buf[0];
+       upwa->phandle = phandle;
+       do {
+               rc = rcall(token, buf, scope);
+               if (rc < 0)
+                       break;
+
+               prop_data = buf + sizeof(*upwa);
+               nprops = be32_to_cpu(upwa->nprops);
+
+               if (*prop_data == 0) {
+                       prop_data++;
+                       vd = be32_to_cpu(*(__be32 *)prop_data);
+                       prop_data += vd + sizeof(vd);
+                       nprops--;
+               }
+
+               for (i = 0; i < nprops; i++) {
+                       char *prop_name;
+
+                       prop_name = prop_data;
+                       prop_data += strlen(prop_name) + 1;
+                       vd = be32_to_cpu(*(__be32 *)prop_data);
+                       prop_data += sizeof(vd);
+
+                       if ((vd != 0x00000000) && (vd != 0x80000000)) {
+                               ret = update_property(dn, prop_name, vd,
+                                               prop_data);
+                               if (ret)
+                                       pr_err("cxl: Could not update property %s - %i\n",
+                                              prop_name, ret);
+
+                               prop_data += vd;
+                       }
+               }
+       } while (rc == 1);
+
+       of_node_put(dn);
+       kfree(buf);
+       return rc;
+}
+
+static int update_devicetree(struct cxl *adapter, s32 scope)
+{
+       struct update_nodes_workarea *unwa;
+       u32 action, node_count;
+       int token, rc, i;
+       __be32 *data, drc_index, phandle;
+       char *buf;
+
+       token = rtas_token("ibm,update-nodes");
+       if (token == RTAS_UNKNOWN_SERVICE)
+               return -EINVAL;
+
+       buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       unwa = (struct update_nodes_workarea *)&buf[0];
+       unwa->unit_address = cpu_to_be64(adapter->guest->handle);
+       do {
+               rc = rcall(token, buf, scope);
+               if (rc && rc != 1)
+                       break;
+
+               data = (__be32 *)buf + 4;
+               while (be32_to_cpu(*data) & NODE_ACTION_MASK) {
+                       action = be32_to_cpu(*data) & NODE_ACTION_MASK;
+                       node_count = be32_to_cpu(*data) & NODE_COUNT_MASK;
+                       pr_devel("device reconfiguration - action: %#x, nodes: %#x\n",
+                                action, node_count);
+                       data++;
+
+                       for (i = 0; i < node_count; i++) {
+                               phandle = *data++;
+
+                               switch (action) {
+                               case OPCODE_DELETE:
+                                       /* nothing to do */
+                                       break;
+                               case OPCODE_UPDATE:
+                                       update_node(phandle, scope);
+                                       break;
+                               case OPCODE_ADD:
+                                       /* nothing to do, just move pointer */
+                                       drc_index = *data++;
+                                       break;
+                               }
+                       }
+               }
+       } while (rc == 1);
+
+       kfree(buf);
+       return 0;
+}
+
+static int handle_image(struct cxl *adapter, int operation,
+                       long (*fct)(u64, u64, u64, u64 *),
+                       struct cxl_adapter_image *ai)
+{
+       size_t mod, s_copy, len_chunk = 0;
+       struct ai_header *header = NULL;
+       unsigned int entries = 0, i;
+       void *dest, *from;
+       int rc = 0, need_header;
+
+       /* base adapter image header */
+       need_header = (ai->flags & CXL_AI_NEED_HEADER);
+       if (need_header) {
+               header = kzalloc(sizeof(struct ai_header), GFP_KERNEL);
+               if (!header)
+                       return -ENOMEM;
+               header->version = cpu_to_be16(1);
+               header->vendor = cpu_to_be16(adapter->guest->vendor);
+               header->device = cpu_to_be16(adapter->guest->device);
+               header->subsystem_vendor = cpu_to_be16(adapter->guest->subsystem_vendor);
+               header->subsystem = cpu_to_be16(adapter->guest->subsystem);
+               header->image_offset = cpu_to_be64(CXL_AI_HEADER_SIZE);
+               header->image_length = cpu_to_be64(ai->len_image);
+       }
+
+       /* number of entries in the list */
+       len_chunk = ai->len_data;
+       if (need_header)
+               len_chunk += CXL_AI_HEADER_SIZE;
+
+       entries = len_chunk / CXL_AI_BUFFER_SIZE;
+       mod = len_chunk % CXL_AI_BUFFER_SIZE;
+       if (mod)
+               entries++;
+
+       if (entries > CXL_AI_MAX_ENTRIES) {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       /*          < -- MAX_CHUNK_SIZE = 4096 * 256 = 1048576 bytes -->
+        * chunk 0  ----------------------------------------------------
+        *          | header   |  data                                 |
+        *          ----------------------------------------------------
+        * chunk 1  ----------------------------------------------------
+        *          | data                                             |
+        *          ----------------------------------------------------
+        * ....
+        * chunk n  ----------------------------------------------------
+        *          | data                                             |
+        *          ----------------------------------------------------
+        */
+       from = (void *) ai->data;
+       for (i = 0; i < entries; i++) {
+               dest = buffer[i];
+               s_copy = CXL_AI_BUFFER_SIZE;
+
+               if ((need_header) && (i == 0)) {
+                       /* add adapter image header */
+                       memcpy(buffer[i], header, sizeof(struct ai_header));
+                       s_copy = CXL_AI_BUFFER_SIZE - CXL_AI_HEADER_SIZE;
+                       dest += CXL_AI_HEADER_SIZE; /* image offset */
+               }
+               if ((i == (entries - 1)) && mod)
+                       s_copy = mod;
+
+               /* copy data */
+               if (copy_from_user(dest, from, s_copy))
+                       goto err;
+
+               /* fill in the list */
+               le[i].phys_addr = cpu_to_be64(virt_to_phys(buffer[i]));
+               le[i].len = cpu_to_be64(CXL_AI_BUFFER_SIZE);
+               if ((i == (entries - 1)) && mod)
+                       le[i].len = cpu_to_be64(mod);
+               from += s_copy;
+       }
+       pr_devel("%s (op: %i, need header: %i, entries: %i, token: %#llx)\n",
+                __func__, operation, need_header, entries, continue_token);
+
+       /*
+        * download/validate the adapter image to the coherent
+        * platform facility
+        */
+       rc = fct(adapter->guest->handle, virt_to_phys(le), entries,
+               &continue_token);
+       if (rc == 0) /* success of download/validation operation */
+               continue_token = 0;
+
+err:
+       kfree(header);
+
+       return rc;
+}
+
+static int transfer_image(struct cxl *adapter, int operation,
+                       struct cxl_adapter_image *ai)
+{
+       int rc = 0;
+       int afu;
+
+       switch (operation) {
+       case DOWNLOAD_IMAGE:
+               rc = handle_image(adapter, operation,
+                               &cxl_h_download_adapter_image, ai);
+               if (rc < 0) {
+                       pr_devel("resetting adapter\n");
+                       cxl_h_reset_adapter(adapter->guest->handle);
+               }
+               return rc;
+
+       case VALIDATE_IMAGE:
+               rc = handle_image(adapter, operation,
+                               &cxl_h_validate_adapter_image, ai);
+               if (rc < 0) {
+                       pr_devel("resetting adapter\n");
+                       cxl_h_reset_adapter(adapter->guest->handle);
+                       return rc;
+               }
+               if (rc == 0) {
+                       pr_devel("remove curent afu\n");
+                       for (afu = 0; afu < adapter->slices; afu++)
+                               cxl_guest_remove_afu(adapter->afu[afu]);
+
+                       pr_devel("resetting adapter\n");
+                       cxl_h_reset_adapter(adapter->guest->handle);
+
+                       /* The entire image has now been
+                        * downloaded and the validation has
+                        * been successfully performed.
+                        * After that, the partition should call
+                        * ibm,update-nodes and
+                        * ibm,update-properties to receive the
+                        * current configuration
+                        */
+                       rc = update_devicetree(adapter, DEVICE_SCOPE);
+                       transfer = 1;
+               }
+               return rc;
+       }
+
+       return -EINVAL;
+}
+
+static long ioctl_transfer_image(struct cxl *adapter, int operation,
+                               struct cxl_adapter_image __user *uai)
+{
+       struct cxl_adapter_image ai;
+
+       pr_devel("%s\n", __func__);
+
+       if (copy_from_user(&ai, uai, sizeof(struct cxl_adapter_image)))
+               return -EFAULT;
+
+       /*
+        * Make sure reserved fields and bits are set to 0
+        */
+       if (ai.reserved1 || ai.reserved2 || ai.reserved3 || ai.reserved4 ||
+               (ai.flags & ~CXL_AI_ALL))
+               return -EINVAL;
+
+       return transfer_image(adapter, operation, &ai);
+}
+
+static int device_open(struct inode *inode, struct file *file)
+{
+       int adapter_num = CXL_DEVT_ADAPTER(inode->i_rdev);
+       struct cxl *adapter;
+       int rc = 0, i;
+
+       pr_devel("in %s\n", __func__);
+
+       BUG_ON(sizeof(struct ai_header) != CXL_AI_HEADER_SIZE);
+
+       /* Allows one process to open the device by using a semaphore */
+       if (down_interruptible(&sem) != 0)
+               return -EPERM;
+
+       if (!(adapter = get_cxl_adapter(adapter_num)))
+               return -ENODEV;
+
+       file->private_data = adapter;
+       continue_token = 0;
+       transfer = 0;
+
+       for (i = 0; i < CXL_AI_MAX_ENTRIES; i++)
+               buffer[i] = NULL;
+
+       /* aligned buffer containing list entries which describes up to
+        * 1 megabyte of data (256 entries of 4096 bytes each)
+        *  Logical real address of buffer 0  -  Buffer 0 length in bytes
+        *  Logical real address of buffer 1  -  Buffer 1 length in bytes
+        *  Logical real address of buffer 2  -  Buffer 2 length in bytes
+        *  ....
+        *  ....
+        *  Logical real address of buffer N  -  Buffer N length in bytes
+        */
+       le = (struct sg_list *)get_zeroed_page(GFP_KERNEL);
+       if (!le) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
+               buffer[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL);
+               if (!buffer[i]) {
+                       rc = -ENOMEM;
+                       goto err1;
+               }
+       }
+
+       return 0;
+
+err1:
+       for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
+               if (buffer[i])
+                       free_page((unsigned long) buffer[i]);
+       }
+
+       if (le)
+               free_page((unsigned long) le);
+err:
+       put_device(&adapter->dev);
+
+       return rc;
+}
+
+static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct cxl *adapter = file->private_data;
+
+       pr_devel("in %s\n", __func__);
+
+       if (cmd == CXL_IOCTL_DOWNLOAD_IMAGE)
+               return ioctl_transfer_image(adapter,
+                                       DOWNLOAD_IMAGE,
+                                       (struct cxl_adapter_image __user *)arg);
+       else if (cmd == CXL_IOCTL_VALIDATE_IMAGE)
+               return ioctl_transfer_image(adapter,
+                                       VALIDATE_IMAGE,
+                                       (struct cxl_adapter_image __user *)arg);
+       else
+               return -EINVAL;
+}
+
+static long device_compat_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       return device_ioctl(file, cmd, arg);
+}
+
+static int device_close(struct inode *inode, struct file *file)
+{
+       struct cxl *adapter = file->private_data;
+       int i;
+
+       pr_devel("in %s\n", __func__);
+
+       for (i = 0; i < CXL_AI_MAX_ENTRIES; i++) {
+               if (buffer[i])
+                       free_page((unsigned long) buffer[i]);
+       }
+
+       if (le)
+               free_page((unsigned long) le);
+
+       up(&sem);
+       put_device(&adapter->dev);
+       continue_token = 0;
+
+       /* reload the module */
+       if (transfer)
+               cxl_guest_reload_module(adapter);
+       else {
+               pr_devel("resetting adapter\n");
+               cxl_h_reset_adapter(adapter->guest->handle);
+       }
+
+       transfer = 0;
+       return 0;
+}
+
+static const struct file_operations fops = {
+       .owner          = THIS_MODULE,
+       .open           = device_open,
+       .unlocked_ioctl = device_ioctl,
+       .compat_ioctl   = device_compat_ioctl,
+       .release        = device_close,
+};
+
+void cxl_guest_remove_chardev(struct cxl *adapter)
+{
+       cdev_del(&adapter->guest->cdev);
+}
+
+int cxl_guest_add_chardev(struct cxl *adapter)
+{
+       dev_t devt;
+       int rc;
+
+       devt = MKDEV(MAJOR(cxl_get_dev()), CXL_CARD_MINOR(adapter));
+       cdev_init(&adapter->guest->cdev, &fops);
+       if ((rc = cdev_add(&adapter->guest->cdev, devt, 1))) {
+               dev_err(&adapter->dev,
+                       "Unable to add chardev on adapter (card%i): %i\n",
+                       adapter->adapter_num, rc);
+               goto err;
+       }
+       adapter->dev.devt = devt;
+       sema_init(&sem, 1);
+err:
+       return rc;
+}
diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c
new file mode 100644 (file)
index 0000000..8213372
--- /dev/null
@@ -0,0 +1,1177 @@
+/*
+ * Copyright 2015 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+
+#include "cxl.h"
+#include "hcalls.h"
+#include "trace.h"
+
+#define CXL_ERROR_DETECTED_EVENT       1
+#define CXL_SLOT_RESET_EVENT           2
+#define CXL_RESUME_EVENT               3
+
+static void pci_error_handlers(struct cxl_afu *afu,
+                               int bus_error_event,
+                               pci_channel_state_t state)
+{
+       struct pci_dev *afu_dev;
+
+       if (afu->phb == NULL)
+               return;
+
+       list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) {
+               if (!afu_dev->driver)
+                       continue;
+
+               switch (bus_error_event) {
+               case CXL_ERROR_DETECTED_EVENT:
+                       afu_dev->error_state = state;
+
+                       if (afu_dev->driver->err_handler &&
+                           afu_dev->driver->err_handler->error_detected)
+                               afu_dev->driver->err_handler->error_detected(afu_dev, state);
+               break;
+               case CXL_SLOT_RESET_EVENT:
+                       afu_dev->error_state = state;
+
+                       if (afu_dev->driver->err_handler &&
+                           afu_dev->driver->err_handler->slot_reset)
+                               afu_dev->driver->err_handler->slot_reset(afu_dev);
+               break;
+               case CXL_RESUME_EVENT:
+                       if (afu_dev->driver->err_handler &&
+                           afu_dev->driver->err_handler->resume)
+                               afu_dev->driver->err_handler->resume(afu_dev);
+               break;
+               }
+       }
+}
+
+static irqreturn_t guest_handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr,
+                                       u64 errstat)
+{
+       pr_devel("in %s\n", __func__);
+       dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%.16llx\n", errstat);
+
+       return cxl_ops->ack_irq(ctx, 0, errstat);
+}
+
+static ssize_t guest_collect_vpd(struct cxl *adapter, struct cxl_afu *afu,
+                       void *buf, size_t len)
+{
+       unsigned int entries, mod;
+       unsigned long **vpd_buf = NULL;
+       struct sg_list *le;
+       int rc = 0, i, tocopy;
+       u64 out = 0;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       /* number of entries in the list */
+       entries = len / SG_BUFFER_SIZE;
+       mod = len % SG_BUFFER_SIZE;
+       if (mod)
+               entries++;
+
+       if (entries > SG_MAX_ENTRIES) {
+               entries = SG_MAX_ENTRIES;
+               len = SG_MAX_ENTRIES * SG_BUFFER_SIZE;
+               mod = 0;
+       }
+
+       vpd_buf = kzalloc(entries * sizeof(unsigned long *), GFP_KERNEL);
+       if (!vpd_buf)
+               return -ENOMEM;
+
+       le = (struct sg_list *)get_zeroed_page(GFP_KERNEL);
+       if (!le) {
+               rc = -ENOMEM;
+               goto err1;
+       }
+
+       for (i = 0; i < entries; i++) {
+               vpd_buf[i] = (unsigned long *)get_zeroed_page(GFP_KERNEL);
+               if (!vpd_buf[i]) {
+                       rc = -ENOMEM;
+                       goto err2;
+               }
+               le[i].phys_addr = cpu_to_be64(virt_to_phys(vpd_buf[i]));
+               le[i].len = cpu_to_be64(SG_BUFFER_SIZE);
+               if ((i == (entries - 1)) && mod)
+                       le[i].len = cpu_to_be64(mod);
+       }
+
+       if (adapter)
+               rc = cxl_h_collect_vpd_adapter(adapter->guest->handle,
+                                       virt_to_phys(le), entries, &out);
+       else
+               rc = cxl_h_collect_vpd(afu->guest->handle, 0,
+                               virt_to_phys(le), entries, &out);
+       pr_devel("length of available (entries: %i), vpd: %#llx\n",
+               entries, out);
+
+       if (!rc) {
+               /*
+                * hcall returns in 'out' the size of available VPDs.
+                * It fills the buffer with as much data as possible.
+                */
+               if (out < len)
+                       len = out;
+               rc = len;
+               if (out) {
+                       for (i = 0; i < entries; i++) {
+                               if (len < SG_BUFFER_SIZE)
+                                       tocopy = len;
+                               else
+                                       tocopy = SG_BUFFER_SIZE;
+                               memcpy(buf, vpd_buf[i], tocopy);
+                               buf += tocopy;
+                               len -= tocopy;
+                       }
+               }
+       }
+err2:
+       for (i = 0; i < entries; i++) {
+               if (vpd_buf[i])
+                       free_page((unsigned long) vpd_buf[i]);
+       }
+       free_page((unsigned long) le);
+err1:
+       kfree(vpd_buf);
+       return rc;
+}
+
+static int guest_get_irq_info(struct cxl_context *ctx, struct cxl_irq_info *info)
+{
+       return cxl_h_collect_int_info(ctx->afu->guest->handle, ctx->process_token, info);
+}
+
+static irqreturn_t guest_psl_irq(int irq, void *data)
+{
+       struct cxl_context *ctx = data;
+       struct cxl_irq_info irq_info;
+       int rc;
+
+       pr_devel("%d: received PSL interrupt %i\n", ctx->pe, irq);
+       rc = guest_get_irq_info(ctx, &irq_info);
+       if (rc) {
+               WARN(1, "Unable to get IRQ info: %i\n", rc);
+               return IRQ_HANDLED;
+       }
+
+       rc = cxl_irq(irq, ctx, &irq_info);
+       return rc;
+}
+
+static int afu_read_error_state(struct cxl_afu *afu, int *state_out)
+{
+       u64 state;
+       int rc = 0;
+
+       rc = cxl_h_read_error_state(afu->guest->handle, &state);
+       if (!rc) {
+               WARN_ON(state != H_STATE_NORMAL &&
+                       state != H_STATE_DISABLE &&
+                       state != H_STATE_TEMP_UNAVAILABLE &&
+                       state != H_STATE_PERM_UNAVAILABLE);
+               *state_out = state & 0xffffffff;
+       }
+       return rc;
+}
+
+static irqreturn_t guest_slice_irq_err(int irq, void *data)
+{
+       struct cxl_afu *afu = data;
+       int rc;
+       u64 serr;
+
+       WARN(irq, "CXL SLICE ERROR interrupt %i\n", irq);
+       rc = cxl_h_get_fn_error_interrupt(afu->guest->handle, &serr);
+       if (rc) {
+               dev_crit(&afu->dev, "Couldn't read PSL_SERR_An: %d\n", rc);
+               return IRQ_HANDLED;
+       }
+       dev_crit(&afu->dev, "PSL_SERR_An: 0x%.16llx\n", serr);
+
+       rc = cxl_h_ack_fn_error_interrupt(afu->guest->handle, serr);
+       if (rc)
+               dev_crit(&afu->dev, "Couldn't ack slice error interrupt: %d\n",
+                       rc);
+
+       return IRQ_HANDLED;
+}
+
+
+static int irq_alloc_range(struct cxl *adapter, int len, int *irq)
+{
+       int i, n;
+       struct irq_avail *cur;
+
+       for (i = 0; i < adapter->guest->irq_nranges; i++) {
+               cur = &adapter->guest->irq_avail[i];
+               n = bitmap_find_next_zero_area(cur->bitmap, cur->range,
+                                       0, len, 0);
+               if (n < cur->range) {
+                       bitmap_set(cur->bitmap, n, len);
+                       *irq = cur->offset + n;
+                       pr_devel("guest: allocate IRQs %#x->%#x\n",
+                               *irq, *irq + len - 1);
+
+                       return 0;
+               }
+       }
+       return -ENOSPC;
+}
+
+static int irq_free_range(struct cxl *adapter, int irq, int len)
+{
+       int i, n;
+       struct irq_avail *cur;
+
+       if (len == 0)
+               return -ENOENT;
+
+       for (i = 0; i < adapter->guest->irq_nranges; i++) {
+               cur = &adapter->guest->irq_avail[i];
+               if (irq >= cur->offset &&
+                       (irq + len) <= (cur->offset + cur->range)) {
+                       n = irq - cur->offset;
+                       bitmap_clear(cur->bitmap, n, len);
+                       pr_devel("guest: release IRQs %#x->%#x\n",
+                               irq, irq + len - 1);
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+
+static int guest_reset(struct cxl *adapter)
+{
+       struct cxl_afu *afu = NULL;
+       int i, rc;
+
+       pr_devel("Adapter reset request\n");
+       for (i = 0; i < adapter->slices; i++) {
+               if ((afu = adapter->afu[i])) {
+                       pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT,
+                                       pci_channel_io_frozen);
+                       cxl_context_detach_all(afu);
+               }
+       }
+
+       rc = cxl_h_reset_adapter(adapter->guest->handle);
+       for (i = 0; i < adapter->slices; i++) {
+               if (!rc && (afu = adapter->afu[i])) {
+                       pci_error_handlers(afu, CXL_SLOT_RESET_EVENT,
+                                       pci_channel_io_normal);
+                       pci_error_handlers(afu, CXL_RESUME_EVENT, 0);
+               }
+       }
+       return rc;
+}
+
+static int guest_alloc_one_irq(struct cxl *adapter)
+{
+       int irq;
+
+       spin_lock(&adapter->guest->irq_alloc_lock);
+       if (irq_alloc_range(adapter, 1, &irq))
+               irq = -ENOSPC;
+       spin_unlock(&adapter->guest->irq_alloc_lock);
+       return irq;
+}
+
+static void guest_release_one_irq(struct cxl *adapter, int irq)
+{
+       spin_lock(&adapter->guest->irq_alloc_lock);
+       irq_free_range(adapter, irq, 1);
+       spin_unlock(&adapter->guest->irq_alloc_lock);
+}
+
+static int guest_alloc_irq_ranges(struct cxl_irq_ranges *irqs,
+                               struct cxl *adapter, unsigned int num)
+{
+       int i, try, irq;
+
+       memset(irqs, 0, sizeof(struct cxl_irq_ranges));
+
+       spin_lock(&adapter->guest->irq_alloc_lock);
+       for (i = 0; i < CXL_IRQ_RANGES && num; i++) {
+               try = num;
+               while (try) {
+                       if (irq_alloc_range(adapter, try, &irq) == 0)
+                               break;
+                       try /= 2;
+               }
+               if (!try)
+                       goto error;
+               irqs->offset[i] = irq;
+               irqs->range[i] = try;
+               num -= try;
+       }
+       if (num)
+               goto error;
+       spin_unlock(&adapter->guest->irq_alloc_lock);
+       return 0;
+
+error:
+       for (i = 0; i < CXL_IRQ_RANGES; i++)
+               irq_free_range(adapter, irqs->offset[i], irqs->range[i]);
+       spin_unlock(&adapter->guest->irq_alloc_lock);
+       return -ENOSPC;
+}
+
+static void guest_release_irq_ranges(struct cxl_irq_ranges *irqs,
+                               struct cxl *adapter)
+{
+       int i;
+
+       spin_lock(&adapter->guest->irq_alloc_lock);
+       for (i = 0; i < CXL_IRQ_RANGES; i++)
+               irq_free_range(adapter, irqs->offset[i], irqs->range[i]);
+       spin_unlock(&adapter->guest->irq_alloc_lock);
+}
+
+static int guest_register_serr_irq(struct cxl_afu *afu)
+{
+       afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
+                                     dev_name(&afu->dev));
+       if (!afu->err_irq_name)
+               return -ENOMEM;
+
+       if (!(afu->serr_virq = cxl_map_irq(afu->adapter, afu->serr_hwirq,
+                                guest_slice_irq_err, afu, afu->err_irq_name))) {
+               kfree(afu->err_irq_name);
+               afu->err_irq_name = NULL;
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void guest_release_serr_irq(struct cxl_afu *afu)
+{
+       cxl_unmap_irq(afu->serr_virq, afu);
+       cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
+       kfree(afu->err_irq_name);
+}
+
+static int guest_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask)
+{
+       return cxl_h_control_faults(ctx->afu->guest->handle, ctx->process_token,
+                               tfc >> 32, (psl_reset_mask != 0));
+}
+
+static void disable_afu_irqs(struct cxl_context *ctx)
+{
+       irq_hw_number_t hwirq;
+       unsigned int virq;
+       int r, i;
+
+       pr_devel("Disabling AFU(%d) interrupts\n", ctx->afu->slice);
+       for (r = 0; r < CXL_IRQ_RANGES; r++) {
+               hwirq = ctx->irqs.offset[r];
+               for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
+                       virq = irq_find_mapping(NULL, hwirq);
+                       disable_irq(virq);
+               }
+       }
+}
+
+static void enable_afu_irqs(struct cxl_context *ctx)
+{
+       irq_hw_number_t hwirq;
+       unsigned int virq;
+       int r, i;
+
+       pr_devel("Enabling AFU(%d) interrupts\n", ctx->afu->slice);
+       for (r = 0; r < CXL_IRQ_RANGES; r++) {
+               hwirq = ctx->irqs.offset[r];
+               for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
+                       virq = irq_find_mapping(NULL, hwirq);
+                       enable_irq(virq);
+               }
+       }
+}
+
+static int _guest_afu_cr_readXX(int sz, struct cxl_afu *afu, int cr_idx,
+                       u64 offset, u64 *val)
+{
+       unsigned long cr;
+       char c;
+       int rc = 0;
+
+       if (afu->crs_len < sz)
+               return -ENOENT;
+
+       if (unlikely(offset >= afu->crs_len))
+               return -ERANGE;
+
+       cr = get_zeroed_page(GFP_KERNEL);
+       if (!cr)
+               return -ENOMEM;
+
+       rc = cxl_h_get_config(afu->guest->handle, cr_idx, offset,
+                       virt_to_phys((void *)cr), sz);
+       if (rc)
+               goto err;
+
+       switch (sz) {
+       case 1:
+               c = *((char *) cr);
+               *val = c;
+               break;
+       case 2:
+               *val = in_le16((u16 *)cr);
+               break;
+       case 4:
+               *val = in_le32((unsigned *)cr);
+               break;
+       case 8:
+               *val = in_le64((u64 *)cr);
+               break;
+       default:
+               WARN_ON(1);
+       }
+err:
+       free_page(cr);
+       return rc;
+}
+
+static int guest_afu_cr_read32(struct cxl_afu *afu, int cr_idx, u64 offset,
+                       u32 *out)
+{
+       int rc;
+       u64 val;
+
+       rc = _guest_afu_cr_readXX(4, afu, cr_idx, offset, &val);
+       if (!rc)
+               *out = (u32) val;
+       return rc;
+}
+
+static int guest_afu_cr_read16(struct cxl_afu *afu, int cr_idx, u64 offset,
+                       u16 *out)
+{
+       int rc;
+       u64 val;
+
+       rc = _guest_afu_cr_readXX(2, afu, cr_idx, offset, &val);
+       if (!rc)
+               *out = (u16) val;
+       return rc;
+}
+
+static int guest_afu_cr_read8(struct cxl_afu *afu, int cr_idx, u64 offset,
+                       u8 *out)
+{
+       int rc;
+       u64 val;
+
+       rc = _guest_afu_cr_readXX(1, afu, cr_idx, offset, &val);
+       if (!rc)
+               *out = (u8) val;
+       return rc;
+}
+
+static int guest_afu_cr_read64(struct cxl_afu *afu, int cr_idx, u64 offset,
+                       u64 *out)
+{
+       return _guest_afu_cr_readXX(8, afu, cr_idx, offset, out);
+}
+
+static int guest_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in)
+{
+       /* config record is not writable from guest */
+       return -EPERM;
+}
+
+static int guest_afu_cr_write16(struct cxl_afu *afu, int cr, u64 off, u16 in)
+{
+       /* config record is not writable from guest */
+       return -EPERM;
+}
+
+static int guest_afu_cr_write8(struct cxl_afu *afu, int cr, u64 off, u8 in)
+{
+       /* config record is not writable from guest */
+       return -EPERM;
+}
+
+static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr)
+{
+       struct cxl_process_element_hcall *elem;
+       struct cxl *adapter = ctx->afu->adapter;
+       const struct cred *cred;
+       u32 pid, idx;
+       int rc, r, i;
+       u64 mmio_addr, mmio_size;
+       __be64 flags = 0;
+
+       /* Must be 8 byte aligned and cannot cross a 4096 byte boundary */
+       if (!(elem = (struct cxl_process_element_hcall *)
+                       get_zeroed_page(GFP_KERNEL)))
+               return -ENOMEM;
+
+       elem->version = cpu_to_be64(CXL_PROCESS_ELEMENT_VERSION);
+       if (ctx->kernel) {
+               pid = 0;
+               flags |= CXL_PE_TRANSLATION_ENABLED;
+               flags |= CXL_PE_PRIVILEGED_PROCESS;
+               if (mfmsr() & MSR_SF)
+                       flags |= CXL_PE_64_BIT;
+       } else {
+               pid = current->pid;
+               flags |= CXL_PE_PROBLEM_STATE;
+               flags |= CXL_PE_TRANSLATION_ENABLED;
+               if (!test_tsk_thread_flag(current, TIF_32BIT))
+                       flags |= CXL_PE_64_BIT;
+               cred = get_current_cred();
+               if (uid_eq(cred->euid, GLOBAL_ROOT_UID))
+                       flags |= CXL_PE_PRIVILEGED_PROCESS;
+               put_cred(cred);
+       }
+       elem->flags         = cpu_to_be64(flags);
+       elem->common.tid    = cpu_to_be32(0); /* Unused */
+       elem->common.pid    = cpu_to_be32(pid);
+       elem->common.csrp   = cpu_to_be64(0); /* disable */
+       elem->common.aurp0  = cpu_to_be64(0); /* disable */
+       elem->common.aurp1  = cpu_to_be64(0); /* disable */
+
+       cxl_prefault(ctx, wed);
+
+       elem->common.sstp0  = cpu_to_be64(ctx->sstp0);
+       elem->common.sstp1  = cpu_to_be64(ctx->sstp1);
+       for (r = 0; r < CXL_IRQ_RANGES; r++) {
+               for (i = 0; i < ctx->irqs.range[r]; i++) {
+                       if (r == 0 && i == 0) {
+                               elem->pslVirtualIsn = cpu_to_be32(ctx->irqs.offset[0]);
+                       } else {
+                               idx = ctx->irqs.offset[r] + i - adapter->guest->irq_base_offset;
+                               elem->applicationVirtualIsnBitmap[idx / 8] |= 0x80 >> (idx % 8);
+                       }
+               }
+       }
+       elem->common.amr = cpu_to_be64(amr);
+       elem->common.wed = cpu_to_be64(wed);
+
+       disable_afu_irqs(ctx);
+
+       rc = cxl_h_attach_process(ctx->afu->guest->handle, elem,
+                               &ctx->process_token, &mmio_addr, &mmio_size);
+       if (rc == H_SUCCESS) {
+               if (ctx->master || !ctx->afu->pp_psa) {
+                       ctx->psn_phys = ctx->afu->psn_phys;
+                       ctx->psn_size = ctx->afu->adapter->ps_size;
+               } else {
+                       ctx->psn_phys = mmio_addr;
+                       ctx->psn_size = mmio_size;
+               }
+               if (ctx->afu->pp_psa && mmio_size &&
+                       ctx->afu->pp_size == 0) {
+                       /*
+                        * There's no property in the device tree to read the
+                        * pp_size. We only find out at the 1st attach.
+                        * Compared to bare-metal, it is too late and we
+                        * should really lock here. However, on powerVM,
+                        * pp_size is really only used to display in /sys.
+                        * Being discussed with pHyp for their next release.
+                        */
+                       ctx->afu->pp_size = mmio_size;
+               }
+               /* from PAPR: process element is bytes 4-7 of process token */
+               ctx->external_pe = ctx->process_token & 0xFFFFFFFF;
+               pr_devel("CXL pe=%i is known as %i for pHyp, mmio_size=%#llx",
+                       ctx->pe, ctx->external_pe, ctx->psn_size);
+               ctx->pe_inserted = true;
+               enable_afu_irqs(ctx);
+       }
+
+       free_page((u64)elem);
+       return rc;
+}
+
+static int guest_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr)
+{
+       pr_devel("in %s\n", __func__);
+
+       ctx->kernel = kernel;
+       if (ctx->afu->current_mode == CXL_MODE_DIRECTED)
+               return attach_afu_directed(ctx, wed, amr);
+
+       /* dedicated mode not supported on FW840 */
+
+       return -EINVAL;
+}
+
+static int detach_afu_directed(struct cxl_context *ctx)
+{
+       if (!ctx->pe_inserted)
+               return 0;
+       if (cxl_h_detach_process(ctx->afu->guest->handle, ctx->process_token))
+               return -1;
+       return 0;
+}
+
+static int guest_detach_process(struct cxl_context *ctx)
+{
+       pr_devel("in %s\n", __func__);
+       trace_cxl_detach(ctx);
+
+       if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
+               return -EIO;
+
+       if (ctx->afu->current_mode == CXL_MODE_DIRECTED)
+               return detach_afu_directed(ctx);
+
+       return -EINVAL;
+}
+
+static void guest_release_afu(struct device *dev)
+{
+       struct cxl_afu *afu = to_cxl_afu(dev);
+
+       pr_devel("%s\n", __func__);
+
+       idr_destroy(&afu->contexts_idr);
+
+       kfree(afu->guest);
+       kfree(afu);
+}
+
+ssize_t cxl_guest_read_afu_vpd(struct cxl_afu *afu, void *buf, size_t len)
+{
+       return guest_collect_vpd(NULL, afu, buf, len);
+}
+
+#define ERR_BUFF_MAX_COPY_SIZE PAGE_SIZE
+static ssize_t guest_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
+                                       loff_t off, size_t count)
+{
+       void *tbuf = NULL;
+       int rc = 0;
+
+       tbuf = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!tbuf)
+               return -ENOMEM;
+
+       rc = cxl_h_get_afu_err(afu->guest->handle,
+                              off & 0x7,
+                              virt_to_phys(tbuf),
+                              count);
+       if (rc)
+               goto err;
+
+       if (count > ERR_BUFF_MAX_COPY_SIZE)
+               count = ERR_BUFF_MAX_COPY_SIZE - (off & 0x7);
+       memcpy(buf, tbuf, count);
+err:
+       free_page((u64)tbuf);
+
+       return rc;
+}
+
+static int guest_afu_check_and_enable(struct cxl_afu *afu)
+{
+       return 0;
+}
+
+static bool guest_support_attributes(const char *attr_name,
+                                    enum cxl_attrs type)
+{
+       switch (type) {
+       case CXL_ADAPTER_ATTRS:
+               if ((strcmp(attr_name, "base_image") == 0) ||
+                       (strcmp(attr_name, "load_image_on_perst") == 0) ||
+                       (strcmp(attr_name, "perst_reloads_same_image") == 0) ||
+                       (strcmp(attr_name, "image_loaded") == 0))
+                       return false;
+               break;
+       case CXL_AFU_MASTER_ATTRS:
+               if ((strcmp(attr_name, "pp_mmio_off") == 0))
+                       return false;
+               break;
+       case CXL_AFU_ATTRS:
+               break;
+       default:
+               break;
+       }
+
+       return true;
+}
+
+static int activate_afu_directed(struct cxl_afu *afu)
+{
+       int rc;
+
+       dev_info(&afu->dev, "Activating AFU(%d) directed mode\n", afu->slice);
+
+       afu->current_mode = CXL_MODE_DIRECTED;
+
+       afu->num_procs = afu->max_procs_virtualised;
+
+       if ((rc = cxl_chardev_m_afu_add(afu)))
+               return rc;
+
+       if ((rc = cxl_sysfs_afu_m_add(afu)))
+               goto err;
+
+       if ((rc = cxl_chardev_s_afu_add(afu)))
+               goto err1;
+
+       return 0;
+err1:
+       cxl_sysfs_afu_m_remove(afu);
+err:
+       cxl_chardev_afu_remove(afu);
+       return rc;
+}
+
+static int guest_afu_activate_mode(struct cxl_afu *afu, int mode)
+{
+       if (!mode)
+               return 0;
+       if (!(mode & afu->modes_supported))
+               return -EINVAL;
+
+       if (mode == CXL_MODE_DIRECTED)
+               return activate_afu_directed(afu);
+
+       if (mode == CXL_MODE_DEDICATED)
+               dev_err(&afu->dev, "Dedicated mode not supported\n");
+
+       return -EINVAL;
+}
+
+static int deactivate_afu_directed(struct cxl_afu *afu)
+{
+       dev_info(&afu->dev, "Deactivating AFU(%d) directed mode\n", afu->slice);
+
+       afu->current_mode = 0;
+       afu->num_procs = 0;
+
+       cxl_sysfs_afu_m_remove(afu);
+       cxl_chardev_afu_remove(afu);
+
+       cxl_ops->afu_reset(afu);
+
+       return 0;
+}
+
+static int guest_afu_deactivate_mode(struct cxl_afu *afu, int mode)
+{
+       if (!mode)
+               return 0;
+       if (!(mode & afu->modes_supported))
+               return -EINVAL;
+
+       if (mode == CXL_MODE_DIRECTED)
+               return deactivate_afu_directed(afu);
+       return 0;
+}
+
+static int guest_afu_reset(struct cxl_afu *afu)
+{
+       pr_devel("AFU(%d) reset request\n", afu->slice);
+       return cxl_h_reset_afu(afu->guest->handle);
+}
+
+static int guest_map_slice_regs(struct cxl_afu *afu)
+{
+       if (!(afu->p2n_mmio = ioremap(afu->guest->p2n_phys, afu->guest->p2n_size))) {
+               dev_err(&afu->dev, "Error mapping AFU(%d) MMIO regions\n",
+                       afu->slice);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void guest_unmap_slice_regs(struct cxl_afu *afu)
+{
+       if (afu->p2n_mmio)
+               iounmap(afu->p2n_mmio);
+}
+
+static int afu_update_state(struct cxl_afu *afu)
+{
+       int rc, cur_state;
+
+       rc = afu_read_error_state(afu, &cur_state);
+       if (rc)
+               return rc;
+
+       if (afu->guest->previous_state == cur_state)
+               return 0;
+
+       pr_devel("AFU(%d) update state to %#x\n", afu->slice, cur_state);
+
+       switch (cur_state) {
+       case H_STATE_NORMAL:
+               afu->guest->previous_state = cur_state;
+               rc = 1;
+               break;
+
+       case H_STATE_DISABLE:
+               pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT,
+                               pci_channel_io_frozen);
+
+               cxl_context_detach_all(afu);
+               if ((rc = cxl_ops->afu_reset(afu)))
+                       pr_devel("reset hcall failed %d\n", rc);
+
+               rc = afu_read_error_state(afu, &cur_state);
+               if (!rc && cur_state == H_STATE_NORMAL) {
+                       pci_error_handlers(afu, CXL_SLOT_RESET_EVENT,
+                                       pci_channel_io_normal);
+                       pci_error_handlers(afu, CXL_RESUME_EVENT, 0);
+                       rc = 1;
+               }
+               afu->guest->previous_state = 0;
+               break;
+
+       case H_STATE_TEMP_UNAVAILABLE:
+               afu->guest->previous_state = cur_state;
+               break;
+
+       case H_STATE_PERM_UNAVAILABLE:
+               dev_err(&afu->dev, "AFU is in permanent error state\n");
+               pci_error_handlers(afu, CXL_ERROR_DETECTED_EVENT,
+                               pci_channel_io_perm_failure);
+               afu->guest->previous_state = cur_state;
+               break;
+
+       default:
+               pr_err("Unexpected AFU(%d) error state: %#x\n",
+                      afu->slice, cur_state);
+               return -EINVAL;
+       }
+
+       return rc;
+}
+
+static int afu_do_recovery(struct cxl_afu *afu)
+{
+       int rc;
+
+       /* many threads can arrive here, in case of detach_all for example.
+        * Only one needs to drive the recovery
+        */
+       if (mutex_trylock(&afu->guest->recovery_lock)) {
+               rc = afu_update_state(afu);
+               mutex_unlock(&afu->guest->recovery_lock);
+               return rc;
+       }
+       return 0;
+}
+
+static bool guest_link_ok(struct cxl *cxl, struct cxl_afu *afu)
+{
+       int state;
+
+       if (afu) {
+               if (afu_read_error_state(afu, &state) ||
+                       state != H_STATE_NORMAL) {
+                       if (afu_do_recovery(afu) > 0) {
+                               /* check again in case we've just fixed it */
+                               if (!afu_read_error_state(afu, &state) &&
+                                       state == H_STATE_NORMAL)
+                                       return true;
+                       }
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int afu_properties_look_ok(struct cxl_afu *afu)
+{
+       if (afu->pp_irqs < 0) {
+               dev_err(&afu->dev, "Unexpected per-process minimum interrupt value\n");
+               return -EINVAL;
+       }
+
+       if (afu->max_procs_virtualised < 1) {
+               dev_err(&afu->dev, "Unexpected max number of processes virtualised value\n");
+               return -EINVAL;
+       }
+
+       if (afu->crs_len < 0) {
+               dev_err(&afu->dev, "Unexpected configuration record size value\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_np)
+{
+       struct cxl_afu *afu;
+       bool free = true;
+       int rc;
+
+       pr_devel("in %s - AFU(%d)\n", __func__, slice);
+       if (!(afu = cxl_alloc_afu(adapter, slice)))
+               return -ENOMEM;
+
+       if (!(afu->guest = kzalloc(sizeof(struct cxl_afu_guest), GFP_KERNEL))) {
+               kfree(afu);
+               return -ENOMEM;
+       }
+
+       mutex_init(&afu->guest->recovery_lock);
+
+       if ((rc = dev_set_name(&afu->dev, "afu%i.%i",
+                                         adapter->adapter_num,
+                                         slice)))
+               goto err1;
+
+       adapter->slices++;
+
+       if ((rc = cxl_of_read_afu_handle(afu, afu_np)))
+               goto err1;
+
+       if ((rc = cxl_ops->afu_reset(afu)))
+               goto err1;
+
+       if ((rc = cxl_of_read_afu_properties(afu, afu_np)))
+               goto err1;
+
+       if ((rc = afu_properties_look_ok(afu)))
+               goto err1;
+
+       if ((rc = guest_map_slice_regs(afu)))
+               goto err1;
+
+       if ((rc = guest_register_serr_irq(afu)))
+               goto err2;
+
+       /*
+        * After we call this function we must not free the afu directly, even
+        * if it returns an error!
+        */
+       if ((rc = cxl_register_afu(afu)))
+               goto err_put1;
+
+       if ((rc = cxl_sysfs_afu_add(afu)))
+               goto err_put1;
+
+       /*
+        * pHyp doesn't expose the programming models supported by the
+        * AFU. pHyp currently only supports directed mode. If it adds
+        * dedicated mode later, this version of cxl has no way to
+        * detect it. So we'll initialize the driver, but the first
+        * attach will fail.
+        * Being discussed with pHyp to do better (likely new property)
+        */
+       if (afu->max_procs_virtualised == 1)
+               afu->modes_supported = CXL_MODE_DEDICATED;
+       else
+               afu->modes_supported = CXL_MODE_DIRECTED;
+
+       if ((rc = cxl_afu_select_best_mode(afu)))
+               goto err_put2;
+
+       adapter->afu[afu->slice] = afu;
+
+       afu->enabled = true;
+
+       if ((rc = cxl_pci_vphb_add(afu)))
+               dev_info(&afu->dev, "Can't register vPHB\n");
+
+       return 0;
+
+err_put2:
+       cxl_sysfs_afu_remove(afu);
+err_put1:
+       device_unregister(&afu->dev);
+       free = false;
+       guest_release_serr_irq(afu);
+err2:
+       guest_unmap_slice_regs(afu);
+err1:
+       if (free) {
+               kfree(afu->guest);
+               kfree(afu);
+       }
+       return rc;
+}
+
+void cxl_guest_remove_afu(struct cxl_afu *afu)
+{
+       pr_devel("in %s - AFU(%d)\n", __func__, afu->slice);
+
+       if (!afu)
+               return;
+
+       cxl_pci_vphb_remove(afu);
+       cxl_sysfs_afu_remove(afu);
+
+       spin_lock(&afu->adapter->afu_list_lock);
+       afu->adapter->afu[afu->slice] = NULL;
+       spin_unlock(&afu->adapter->afu_list_lock);
+
+       cxl_context_detach_all(afu);
+       cxl_ops->afu_deactivate_mode(afu, afu->current_mode);
+       guest_release_serr_irq(afu);
+       guest_unmap_slice_regs(afu);
+
+       device_unregister(&afu->dev);
+}
+
+static void free_adapter(struct cxl *adapter)
+{
+       struct irq_avail *cur;
+       int i;
+
+       if (adapter->guest->irq_avail) {
+               for (i = 0; i < adapter->guest->irq_nranges; i++) {
+                       cur = &adapter->guest->irq_avail[i];
+                       kfree(cur->bitmap);
+               }
+               kfree(adapter->guest->irq_avail);
+       }
+       kfree(adapter->guest->status);
+       cxl_remove_adapter_nr(adapter);
+       kfree(adapter->guest);
+       kfree(adapter);
+}
+
+static int properties_look_ok(struct cxl *adapter)
+{
+       /* The absence of this property means that the operational
+        * status is unknown or okay
+        */
+       if (strlen(adapter->guest->status) &&
+           strcmp(adapter->guest->status, "okay")) {
+               pr_err("ABORTING:Bad operational status of the device\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+ssize_t cxl_guest_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len)
+{
+       return guest_collect_vpd(adapter, NULL, buf, len);
+}
+
+void cxl_guest_remove_adapter(struct cxl *adapter)
+{
+       pr_devel("in %s\n", __func__);
+
+       cxl_sysfs_adapter_remove(adapter);
+
+       cxl_guest_remove_chardev(adapter);
+       device_unregister(&adapter->dev);
+}
+
+static void release_adapter(struct device *dev)
+{
+       free_adapter(to_cxl_adapter(dev));
+}
+
+struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_device *pdev)
+{
+       struct cxl *adapter;
+       bool free = true;
+       int rc;
+
+       if (!(adapter = cxl_alloc_adapter()))
+               return ERR_PTR(-ENOMEM);
+
+       if (!(adapter->guest = kzalloc(sizeof(struct cxl_guest), GFP_KERNEL))) {
+               free_adapter(adapter);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       adapter->slices = 0;
+       adapter->guest->pdev = pdev;
+       adapter->dev.parent = &pdev->dev;
+       adapter->dev.release = release_adapter;
+       dev_set_drvdata(&pdev->dev, adapter);
+
+       if ((rc = cxl_of_read_adapter_handle(adapter, np)))
+               goto err1;
+
+       if ((rc = cxl_of_read_adapter_properties(adapter, np)))
+               goto err1;
+
+       if ((rc = properties_look_ok(adapter)))
+               goto err1;
+
+       if ((rc = cxl_guest_add_chardev(adapter)))
+               goto err1;
+
+       /*
+        * After we call this function we must not free the adapter directly,
+        * even if it returns an error!
+        */
+       if ((rc = cxl_register_adapter(adapter)))
+               goto err_put1;
+
+       if ((rc = cxl_sysfs_adapter_add(adapter)))
+               goto err_put1;
+
+       return adapter;
+
+err_put1:
+       device_unregister(&adapter->dev);
+       free = false;
+       cxl_guest_remove_chardev(adapter);
+err1:
+       if (free)
+               free_adapter(adapter);
+       return ERR_PTR(rc);
+}
+
+void cxl_guest_reload_module(struct cxl *adapter)
+{
+       struct platform_device *pdev;
+
+       pdev = adapter->guest->pdev;
+       cxl_guest_remove_adapter(adapter);
+
+       cxl_of_probe(pdev);
+}
+
+const struct cxl_backend_ops cxl_guest_ops = {
+       .module = THIS_MODULE,
+       .adapter_reset = guest_reset,
+       .alloc_one_irq = guest_alloc_one_irq,
+       .release_one_irq = guest_release_one_irq,
+       .alloc_irq_ranges = guest_alloc_irq_ranges,
+       .release_irq_ranges = guest_release_irq_ranges,
+       .setup_irq = NULL,
+       .handle_psl_slice_error = guest_handle_psl_slice_error,
+       .psl_interrupt = guest_psl_irq,
+       .ack_irq = guest_ack_irq,
+       .attach_process = guest_attach_process,
+       .detach_process = guest_detach_process,
+       .support_attributes = guest_support_attributes,
+       .link_ok = guest_link_ok,
+       .release_afu = guest_release_afu,
+       .afu_read_err_buffer = guest_afu_read_err_buffer,
+       .afu_check_and_enable = guest_afu_check_and_enable,
+       .afu_activate_mode = guest_afu_activate_mode,
+       .afu_deactivate_mode = guest_afu_deactivate_mode,
+       .afu_reset = guest_afu_reset,
+       .afu_cr_read8 = guest_afu_cr_read8,
+       .afu_cr_read16 = guest_afu_cr_read16,
+       .afu_cr_read32 = guest_afu_cr_read32,
+       .afu_cr_read64 = guest_afu_cr_read64,
+       .afu_cr_write8 = guest_afu_cr_write8,
+       .afu_cr_write16 = guest_afu_cr_write16,
+       .afu_cr_write32 = guest_afu_cr_write32,
+       .read_adapter_vpd = cxl_guest_read_adapter_vpd,
+};
diff --git a/drivers/misc/cxl/hcalls.c b/drivers/misc/cxl/hcalls.c
new file mode 100644 (file)
index 0000000..d6d11f4
--- /dev/null
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2015 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include "hcalls.h"
+#include "trace.h"
+
+#define CXL_HCALL_TIMEOUT 60000
+#define CXL_HCALL_TIMEOUT_DOWNLOAD 120000
+
+#define H_ATTACH_CA_PROCESS    0x344
+#define H_CONTROL_CA_FUNCTION  0x348
+#define H_DETACH_CA_PROCESS    0x34C
+#define H_COLLECT_CA_INT_INFO  0x350
+#define H_CONTROL_CA_FAULTS    0x354
+#define H_DOWNLOAD_CA_FUNCTION 0x35C
+#define H_DOWNLOAD_CA_FACILITY 0x364
+#define H_CONTROL_CA_FACILITY  0x368
+
+#define H_CONTROL_CA_FUNCTION_RESET                   1 /* perform a reset */
+#define H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS         2 /* suspend a process from being executed */
+#define H_CONTROL_CA_FUNCTION_RESUME_PROCESS          3 /* resume a process to be executed */
+#define H_CONTROL_CA_FUNCTION_READ_ERR_STATE          4 /* read the error state */
+#define H_CONTROL_CA_FUNCTION_GET_AFU_ERR             5 /* collect the AFU error buffer */
+#define H_CONTROL_CA_FUNCTION_GET_CONFIG              6 /* collect configuration record */
+#define H_CONTROL_CA_FUNCTION_GET_DOWNLOAD_STATE      7 /* query to return download status */
+#define H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS       8 /* terminate the process before completion */
+#define H_CONTROL_CA_FUNCTION_COLLECT_VPD             9 /* collect VPD */
+#define H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT   11 /* read the function-wide error data based on an interrupt */
+#define H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT   12 /* acknowledge function-wide error data based on an interrupt */
+#define H_CONTROL_CA_FUNCTION_GET_ERROR_LOG          13 /* retrieve the Platform Log ID (PLID) of an error log */
+
+#define H_CONTROL_CA_FAULTS_RESPOND_PSL         1
+#define H_CONTROL_CA_FAULTS_RESPOND_AFU         2
+
+#define H_CONTROL_CA_FACILITY_RESET             1 /* perform a reset */
+#define H_CONTROL_CA_FACILITY_COLLECT_VPD       2 /* collect VPD */
+
+#define H_DOWNLOAD_CA_FACILITY_DOWNLOAD         1 /* download adapter image */
+#define H_DOWNLOAD_CA_FACILITY_VALIDATE         2 /* validate adapter image */
+
+
+#define _CXL_LOOP_HCALL(call, rc, retbuf, fn, ...)                     \
+       {                                                               \
+               unsigned int delay, total_delay = 0;                    \
+               u64 token = 0;                                          \
+                                                                       \
+               memset(retbuf, 0, sizeof(retbuf));                      \
+               while (1) {                                             \
+                       rc = call(fn, retbuf, __VA_ARGS__, token);      \
+                       token = retbuf[0];                              \
+                       if (rc != H_BUSY && !H_IS_LONG_BUSY(rc))        \
+                               break;                                  \
+                                                                       \
+                       if (rc == H_BUSY)                               \
+                               delay = 10;                             \
+                       else                                            \
+                               delay = get_longbusy_msecs(rc);         \
+                                                                       \
+                       total_delay += delay;                           \
+                       if (total_delay > CXL_HCALL_TIMEOUT) {          \
+                               WARN(1, "Warning: Giving up waiting for CXL hcall " \
+                                       "%#x after %u msec\n", fn, total_delay); \
+                               rc = H_BUSY;                            \
+                               break;                                  \
+                       }                                               \
+                       msleep(delay);                                  \
+               }                                                       \
+       }
+#define CXL_H_WAIT_UNTIL_DONE(...)  _CXL_LOOP_HCALL(plpar_hcall, __VA_ARGS__)
+#define CXL_H9_WAIT_UNTIL_DONE(...) _CXL_LOOP_HCALL(plpar_hcall9, __VA_ARGS__)
+
+#define _PRINT_MSG(rc, format, ...)                                    \
+       {                                                               \
+               if ((rc != H_SUCCESS) && (rc != H_CONTINUE))            \
+                       pr_err(format, __VA_ARGS__);                    \
+               else                                                    \
+                       pr_devel(format, __VA_ARGS__);                  \
+       }                                                               \
+
+
+static char *afu_op_names[] = {
+       "UNKNOWN_OP",           /* 0 undefined */
+       "RESET",                /* 1 */
+       "SUSPEND_PROCESS",      /* 2 */
+       "RESUME_PROCESS",       /* 3 */
+       "READ_ERR_STATE",       /* 4 */
+       "GET_AFU_ERR",          /* 5 */
+       "GET_CONFIG",           /* 6 */
+       "GET_DOWNLOAD_STATE",   /* 7 */
+       "TERMINATE_PROCESS",    /* 8 */
+       "COLLECT_VPD",          /* 9 */
+       "UNKNOWN_OP",           /* 10 undefined */
+       "GET_FUNCTION_ERR_INT", /* 11 */
+       "ACK_FUNCTION_ERR_INT", /* 12 */
+       "GET_ERROR_LOG",        /* 13 */
+};
+
+static char *control_adapter_op_names[] = {
+       "UNKNOWN_OP",           /* 0 undefined */
+       "RESET",                /* 1 */
+       "COLLECT_VPD",          /* 2 */
+};
+
+static char *download_op_names[] = {
+       "UNKNOWN_OP",           /* 0 undefined */
+       "DOWNLOAD",             /* 1 */
+       "VALIDATE",             /* 2 */
+};
+
+static char *op_str(unsigned int op, char *name_array[], int array_len)
+{
+       if (op >= array_len)
+               return "UNKNOWN_OP";
+       return name_array[op];
+}
+
+#define OP_STR(op, name_array)      op_str(op, name_array, ARRAY_SIZE(name_array))
+
+#define OP_STR_AFU(op)              OP_STR(op, afu_op_names)
+#define OP_STR_CONTROL_ADAPTER(op)  OP_STR(op, control_adapter_op_names)
+#define OP_STR_DOWNLOAD_ADAPTER(op) OP_STR(op, download_op_names)
+
+
+long cxl_h_attach_process(u64 unit_address,
+                       struct cxl_process_element_hcall *element,
+                       u64 *process_token, u64 *mmio_addr, u64 *mmio_size)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       long rc;
+
+       CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_ATTACH_CA_PROCESS, unit_address, virt_to_phys(element));
+       _PRINT_MSG(rc, "cxl_h_attach_process(%#.16llx, %#.16lx): %li\n",
+               unit_address, virt_to_phys(element), rc);
+       trace_cxl_hcall_attach(unit_address, virt_to_phys(element), retbuf[0], retbuf[1], retbuf[2], rc);
+
+       pr_devel("token: 0x%.8lx mmio_addr: 0x%lx mmio_size: 0x%lx\nProcess Element Structure:\n",
+               retbuf[0], retbuf[1], retbuf[2]);
+       cxl_dump_debug_buffer(element, sizeof(*element));
+
+       switch (rc) {
+       case H_SUCCESS:       /* The process info is attached to the coherent platform function */
+               *process_token = retbuf[0];
+               if (mmio_addr)
+                       *mmio_addr = retbuf[1];
+               if (mmio_size)
+                       *mmio_size = retbuf[2];
+               return 0;
+       case H_PARAMETER:     /* An incorrect parameter was supplied. */
+       case H_FUNCTION:      /* The function is not supported. */
+               return -EINVAL;
+       case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
+       case H_RESOURCE:      /* The coherent platform function does not have enough additional resource to attach the process */
+       case H_HARDWARE:      /* A hardware event prevented the attach operation */
+       case H_STATE:         /* The coherent platform function is not in a valid state */
+       case H_BUSY:
+               return -EBUSY;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_detach_process - Detach a process element from a coherent
+ *                        platform function.
+ */
+long cxl_h_detach_process(u64 unit_address, u64 process_token)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       long rc;
+
+       CXL_H_WAIT_UNTIL_DONE(rc, retbuf, H_DETACH_CA_PROCESS, unit_address, process_token);
+       _PRINT_MSG(rc, "cxl_h_detach_process(%#.16llx, 0x%.8llx): %li\n", unit_address, process_token, rc);
+       trace_cxl_hcall_detach(unit_address, process_token, rc);
+
+       switch (rc) {
+       case H_SUCCESS:       /* The process was detached from the coherent platform function */
+               return 0;
+       case H_PARAMETER:     /* An incorrect parameter was supplied. */
+               return -EINVAL;
+       case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
+       case H_RESOURCE:      /* The function has page table mappings for MMIO */
+       case H_HARDWARE:      /* A hardware event prevented the detach operation */
+       case H_STATE:         /* The coherent platform function is not in a valid state */
+       case H_BUSY:
+               return -EBUSY;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_control_function - This H_CONTROL_CA_FUNCTION hypervisor call allows
+ *                          the partition to manipulate or query
+ *                          certain coherent platform function behaviors.
+ */
+static long cxl_h_control_function(u64 unit_address, u64 op,
+                                  u64 p1, u64 p2, u64 p3, u64 p4, u64 *out)
+{
+       unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+       long rc;
+
+       CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FUNCTION, unit_address, op, p1, p2, p3, p4);
+       _PRINT_MSG(rc, "cxl_h_control_function(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n",
+               unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc);
+       trace_cxl_hcall_control_function(unit_address, OP_STR_AFU(op), p1, p2, p3, p4, retbuf[0], rc);
+
+       switch (rc) {
+       case H_SUCCESS:       /* The operation is completed for the coherent platform function */
+               if ((op == H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT ||
+                    op == H_CONTROL_CA_FUNCTION_READ_ERR_STATE ||
+                    op == H_CONTROL_CA_FUNCTION_COLLECT_VPD))
+                       *out = retbuf[0];
+               return 0;
+       case H_PARAMETER:     /* An incorrect parameter was supplied. */
+       case H_FUNCTION:      /* The function is not supported. */
+       case H_NOT_FOUND:     /* The operation supplied was not valid */
+       case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */
+       case H_SG_LIST:       /* An block list entry was invalid */
+               return -EINVAL;
+       case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
+       case H_RESOURCE:      /* The function has page table mappings for MMIO */
+       case H_HARDWARE:      /* A hardware event prevented the attach operation */
+       case H_STATE:         /* The coherent platform function is not in a valid state */
+       case H_BUSY:
+               return -EBUSY;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_reset_afu - Perform a reset to the coherent platform function.
+ */
+long cxl_h_reset_afu(u64 unit_address)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_RESET,
+                               0, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_suspend_process - Suspend a process from being executed
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_suspend_process(u64 unit_address, u64 process_token)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_SUSPEND_PROCESS,
+                               process_token, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_resume_process - Resume a process to be executed
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_resume_process(u64 unit_address, u64 process_token)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_RESUME_PROCESS,
+                               process_token, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_read_error_state - Checks the error state of the coherent
+ *                          platform function.
+ * R4 contains the error state
+ */
+long cxl_h_read_error_state(u64 unit_address, u64 *state)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_READ_ERR_STATE,
+                               0, 0, 0, 0,
+                               state);
+}
+
+/**
+ * cxl_h_get_afu_err - collect the AFU error buffer
+ * Parameter1 = byte offset into error buffer to retrieve, valid values
+ *              are between 0 and (ibm,error-buffer-size - 1)
+ * Parameter2 = 4K aligned real address of error buffer, to be filled in
+ * Parameter3 = length of error buffer, valid values are 4K or less
+ */
+long cxl_h_get_afu_err(u64 unit_address, u64 offset,
+               u64 buf_address, u64 len)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_GET_AFU_ERR,
+                               offset, buf_address, len, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_get_config - collect configuration record for the
+ *                    coherent platform function
+ * Parameter1 = # of configuration record to retrieve, valid values are
+ *              between 0 and (ibm,#config-records - 1)
+ * Parameter2 = byte offset into configuration record to retrieve,
+ *              valid values are between 0 and (ibm,config-record-size - 1)
+ * Parameter3 = 4K aligned real address of configuration record buffer,
+ *              to be filled in
+ * Parameter4 = length of configuration buffer, valid values are 4K or less
+ */
+long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset,
+               u64 buf_address, u64 len)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_GET_CONFIG,
+                               cr_num, offset, buf_address, len,
+                               NULL);
+}
+
+/**
+ * cxl_h_terminate_process - Terminate the process before completion
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_terminate_process(u64 unit_address, u64 process_token)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_TERMINATE_PROCESS,
+                               process_token, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
+ * Parameter1 = # of VPD record to retrieve, valid values are between 0
+ *              and (ibm,#config-records - 1).
+ * Parameter2 = 4K naturally aligned real buffer containing block
+ *              list entries
+ * Parameter3 = number of block list entries in the block list, valid
+ *              values are between 0 and 256
+ */
+long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address,
+                      u64 num, u64 *out)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_COLLECT_VPD,
+                               record, list_address, num, 0,
+                               out);
+}
+
+/**
+ * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt
+ */
+long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_GET_FUNCTION_ERR_INT,
+                               0, 0, 0, 0, reg);
+}
+
+/**
+ * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data
+ *                                based on an interrupt
+ * Parameter1 = value to write to the function-wide error interrupt register
+ */
+long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_ACK_FUNCTION_ERR_INT,
+                               value, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of
+ *                       an error log
+ */
+long cxl_h_get_error_log(u64 unit_address, u64 value)
+{
+       return cxl_h_control_function(unit_address,
+                               H_CONTROL_CA_FUNCTION_GET_ERROR_LOG,
+                               0, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_collect_int_info - Collect interrupt info about a coherent
+ *                          platform function after an interrupt occurred.
+ */
+long cxl_h_collect_int_info(u64 unit_address, u64 process_token,
+                           struct cxl_irq_info *info)
+{
+       long rc;
+
+       BUG_ON(sizeof(*info) != sizeof(unsigned long[PLPAR_HCALL9_BUFSIZE]));
+
+       rc = plpar_hcall9(H_COLLECT_CA_INT_INFO, (unsigned long *) info,
+                       unit_address, process_token);
+       _PRINT_MSG(rc, "cxl_h_collect_int_info(%#.16llx, 0x%llx): %li\n",
+               unit_address, process_token, rc);
+       trace_cxl_hcall_collect_int_info(unit_address, process_token, rc);
+
+       switch (rc) {
+       case H_SUCCESS:     /* The interrupt info is returned in return registers. */
+               pr_devel("dsisr:%#llx, dar:%#llx, dsr:%#llx, pid:%u, tid:%u, afu_err:%#llx, errstat:%#llx\n",
+                       info->dsisr, info->dar, info->dsr, info->pid,
+                       info->tid, info->afu_err, info->errstat);
+               return 0;
+       case H_PARAMETER:   /* An incorrect parameter was supplied. */
+               return -EINVAL;
+       case H_AUTHORITY:   /* The partition does not have authority to perform this hcall. */
+       case H_HARDWARE:    /* A hardware event prevented the collection of the interrupt info.*/
+       case H_STATE:       /* The coherent platform function is not in a valid state to collect interrupt info. */
+               return -EBUSY;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_control_faults - Control the operation of a coherent platform
+ *                        function after a fault occurs.
+ *
+ * Parameters
+ *    control-mask: value to control the faults
+ *                  looks like PSL_TFC_An shifted >> 32
+ *    reset-mask: mask to control reset of function faults
+ *                Set reset_mask = 1 to reset PSL errors
+ */
+long cxl_h_control_faults(u64 unit_address, u64 process_token,
+                         u64 control_mask, u64 reset_mask)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       long rc;
+
+       memset(retbuf, 0, sizeof(retbuf));
+
+       rc = plpar_hcall(H_CONTROL_CA_FAULTS, retbuf, unit_address,
+                       H_CONTROL_CA_FAULTS_RESPOND_PSL, process_token,
+                       control_mask, reset_mask);
+       _PRINT_MSG(rc, "cxl_h_control_faults(%#.16llx, 0x%llx, %#llx, %#llx): %li (%#lx)\n",
+               unit_address, process_token, control_mask, reset_mask,
+               rc, retbuf[0]);
+       trace_cxl_hcall_control_faults(unit_address, process_token,
+                               control_mask, reset_mask, retbuf[0], rc);
+
+       switch (rc) {
+       case H_SUCCESS:    /* Faults were successfully controlled for the function. */
+               return 0;
+       case H_PARAMETER:  /* An incorrect parameter was supplied. */
+               return -EINVAL;
+       case H_HARDWARE:   /* A hardware event prevented the control of faults. */
+       case H_STATE:      /* The function was in an invalid state. */
+       case H_AUTHORITY:  /* The partition does not have authority to perform this hcall; the coherent platform facilities may need to be licensed. */
+               return -EBUSY;
+       case H_FUNCTION:   /* The function is not supported */
+       case H_NOT_FOUND:  /* The operation supplied was not valid */
+               return -EINVAL;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_control_facility - This H_CONTROL_CA_FACILITY hypervisor call
+ *                          allows the partition to manipulate or query
+ *                          certain coherent platform facility behaviors.
+ */
+static long cxl_h_control_facility(u64 unit_address, u64 op,
+                                  u64 p1, u64 p2, u64 p3, u64 p4, u64 *out)
+{
+       unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+       long rc;
+
+       CXL_H9_WAIT_UNTIL_DONE(rc, retbuf, H_CONTROL_CA_FACILITY, unit_address, op, p1, p2, p3, p4);
+       _PRINT_MSG(rc, "cxl_h_control_facility(%#.16llx, %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li\n",
+               unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc);
+       trace_cxl_hcall_control_facility(unit_address, OP_STR_CONTROL_ADAPTER(op), p1, p2, p3, p4, retbuf[0], rc);
+
+       switch (rc) {
+       case H_SUCCESS:       /* The operation is completed for the coherent platform facility */
+               if (op == H_CONTROL_CA_FACILITY_COLLECT_VPD)
+                       *out = retbuf[0];
+               return 0;
+       case H_PARAMETER:     /* An incorrect parameter was supplied. */
+       case H_FUNCTION:      /* The function is not supported. */
+       case H_NOT_FOUND:     /* The operation supplied was not valid */
+       case H_NOT_AVAILABLE: /* The operation cannot be performed because the AFU has not been downloaded */
+       case H_SG_LIST:       /* An block list entry was invalid */
+               return -EINVAL;
+       case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
+       case H_RESOURCE:      /* The function has page table mappings for MMIO */
+       case H_HARDWARE:      /* A hardware event prevented the attach operation */
+       case H_STATE:         /* The coherent platform facility is not in a valid state */
+       case H_BUSY:
+               return -EBUSY;
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_reset_adapter - Perform a reset to the coherent platform facility.
+ */
+long cxl_h_reset_adapter(u64 unit_address)
+{
+       return cxl_h_control_facility(unit_address,
+                               H_CONTROL_CA_FACILITY_RESET,
+                               0, 0, 0, 0,
+                               NULL);
+}
+
+/**
+ * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
+ * Parameter1 = 4K naturally aligned real buffer containing block
+ *              list entries
+ * Parameter2 = number of block list entries in the block list, valid
+ *              values are between 0 and 256
+ */
+long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address,
+                              u64 num, u64 *out)
+{
+       return cxl_h_control_facility(unit_address,
+                               H_CONTROL_CA_FACILITY_COLLECT_VPD,
+                               list_address, num, 0, 0,
+                               out);
+}
+
+/**
+ * cxl_h_download_facility - This H_DOWNLOAD_CA_FACILITY
+ *                    hypervisor call provide platform support for
+ *                    downloading a base adapter image to the coherent
+ *                    platform facility, and for validating the entire
+ *                    image after the download.
+ * Parameters
+ *    op: operation to perform to the coherent platform function
+ *      Download: operation = 1, the base image in the coherent platform
+ *                               facility is first erased, and then
+ *                               programmed using the image supplied
+ *                               in the scatter/gather list.
+ *      Validate: operation = 2, the base image in the coherent platform
+ *                               facility is compared with the image
+ *                               supplied in the scatter/gather list.
+ *    list_address: 4K naturally aligned real buffer containing
+ *                  scatter/gather list entries.
+ *    num: number of block list entries in the scatter/gather list.
+ */
+static long cxl_h_download_facility(u64 unit_address, u64 op,
+                                   u64 list_address, u64 num,
+                                   u64 *out)
+{
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+       unsigned int delay, total_delay = 0;
+       u64 token = 0;
+       long rc;
+
+       if (*out != 0)
+               token = *out;
+
+       memset(retbuf, 0, sizeof(retbuf));
+       while (1) {
+               rc = plpar_hcall(H_DOWNLOAD_CA_FACILITY, retbuf,
+                                unit_address, op, list_address, num,
+                                token);
+               token = retbuf[0];
+               if (rc != H_BUSY && !H_IS_LONG_BUSY(rc))
+                       break;
+
+               if (rc != H_BUSY) {
+                       delay = get_longbusy_msecs(rc);
+                       total_delay += delay;
+                       if (total_delay > CXL_HCALL_TIMEOUT_DOWNLOAD) {
+                               WARN(1, "Warning: Giving up waiting for CXL hcall "
+                                       "%#x after %u msec\n",
+                                       H_DOWNLOAD_CA_FACILITY, total_delay);
+                               rc = H_BUSY;
+                               break;
+                       }
+                       msleep(delay);
+               }
+       }
+       _PRINT_MSG(rc, "cxl_h_download_facility(%#.16llx, %s(%#llx, %#llx), %#lx): %li\n",
+                unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc);
+       trace_cxl_hcall_download_facility(unit_address, OP_STR_DOWNLOAD_ADAPTER(op), list_address, num, retbuf[0], rc);
+
+       switch (rc) {
+       case H_SUCCESS:       /* The operation is completed for the coherent platform facility */
+               return 0;
+       case H_PARAMETER:     /* An incorrect parameter was supplied */
+       case H_FUNCTION:      /* The function is not supported. */
+       case H_SG_LIST:       /* An block list entry was invalid */
+       case H_BAD_DATA:      /* Image verification failed */
+               return -EINVAL;
+       case H_AUTHORITY:     /* The partition does not have authority to perform this hcall */
+       case H_RESOURCE:      /* The function has page table mappings for MMIO */
+       case H_HARDWARE:      /* A hardware event prevented the attach operation */
+       case H_STATE:         /* The coherent platform facility is not in a valid state */
+       case H_BUSY:
+               return -EBUSY;
+       case H_CONTINUE:
+               *out = retbuf[0];
+               return 1;  /* More data is needed for the complete image */
+       default:
+               WARN(1, "Unexpected return code: %lx", rc);
+               return -EINVAL;
+       }
+}
+
+/**
+ * cxl_h_download_adapter_image - Download the base image to the coherent
+ *                                platform facility.
+ */
+long cxl_h_download_adapter_image(u64 unit_address,
+                                 u64 list_address, u64 num,
+                                 u64 *out)
+{
+       return cxl_h_download_facility(unit_address,
+                                      H_DOWNLOAD_CA_FACILITY_DOWNLOAD,
+                                      list_address, num, out);
+}
+
+/**
+ * cxl_h_validate_adapter_image - Validate the base image in the coherent
+ *                                platform facility.
+ */
+long cxl_h_validate_adapter_image(u64 unit_address,
+                                 u64 list_address, u64 num,
+                                 u64 *out)
+{
+       return cxl_h_download_facility(unit_address,
+                                      H_DOWNLOAD_CA_FACILITY_VALIDATE,
+                                      list_address, num, out);
+}
diff --git a/drivers/misc/cxl/hcalls.h b/drivers/misc/cxl/hcalls.h
new file mode 100644 (file)
index 0000000..3e25522
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2015 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _HCALLS_H
+#define _HCALLS_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/hvcall.h>
+#include "cxl.h"
+
+#define SG_BUFFER_SIZE 4096
+#define SG_MAX_ENTRIES 256
+
+struct sg_list {
+       u64 phys_addr;
+       u64 len;
+};
+
+/*
+ * This is straight out of PAPR, but replacing some of the compound fields with
+ * a single field, where they were identical to the register layout.
+ *
+ * The 'flags' parameter regroups the various bit-fields
+ */
+#define CXL_PE_CSRP_VALID                      (1ULL << 63)
+#define CXL_PE_PROBLEM_STATE                   (1ULL << 62)
+#define CXL_PE_SECONDARY_SEGMENT_TBL_SRCH      (1ULL << 61)
+#define CXL_PE_TAGS_ACTIVE                     (1ULL << 60)
+#define CXL_PE_USER_STATE                      (1ULL << 59)
+#define CXL_PE_TRANSLATION_ENABLED             (1ULL << 58)
+#define CXL_PE_64_BIT                          (1ULL << 57)
+#define CXL_PE_PRIVILEGED_PROCESS              (1ULL << 56)
+
+#define CXL_PROCESS_ELEMENT_VERSION 1
+struct cxl_process_element_hcall {
+       __be64 version;
+       __be64 flags;
+       u8     reserved0[12];
+       __be32 pslVirtualIsn;
+       u8     applicationVirtualIsnBitmap[256];
+       u8     reserved1[144];
+       struct cxl_process_element_common common;
+       u8     reserved4[12];
+} __packed;
+
+#define H_STATE_NORMAL              1
+#define H_STATE_DISABLE             2
+#define H_STATE_TEMP_UNAVAILABLE    3
+#define H_STATE_PERM_UNAVAILABLE    4
+
+/* NOTE: element must be a logical real address, and must be pinned */
+long cxl_h_attach_process(u64 unit_address, struct cxl_process_element_hcall *element,
+                       u64 *process_token, u64 *mmio_addr, u64 *mmio_size);
+
+/**
+ * cxl_h_detach_process - Detach a process element from a coherent
+ *                        platform function.
+ */
+long cxl_h_detach_process(u64 unit_address, u64 process_token);
+
+/**
+ * cxl_h_reset_afu - Perform a reset to the coherent platform function.
+ */
+long cxl_h_reset_afu(u64 unit_address);
+
+/**
+ * cxl_h_suspend_process - Suspend a process from being executed
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_suspend_process(u64 unit_address, u64 process_token);
+
+/**
+ * cxl_h_resume_process - Resume a process to be executed
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_resume_process(u64 unit_address, u64 process_token);
+
+/**
+ * cxl_h_read_error_state - Reads the error state of the coherent
+ *                          platform function.
+ * R4 contains the error state
+ */
+long cxl_h_read_error_state(u64 unit_address, u64 *state);
+
+/**
+ * cxl_h_get_afu_err - collect the AFU error buffer
+ * Parameter1 = byte offset into error buffer to retrieve, valid values
+ *              are between 0 and (ibm,error-buffer-size - 1)
+ * Parameter2 = 4K aligned real address of error buffer, to be filled in
+ * Parameter3 = length of error buffer, valid values are 4K or less
+ */
+long cxl_h_get_afu_err(u64 unit_address, u64 offset, u64 buf_address, u64 len);
+
+/**
+ * cxl_h_get_config - collect configuration record for the
+ *                    coherent platform function
+ * Parameter1 = # of configuration record to retrieve, valid values are
+ *              between 0 and (ibm,#config-records - 1)
+ * Parameter2 = byte offset into configuration record to retrieve,
+ *              valid values are between 0 and (ibm,config-record-size - 1)
+ * Parameter3 = 4K aligned real address of configuration record buffer,
+ *              to be filled in
+ * Parameter4 = length of configuration buffer, valid values are 4K or less
+ */
+long cxl_h_get_config(u64 unit_address, u64 cr_num, u64 offset,
+               u64 buf_address, u64 len);
+
+/**
+ * cxl_h_terminate_process - Terminate the process before completion
+ * Parameter1 = process-token as returned from H_ATTACH_CA_PROCESS when
+ *              process was attached.
+ */
+long cxl_h_terminate_process(u64 unit_address, u64 process_token);
+
+/**
+ * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
+ * Parameter1 = # of VPD record to retrieve, valid values are between 0
+ *              and (ibm,#config-records - 1).
+ * Parameter2 = 4K naturally aligned real buffer containing block
+ *              list entries
+ * Parameter3 = number of block list entries in the block list, valid
+ *              values are between 0 and 256
+ */
+long cxl_h_collect_vpd(u64 unit_address, u64 record, u64 list_address,
+                      u64 num, u64 *out);
+
+/**
+ * cxl_h_get_fn_error_interrupt - Read the function-wide error data based on an interrupt
+ */
+long cxl_h_get_fn_error_interrupt(u64 unit_address, u64 *reg);
+
+/**
+ * cxl_h_ack_fn_error_interrupt - Acknowledge function-wide error data
+ *                                based on an interrupt
+ * Parameter1 = value to write to the function-wide error interrupt register
+ */
+long cxl_h_ack_fn_error_interrupt(u64 unit_address, u64 value);
+
+/**
+ * cxl_h_get_error_log - Retrieve the Platform Log ID (PLID) of
+ *                       an error log
+ */
+long cxl_h_get_error_log(u64 unit_address, u64 value);
+
+/**
+ * cxl_h_collect_int_info - Collect interrupt info about a coherent
+ *                          platform function after an interrupt occurred.
+ */
+long cxl_h_collect_int_info(u64 unit_address, u64 process_token,
+                       struct cxl_irq_info *info);
+
+/**
+ * cxl_h_control_faults - Control the operation of a coherent platform
+ *                        function after a fault occurs.
+ *
+ * Parameters
+ *    control-mask: value to control the faults
+ *                  looks like PSL_TFC_An shifted >> 32
+ *    reset-mask: mask to control reset of function faults
+ *                Set reset_mask = 1 to reset PSL errors
+ */
+long cxl_h_control_faults(u64 unit_address, u64 process_token,
+                       u64 control_mask, u64 reset_mask);
+
+/**
+ * cxl_h_reset_adapter - Perform a reset to the coherent platform facility.
+ */
+long cxl_h_reset_adapter(u64 unit_address);
+
+/**
+ * cxl_h_collect_vpd - Collect VPD for the coherent platform function.
+ * Parameter1 = 4K naturally aligned real buffer containing block
+ *              list entries
+ * Parameter2 = number of block list entries in the block list, valid
+ *              values are between 0 and 256
+ */
+long cxl_h_collect_vpd_adapter(u64 unit_address, u64 list_address,
+                              u64 num, u64 *out);
+
+/**
+ * cxl_h_download_adapter_image - Download the base image to the coherent
+ *                                platform facility.
+ */
+long cxl_h_download_adapter_image(u64 unit_address,
+                                 u64 list_address, u64 num,
+                                 u64 *out);
+
+/**
+ * cxl_h_validate_adapter_image - Validate the base image in the coherent
+ *                                platform facility.
+ */
+long cxl_h_validate_adapter_image(u64 unit_address,
+                                 u64 list_address, u64 num,
+                                 u64 *out);
+#endif /* _HCALLS_H */
index 09a4060..be646dc 100644 (file)
 #include "cxl.h"
 #include "trace.h"
 
-/* XXX: This is implementation specific */
-static irqreturn_t handle_psl_slice_error(struct cxl_context *ctx, u64 dsisr, u64 errstat)
+static int afu_irq_range_start(void)
 {
-       u64 fir1, fir2, fir_slice, serr, afu_debug;
-
-       fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR1);
-       fir2 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR2);
-       fir_slice = cxl_p1n_read(ctx->afu, CXL_PSL_FIR_SLICE_An);
-       serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An);
-       afu_debug = cxl_p1n_read(ctx->afu, CXL_AFU_DEBUG_An);
-
-       dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%016llx\n", errstat);
-       dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1);
-       dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2);
-       dev_crit(&ctx->afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
-       dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
-       dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
-
-       dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n");
-       cxl_stop_trace(ctx->afu->adapter);
-
-       return cxl_ack_irq(ctx, 0, errstat);
-}
-
-irqreturn_t cxl_slice_irq_err(int irq, void *data)
-{
-       struct cxl_afu *afu = data;
-       u64 fir_slice, errstat, serr, afu_debug;
-
-       WARN(irq, "CXL SLICE ERROR interrupt %i\n", irq);
-
-       serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
-       fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
-       errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
-       afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
-       dev_crit(&afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
-       dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
-       dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat);
-       dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
-
-       cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t cxl_irq_err(int irq, void *data)
-{
-       struct cxl *adapter = data;
-       u64 fir1, fir2, err_ivte;
-
-       WARN(1, "CXL ERROR interrupt %i\n", irq);
-
-       err_ivte = cxl_p1_read(adapter, CXL_PSL_ErrIVTE);
-       dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%016llx\n", err_ivte);
-
-       dev_crit(&adapter->dev, "STOPPING CXL TRACE\n");
-       cxl_stop_trace(adapter);
-
-       fir1 = cxl_p1_read(adapter, CXL_PSL_FIR1);
-       fir2 = cxl_p1_read(adapter, CXL_PSL_FIR2);
-
-       dev_crit(&adapter->dev, "PSL_FIR1: 0x%016llx\nPSL_FIR2: 0x%016llx\n", fir1, fir2);
-
-       return IRQ_HANDLED;
+       if (cpu_has_feature(CPU_FTR_HVMODE))
+               return 1;
+       return 0;
 }
 
 static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 dar)
@@ -93,9 +34,8 @@ static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 da
        return IRQ_HANDLED;
 }
 
-static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
+irqreturn_t cxl_irq(int irq, struct cxl_context *ctx, struct cxl_irq_info *irq_info)
 {
-       struct cxl_context *ctx = data;
        u64 dsisr, dar;
 
        dsisr = irq_info->dsisr;
@@ -145,7 +85,8 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
        if (dsisr & CXL_PSL_DSISR_An_UR)
                pr_devel("CXL interrupt: AURP PTE not found\n");
        if (dsisr & CXL_PSL_DSISR_An_PE)
-               return handle_psl_slice_error(ctx, dsisr, irq_info->errstat);
+               return cxl_ops->handle_psl_slice_error(ctx, dsisr,
+                                               irq_info->errstat);
        if (dsisr & CXL_PSL_DSISR_An_AE) {
                pr_devel("CXL interrupt: AFU Error 0x%016llx\n", irq_info->afu_err);
 
@@ -169,7 +110,7 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
                        wake_up_all(&ctx->wq);
                }
 
-               cxl_ack_irq(ctx, CXL_PSL_TFC_An_A, 0);
+               cxl_ops->ack_irq(ctx, CXL_PSL_TFC_An_A, 0);
                return IRQ_HANDLED;
        }
        if (dsisr & CXL_PSL_DSISR_An_OC)
@@ -179,54 +120,27 @@ static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
        return IRQ_HANDLED;
 }
 
-static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
-{
-       if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
-               cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
-       else
-               cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t cxl_irq_multiplexed(int irq, void *data)
-{
-       struct cxl_afu *afu = data;
-       struct cxl_context *ctx;
-       struct cxl_irq_info irq_info;
-       int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
-       int ret;
-
-       if ((ret = cxl_get_irq(afu, &irq_info))) {
-               WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
-               return fail_psl_irq(afu, &irq_info);
-       }
-
-       rcu_read_lock();
-       ctx = idr_find(&afu->contexts_idr, ph);
-       if (ctx) {
-               ret = cxl_irq(irq, ctx, &irq_info);
-               rcu_read_unlock();
-               return ret;
-       }
-       rcu_read_unlock();
-
-       WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %016llx DAR"
-               " %016llx\n(Possible AFU HW issue - was a term/remove acked"
-               " with outstanding transactions?)\n", ph, irq_info.dsisr,
-               irq_info.dar);
-       return fail_psl_irq(afu, &irq_info);
-}
-
 static irqreturn_t cxl_irq_afu(int irq, void *data)
 {
        struct cxl_context *ctx = data;
        irq_hw_number_t hwirq = irqd_to_hwirq(irq_get_irq_data(irq));
-       int irq_off, afu_irq = 1;
+       int irq_off, afu_irq = 0;
        __u16 range;
        int r;
 
-       for (r = 1; r < CXL_IRQ_RANGES; r++) {
+       /*
+        * Look for the interrupt number.
+        * On bare-metal, we know range 0 only contains the PSL
+        * interrupt so we could start counting at range 1 and initialize
+        * afu_irq at 1.
+        * In a guest, range 0 also contains AFU interrupts, so it must
+        * be counted for. Therefore we initialize afu_irq at 0 to take into
+        * account the PSL interrupt.
+        *
+        * For code-readability, it just seems easier to go over all
+        * the ranges on bare-metal and guest. The end result is the same.
+        */
+       for (r = 0; r < CXL_IRQ_RANGES; r++) {
                irq_off = hwirq - ctx->irqs.offset[r];
                range = ctx->irqs.range[r];
                if (irq_off >= 0 && irq_off < range) {
@@ -236,7 +150,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)
                afu_irq += range;
        }
        if (unlikely(r >= CXL_IRQ_RANGES)) {
-               WARN(1, "Recieved AFU IRQ out of range for pe %i (virq %i hwirq %lx)\n",
+               WARN(1, "Received AFU IRQ out of range for pe %i (virq %i hwirq %lx)\n",
                     ctx->pe, irq, hwirq);
                return IRQ_HANDLED;
        }
@@ -246,7 +160,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)
               afu_irq, ctx->pe, irq, hwirq);
 
        if (unlikely(!ctx->irq_bitmap)) {
-               WARN(1, "Recieved AFU IRQ for context with no IRQ bitmap\n");
+               WARN(1, "Received AFU IRQ for context with no IRQ bitmap\n");
                return IRQ_HANDLED;
        }
        spin_lock(&ctx->lock);
@@ -272,7 +186,8 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
                return 0;
        }
 
-       cxl_setup_irq(adapter, hwirq, virq);
+       if (cxl_ops->setup_irq)
+               cxl_ops->setup_irq(adapter, hwirq, virq);
 
        pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq);
 
@@ -291,16 +206,16 @@ void cxl_unmap_irq(unsigned int virq, void *cookie)
        irq_dispose_mapping(virq);
 }
 
-static int cxl_register_one_irq(struct cxl *adapter,
-                               irq_handler_t handler,
-                               void *cookie,
-                               irq_hw_number_t *dest_hwirq,
-                               unsigned int *dest_virq,
-                               const char *name)
+int cxl_register_one_irq(struct cxl *adapter,
+                       irq_handler_t handler,
+                       void *cookie,
+                       irq_hw_number_t *dest_hwirq,
+                       unsigned int *dest_virq,
+                       const char *name)
 {
        int hwirq, virq;
 
-       if ((hwirq = cxl_alloc_one_irq(adapter)) < 0)
+       if ((hwirq = cxl_ops->alloc_one_irq(adapter)) < 0)
                return hwirq;
 
        if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name)))
@@ -312,108 +227,10 @@ static int cxl_register_one_irq(struct cxl *adapter,
        return 0;
 
 err:
-       cxl_release_one_irq(adapter, hwirq);
+       cxl_ops->release_one_irq(adapter, hwirq);
        return -ENOMEM;
 }
 
-int cxl_register_psl_err_irq(struct cxl *adapter)
-{
-       int rc;
-
-       adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
-                                     dev_name(&adapter->dev));
-       if (!adapter->irq_name)
-               return -ENOMEM;
-
-       if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter,
-                                      &adapter->err_hwirq,
-                                      &adapter->err_virq,
-                                      adapter->irq_name))) {
-               kfree(adapter->irq_name);
-               adapter->irq_name = NULL;
-               return rc;
-       }
-
-       cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff);
-
-       return 0;
-}
-
-void cxl_release_psl_err_irq(struct cxl *adapter)
-{
-       if (adapter->err_virq != irq_find_mapping(NULL, adapter->err_hwirq))
-               return;
-
-       cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
-       cxl_unmap_irq(adapter->err_virq, adapter);
-       cxl_release_one_irq(adapter, adapter->err_hwirq);
-       kfree(adapter->irq_name);
-}
-
-int cxl_register_serr_irq(struct cxl_afu *afu)
-{
-       u64 serr;
-       int rc;
-
-       afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
-                                     dev_name(&afu->dev));
-       if (!afu->err_irq_name)
-               return -ENOMEM;
-
-       if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu,
-                                      &afu->serr_hwirq,
-                                      &afu->serr_virq, afu->err_irq_name))) {
-               kfree(afu->err_irq_name);
-               afu->err_irq_name = NULL;
-               return rc;
-       }
-
-       serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
-       serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
-       cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
-
-       return 0;
-}
-
-void cxl_release_serr_irq(struct cxl_afu *afu)
-{
-       if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
-               return;
-
-       cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
-       cxl_unmap_irq(afu->serr_virq, afu);
-       cxl_release_one_irq(afu->adapter, afu->serr_hwirq);
-       kfree(afu->err_irq_name);
-}
-
-int cxl_register_psl_irq(struct cxl_afu *afu)
-{
-       int rc;
-
-       afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s",
-                                     dev_name(&afu->dev));
-       if (!afu->psl_irq_name)
-               return -ENOMEM;
-
-       if ((rc = cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu,
-                                   &afu->psl_hwirq, &afu->psl_virq,
-                                   afu->psl_irq_name))) {
-               kfree(afu->psl_irq_name);
-               afu->psl_irq_name = NULL;
-       }
-       return rc;
-}
-
-void cxl_release_psl_irq(struct cxl_afu *afu)
-{
-       if (afu->psl_virq != irq_find_mapping(NULL, afu->psl_hwirq))
-               return;
-
-       cxl_unmap_irq(afu->psl_virq, afu);
-       cxl_release_one_irq(afu->adapter, afu->psl_hwirq);
-       kfree(afu->psl_irq_name);
-}
-
 void afu_irq_name_free(struct cxl_context *ctx)
 {
        struct cxl_irq_name *irq_name, *tmp;
@@ -429,16 +246,33 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count)
 {
        int rc, r, i, j = 1;
        struct cxl_irq_name *irq_name;
+       int alloc_count;
+
+       /*
+        * In native mode, range 0 is reserved for the multiplexed
+        * PSL interrupt. It has been allocated when the AFU was initialized.
+        *
+        * In a guest, the PSL interrupt is not mutliplexed, but per-context,
+        * and is the first interrupt from range 0. It still needs to be
+        * allocated, so bump the count by one.
+        */
+       if (cpu_has_feature(CPU_FTR_HVMODE))
+               alloc_count = count;
+       else
+               alloc_count = count + 1;
 
        /* Initialize the list head to hold irq names */
        INIT_LIST_HEAD(&ctx->irq_names);
 
-       if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count)))
+       if ((rc = cxl_ops->alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter,
+                                                       alloc_count)))
                return rc;
 
-       /* Multiplexed PSL Interrupt */
-       ctx->irqs.offset[0] = ctx->afu->psl_hwirq;
-       ctx->irqs.range[0] = 1;
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               /* Multiplexed PSL Interrupt */
+               ctx->irqs.offset[0] = ctx->afu->native->psl_hwirq;
+               ctx->irqs.range[0] = 1;
+       }
 
        ctx->irq_count = count;
        ctx->irq_bitmap = kcalloc(BITS_TO_LONGS(count),
@@ -450,7 +284,7 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count)
         * Allocate names first.  If any fail, bail out before allocating
         * actual hardware IRQs.
         */
-       for (r = 1; r < CXL_IRQ_RANGES; r++) {
+       for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) {
                for (i = 0; i < ctx->irqs.range[r]; i++) {
                        irq_name = kmalloc(sizeof(struct cxl_irq_name),
                                           GFP_KERNEL);
@@ -471,7 +305,7 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count)
        return 0;
 
 out:
-       cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+       cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
        afu_irq_name_free(ctx);
        return -ENOMEM;
 }
@@ -480,15 +314,30 @@ static void afu_register_hwirqs(struct cxl_context *ctx)
 {
        irq_hw_number_t hwirq;
        struct cxl_irq_name *irq_name;
-       int r,i;
+       int r, i;
+       irqreturn_t (*handler)(int irq, void *data);
 
        /* We've allocated all memory now, so let's do the irq allocations */
        irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list);
-       for (r = 1; r < CXL_IRQ_RANGES; r++) {
+       for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) {
                hwirq = ctx->irqs.offset[r];
                for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
-                       cxl_map_irq(ctx->afu->adapter, hwirq,
-                                   cxl_irq_afu, ctx, irq_name->name);
+                       if (r == 0 && i == 0)
+                               /*
+                                * The very first interrupt of range 0 is
+                                * always the PSL interrupt, but we only
+                                * need to connect a handler for guests,
+                                * because there's one PSL interrupt per
+                                * context.
+                                * On bare-metal, the PSL interrupt is
+                                * multiplexed and was setup when the AFU
+                                * was configured.
+                                */
+                               handler = cxl_ops->psl_interrupt;
+                       else
+                               handler = cxl_irq_afu;
+                       cxl_map_irq(ctx->afu->adapter, hwirq, handler, ctx,
+                               irq_name->name);
                        irq_name = list_next_entry(irq_name, list);
                }
        }
@@ -504,7 +353,7 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
 
        afu_register_hwirqs(ctx);
        return 0;
- }
+}
 
 void afu_release_irqs(struct cxl_context *ctx, void *cookie)
 {
@@ -512,7 +361,7 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie)
        unsigned int virq;
        int r, i;
 
-       for (r = 1; r < CXL_IRQ_RANGES; r++) {
+       for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) {
                hwirq = ctx->irqs.offset[r];
                for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
                        virq = irq_find_mapping(NULL, hwirq);
@@ -522,7 +371,7 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie)
        }
 
        afu_irq_name_free(ctx);
-       cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+       cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
 
        ctx->irq_count = 0;
 }
index 9fde75e..ae68c32 100644 (file)
@@ -32,6 +32,29 @@ uint cxl_verbose;
 module_param_named(verbose, cxl_verbose, uint, 0600);
 MODULE_PARM_DESC(verbose, "Enable verbose dmesg output");
 
+const struct cxl_backend_ops *cxl_ops;
+
+int cxl_afu_slbia(struct cxl_afu *afu)
+{
+       unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT);
+
+       pr_devel("cxl_afu_slbia issuing SLBIA command\n");
+       cxl_p2n_write(afu, CXL_SLBIA_An, CXL_TLB_SLB_IQ_ALL);
+       while (cxl_p2n_read(afu, CXL_SLBIA_An) & CXL_TLB_SLB_P) {
+               if (time_after_eq(jiffies, timeout)) {
+                       dev_warn(&afu->dev, "WARNING: CXL AFU SLBIA timed out!\n");
+                       return -EBUSY;
+               }
+               /* If the adapter has gone down, we can assume that we
+                * will PERST it and that will invalidate everything.
+                */
+               if (!cxl_ops->link_ok(afu->adapter, afu))
+                       return -EIO;
+               cpu_relax();
+       }
+       return 0;
+}
+
 static inline void _cxl_slbia(struct cxl_context *ctx, struct mm_struct *mm)
 {
        struct task_struct *task;
@@ -139,6 +162,32 @@ int cxl_alloc_sst(struct cxl_context *ctx)
        return 0;
 }
 
+/* print buffer content as integers when debugging */
+void cxl_dump_debug_buffer(void *buf, size_t buf_len)
+{
+#ifdef DEBUG
+       int i, *ptr;
+
+       /*
+        * We want to regroup up to 4 integers per line, which means they
+        * need to be in the same pr_devel() statement
+        */
+       ptr = (int *) buf;
+       for (i = 0; i * 4 < buf_len; i += 4) {
+               if ((i + 3) * 4 < buf_len)
+                       pr_devel("%.8x %.8x %.8x %.8x\n", ptr[i], ptr[i + 1],
+                               ptr[i + 2], ptr[i + 3]);
+               else if ((i + 2) * 4 < buf_len)
+                       pr_devel("%.8x %.8x %.8x\n", ptr[i], ptr[i + 1],
+                               ptr[i + 2]);
+               else if ((i + 1) * 4 < buf_len)
+                       pr_devel("%.8x %.8x\n", ptr[i], ptr[i + 1]);
+               else
+                       pr_devel("%.8x\n", ptr[i]);
+       }
+#endif /* DEBUG */
+}
+
 /* Find a CXL adapter by it's number and increase it's refcount */
 struct cxl *get_cxl_adapter(int num)
 {
@@ -152,7 +201,7 @@ struct cxl *get_cxl_adapter(int num)
        return adapter;
 }
 
-int cxl_alloc_adapter_nr(struct cxl *adapter)
+static int cxl_alloc_adapter_nr(struct cxl *adapter)
 {
        int i;
 
@@ -174,13 +223,58 @@ void cxl_remove_adapter_nr(struct cxl *adapter)
        idr_remove(&cxl_adapter_idr, adapter->adapter_num);
 }
 
+struct cxl *cxl_alloc_adapter(void)
+{
+       struct cxl *adapter;
+
+       if (!(adapter = kzalloc(sizeof(struct cxl), GFP_KERNEL)))
+               return NULL;
+
+       spin_lock_init(&adapter->afu_list_lock);
+
+       if (cxl_alloc_adapter_nr(adapter))
+               goto err1;
+
+       if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
+               goto err2;
+
+       return adapter;
+
+err2:
+       cxl_remove_adapter_nr(adapter);
+err1:
+       kfree(adapter);
+       return NULL;
+}
+
+struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice)
+{
+       struct cxl_afu *afu;
+
+       if (!(afu = kzalloc(sizeof(struct cxl_afu), GFP_KERNEL)))
+               return NULL;
+
+       afu->adapter = adapter;
+       afu->dev.parent = &adapter->dev;
+       afu->dev.release = cxl_ops->release_afu;
+       afu->slice = slice;
+       idr_init(&afu->contexts_idr);
+       mutex_init(&afu->contexts_lock);
+       spin_lock_init(&afu->afu_cntl_lock);
+
+       afu->prefault_mode = CXL_PREFAULT_NONE;
+       afu->irqs_max = afu->adapter->user_irqs;
+
+       return afu;
+}
+
 int cxl_afu_select_best_mode(struct cxl_afu *afu)
 {
        if (afu->modes_supported & CXL_MODE_DIRECTED)
-               return cxl_afu_activate_mode(afu, CXL_MODE_DIRECTED);
+               return cxl_ops->afu_activate_mode(afu, CXL_MODE_DIRECTED);
 
        if (afu->modes_supported & CXL_MODE_DEDICATED)
-               return cxl_afu_activate_mode(afu, CXL_MODE_DEDICATED);
+               return cxl_ops->afu_activate_mode(afu, CXL_MODE_DEDICATED);
 
        dev_warn(&afu->dev, "No supported programming modes available\n");
        /* We don't fail this so the user can inspect sysfs */
@@ -191,9 +285,6 @@ static int __init init_cxl(void)
 {
        int rc = 0;
 
-       if (!cpu_has_feature(CPU_FTR_HVMODE))
-               return -EPERM;
-
        if ((rc = cxl_file_init()))
                return rc;
 
@@ -202,7 +293,17 @@ static int __init init_cxl(void)
        if ((rc = register_cxl_calls(&cxl_calls)))
                goto err;
 
-       if ((rc = pci_register_driver(&cxl_pci_driver)))
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               cxl_ops = &cxl_native_ops;
+               rc = pci_register_driver(&cxl_pci_driver);
+       }
+#ifdef CONFIG_PPC_PSERIES
+       else {
+               cxl_ops = &cxl_guest_ops;
+               rc = platform_driver_register(&cxl_of_driver);
+       }
+#endif
+       if (rc)
                goto err1;
 
        return 0;
@@ -217,7 +318,12 @@ err:
 
 static void exit_cxl(void)
 {
-       pci_unregister_driver(&cxl_pci_driver);
+       if (cpu_has_feature(CPU_FTR_HVMODE))
+               pci_unregister_driver(&cxl_pci_driver);
+#ifdef CONFIG_PPC_PSERIES
+       else
+               platform_driver_unregister(&cxl_of_driver);
+#endif
 
        cxl_debugfs_exit();
        cxl_file_exit();
index f409097..387fcbd 100644 (file)
@@ -42,7 +42,7 @@ static int afu_control(struct cxl_afu *afu, u64 command,
                        goto out;
                }
 
-               if (!cxl_adapter_link_ok(afu->adapter)) {
+               if (!cxl_ops->link_ok(afu->adapter, afu)) {
                        afu->enabled = enabled;
                        rc = -EIO;
                        goto out;
@@ -80,7 +80,7 @@ int cxl_afu_disable(struct cxl_afu *afu)
 }
 
 /* This will disable as well as reset */
-int __cxl_afu_reset(struct cxl_afu *afu)
+static int native_afu_reset(struct cxl_afu *afu)
 {
        pr_devel("AFU reset request\n");
 
@@ -90,9 +90,9 @@ int __cxl_afu_reset(struct cxl_afu *afu)
                           false);
 }
 
-int cxl_afu_check_and_enable(struct cxl_afu *afu)
+static int native_afu_check_and_enable(struct cxl_afu *afu)
 {
-       if (!cxl_adapter_link_ok(afu->adapter)) {
+       if (!cxl_ops->link_ok(afu->adapter, afu)) {
                WARN(1, "Refusing to enable afu while link down!\n");
                return -EIO;
        }
@@ -114,7 +114,7 @@ int cxl_psl_purge(struct cxl_afu *afu)
 
        pr_devel("PSL purge request\n");
 
-       if (!cxl_adapter_link_ok(afu->adapter)) {
+       if (!cxl_ops->link_ok(afu->adapter, afu)) {
                dev_warn(&afu->dev, "PSL Purge called with link down, ignoring\n");
                rc = -EIO;
                goto out;
@@ -136,7 +136,7 @@ int cxl_psl_purge(struct cxl_afu *afu)
                        rc = -EBUSY;
                        goto out;
                }
-               if (!cxl_adapter_link_ok(afu->adapter)) {
+               if (!cxl_ops->link_ok(afu->adapter, afu)) {
                        rc = -EIO;
                        goto out;
                }
@@ -186,22 +186,22 @@ static int spa_max_procs(int spa_size)
 int cxl_alloc_spa(struct cxl_afu *afu)
 {
        /* Work out how many pages to allocate */
-       afu->spa_order = 0;
+       afu->native->spa_order = 0;
        do {
-               afu->spa_order++;
-               afu->spa_size = (1 << afu->spa_order) * PAGE_SIZE;
-               afu->spa_max_procs = spa_max_procs(afu->spa_size);
-       } while (afu->spa_max_procs < afu->num_procs);
+               afu->native->spa_order++;
+               afu->native->spa_size = (1 << afu->native->spa_order) * PAGE_SIZE;
+               afu->native->spa_max_procs = spa_max_procs(afu->native->spa_size);
+       } while (afu->native->spa_max_procs < afu->num_procs);
 
-       WARN_ON(afu->spa_size > 0x100000); /* Max size supported by the hardware */
+       WARN_ON(afu->native->spa_size > 0x100000); /* Max size supported by the hardware */
 
-       if (!(afu->spa = (struct cxl_process_element *)
-             __get_free_pages(GFP_KERNEL | __GFP_ZERO, afu->spa_order))) {
+       if (!(afu->native->spa = (struct cxl_process_element *)
+             __get_free_pages(GFP_KERNEL | __GFP_ZERO, afu->native->spa_order))) {
                pr_err("cxl_alloc_spa: Unable to allocate scheduled process area\n");
                return -ENOMEM;
        }
        pr_devel("spa pages: %i afu->spa_max_procs: %i   afu->num_procs: %i\n",
-                1<<afu->spa_order, afu->spa_max_procs, afu->num_procs);
+                1<<afu->native->spa_order, afu->native->spa_max_procs, afu->num_procs);
 
        return 0;
 }
@@ -210,13 +210,15 @@ static void attach_spa(struct cxl_afu *afu)
 {
        u64 spap;
 
-       afu->sw_command_status = (__be64 *)((char *)afu->spa +
-                                           ((afu->spa_max_procs + 3) * 128));
+       afu->native->sw_command_status = (__be64 *)((char *)afu->native->spa +
+                                           ((afu->native->spa_max_procs + 3) * 128));
 
-       spap = virt_to_phys(afu->spa) & CXL_PSL_SPAP_Addr;
-       spap |= ((afu->spa_size >> (12 - CXL_PSL_SPAP_Size_Shift)) - 1) & CXL_PSL_SPAP_Size;
+       spap = virt_to_phys(afu->native->spa) & CXL_PSL_SPAP_Addr;
+       spap |= ((afu->native->spa_size >> (12 - CXL_PSL_SPAP_Size_Shift)) - 1) & CXL_PSL_SPAP_Size;
        spap |= CXL_PSL_SPAP_V;
-       pr_devel("cxl: SPA allocated at 0x%p. Max processes: %i, sw_command_status: 0x%p CXL_PSL_SPAP_An=0x%016llx\n", afu->spa, afu->spa_max_procs, afu->sw_command_status, spap);
+       pr_devel("cxl: SPA allocated at 0x%p. Max processes: %i, sw_command_status: 0x%p CXL_PSL_SPAP_An=0x%016llx\n",
+               afu->native->spa, afu->native->spa_max_procs,
+               afu->native->sw_command_status, spap);
        cxl_p1n_write(afu, CXL_PSL_SPAP_An, spap);
 }
 
@@ -227,9 +229,10 @@ static inline void detach_spa(struct cxl_afu *afu)
 
 void cxl_release_spa(struct cxl_afu *afu)
 {
-       if (afu->spa) {
-               free_pages((unsigned long) afu->spa, afu->spa_order);
-               afu->spa = NULL;
+       if (afu->native->spa) {
+               free_pages((unsigned long) afu->native->spa,
+                       afu->native->spa_order);
+               afu->native->spa = NULL;
        }
 }
 
@@ -247,7 +250,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter)
                        dev_warn(&adapter->dev, "WARNING: CXL adapter wide TLBIA timed out!\n");
                        return -EBUSY;
                }
-               if (!cxl_adapter_link_ok(adapter))
+               if (!cxl_ops->link_ok(adapter, NULL))
                        return -EIO;
                cpu_relax();
        }
@@ -258,28 +261,7 @@ int cxl_tlb_slb_invalidate(struct cxl *adapter)
                        dev_warn(&adapter->dev, "WARNING: CXL adapter wide SLBIA timed out!\n");
                        return -EBUSY;
                }
-               if (!cxl_adapter_link_ok(adapter))
-                       return -EIO;
-               cpu_relax();
-       }
-       return 0;
-}
-
-int cxl_afu_slbia(struct cxl_afu *afu)
-{
-       unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT);
-
-       pr_devel("cxl_afu_slbia issuing SLBIA command\n");
-       cxl_p2n_write(afu, CXL_SLBIA_An, CXL_TLB_SLB_IQ_ALL);
-       while (cxl_p2n_read(afu, CXL_SLBIA_An) & CXL_TLB_SLB_P) {
-               if (time_after_eq(jiffies, timeout)) {
-                       dev_warn(&afu->dev, "WARNING: CXL AFU SLBIA timed out!\n");
-                       return -EBUSY;
-               }
-               /* If the adapter has gone down, we can assume that we
-                * will PERST it and that will invalidate everything.
-                */
-               if (!cxl_adapter_link_ok(afu->adapter))
+               if (!cxl_ops->link_ok(adapter, NULL))
                        return -EIO;
                cpu_relax();
        }
@@ -312,7 +294,7 @@ static void slb_invalid(struct cxl_context *ctx)
        struct cxl *adapter = ctx->afu->adapter;
        u64 slbia;
 
-       WARN_ON(!mutex_is_locked(&ctx->afu->spa_mutex));
+       WARN_ON(!mutex_is_locked(&ctx->afu->native->spa_mutex));
 
        cxl_p1_write(adapter, CXL_PSL_LBISEL,
                        ((u64)be32_to_cpu(ctx->elem->common.pid) << 32) |
@@ -320,7 +302,7 @@ static void slb_invalid(struct cxl_context *ctx)
        cxl_p1_write(adapter, CXL_PSL_SLBIA, CXL_TLB_SLB_IQ_LPIDPID);
 
        while (1) {
-               if (!cxl_adapter_link_ok(adapter))
+               if (!cxl_ops->link_ok(adapter, NULL))
                        break;
                slbia = cxl_p1_read(adapter, CXL_PSL_SLBIA);
                if (!(slbia & CXL_TLB_SLB_P))
@@ -342,7 +324,7 @@ static int do_process_element_cmd(struct cxl_context *ctx,
 
        ctx->elem->software_state = cpu_to_be32(pe_state);
        smp_wmb();
-       *(ctx->afu->sw_command_status) = cpu_to_be64(cmd | 0 | ctx->pe);
+       *(ctx->afu->native->sw_command_status) = cpu_to_be64(cmd | 0 | ctx->pe);
        smp_mb();
        cxl_p1n_write(ctx->afu, CXL_PSL_LLCMD_An, cmd | ctx->pe);
        while (1) {
@@ -351,12 +333,12 @@ static int do_process_element_cmd(struct cxl_context *ctx,
                        rc = -EBUSY;
                        goto out;
                }
-               if (!cxl_adapter_link_ok(ctx->afu->adapter)) {
+               if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) {
                        dev_warn(&ctx->afu->dev, "WARNING: Device link down, aborting Process Element Command!\n");
                        rc = -EIO;
                        goto out;
                }
-               state = be64_to_cpup(ctx->afu->sw_command_status);
+               state = be64_to_cpup(ctx->afu->native->sw_command_status);
                if (state == ~0ULL) {
                        pr_err("cxl: Error adding process element to AFU\n");
                        rc = -1;
@@ -384,12 +366,12 @@ static int add_process_element(struct cxl_context *ctx)
 {
        int rc = 0;
 
-       mutex_lock(&ctx->afu->spa_mutex);
+       mutex_lock(&ctx->afu->native->spa_mutex);
        pr_devel("%s Adding pe: %i started\n", __func__, ctx->pe);
        if (!(rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_ADD, CXL_PE_SOFTWARE_STATE_V)))
                ctx->pe_inserted = true;
        pr_devel("%s Adding pe: %i finished\n", __func__, ctx->pe);
-       mutex_unlock(&ctx->afu->spa_mutex);
+       mutex_unlock(&ctx->afu->native->spa_mutex);
        return rc;
 }
 
@@ -401,18 +383,18 @@ static int terminate_process_element(struct cxl_context *ctx)
        if (!(ctx->elem->software_state & cpu_to_be32(CXL_PE_SOFTWARE_STATE_V)))
                return rc;
 
-       mutex_lock(&ctx->afu->spa_mutex);
+       mutex_lock(&ctx->afu->native->spa_mutex);
        pr_devel("%s Terminate pe: %i started\n", __func__, ctx->pe);
        /* We could be asked to terminate when the hw is down. That
         * should always succeed: it's not running if the hw has gone
         * away and is being reset.
         */
-       if (cxl_adapter_link_ok(ctx->afu->adapter))
+       if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
                rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_TERMINATE,
                                            CXL_PE_SOFTWARE_STATE_V | CXL_PE_SOFTWARE_STATE_T);
        ctx->elem->software_state = 0;  /* Remove Valid bit */
        pr_devel("%s Terminate pe: %i finished\n", __func__, ctx->pe);
-       mutex_unlock(&ctx->afu->spa_mutex);
+       mutex_unlock(&ctx->afu->native->spa_mutex);
        return rc;
 }
 
@@ -420,20 +402,20 @@ static int remove_process_element(struct cxl_context *ctx)
 {
        int rc = 0;
 
-       mutex_lock(&ctx->afu->spa_mutex);
+       mutex_lock(&ctx->afu->native->spa_mutex);
        pr_devel("%s Remove pe: %i started\n", __func__, ctx->pe);
 
        /* We could be asked to remove when the hw is down. Again, if
         * the hw is down, the PE is gone, so we succeed.
         */
-       if (cxl_adapter_link_ok(ctx->afu->adapter))
+       if (cxl_ops->link_ok(ctx->afu->adapter, ctx->afu))
                rc = do_process_element_cmd(ctx, CXL_SPA_SW_CMD_REMOVE, 0);
 
        if (!rc)
                ctx->pe_inserted = false;
        slb_invalid(ctx);
        pr_devel("%s Remove pe: %i finished\n", __func__, ctx->pe);
-       mutex_unlock(&ctx->afu->spa_mutex);
+       mutex_unlock(&ctx->afu->native->spa_mutex);
 
        return rc;
 }
@@ -446,7 +428,7 @@ void cxl_assign_psn_space(struct cxl_context *ctx)
                ctx->psn_size = ctx->afu->adapter->ps_size;
        } else {
                ctx->psn_phys = ctx->afu->psn_phys +
-                       (ctx->afu->pp_offset + ctx->afu->pp_size * ctx->pe);
+                       (ctx->afu->native->pp_offset + ctx->afu->pp_size * ctx->pe);
                ctx->psn_size = ctx->afu->pp_size;
        }
 }
@@ -458,7 +440,7 @@ static int activate_afu_directed(struct cxl_afu *afu)
        dev_info(&afu->dev, "Activating AFU directed mode\n");
 
        afu->num_procs = afu->max_procs_virtualised;
-       if (afu->spa == NULL) {
+       if (afu->native->spa == NULL) {
                if (cxl_alloc_spa(afu))
                        return -ENOMEM;
        }
@@ -552,7 +534,7 @@ static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr)
        ctx->elem->common.wed = cpu_to_be64(wed);
 
        /* first guy needs to enable */
-       if ((result = cxl_afu_check_and_enable(ctx->afu)))
+       if ((result = cxl_ops->afu_check_and_enable(ctx->afu)))
                return result;
 
        return add_process_element(ctx);
@@ -568,7 +550,7 @@ static int deactivate_afu_directed(struct cxl_afu *afu)
        cxl_sysfs_afu_m_remove(afu);
        cxl_chardev_afu_remove(afu);
 
-       __cxl_afu_reset(afu);
+       cxl_ops->afu_reset(afu);
        cxl_afu_disable(afu);
        cxl_psl_purge(afu);
 
@@ -632,7 +614,7 @@ static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr)
        /* master only context for dedicated */
        cxl_assign_psn_space(ctx);
 
-       if ((rc = __cxl_afu_reset(afu)))
+       if ((rc = cxl_ops->afu_reset(afu)))
                return rc;
 
        cxl_p2n_write(afu, CXL_PSL_WED_An, wed);
@@ -652,7 +634,7 @@ static int deactivate_dedicated_process(struct cxl_afu *afu)
        return 0;
 }
 
-int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode)
+static int native_afu_deactivate_mode(struct cxl_afu *afu, int mode)
 {
        if (mode == CXL_MODE_DIRECTED)
                return deactivate_afu_directed(afu);
@@ -661,19 +643,14 @@ int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode)
        return 0;
 }
 
-int cxl_afu_deactivate_mode(struct cxl_afu *afu)
-{
-       return _cxl_afu_deactivate_mode(afu, afu->current_mode);
-}
-
-int cxl_afu_activate_mode(struct cxl_afu *afu, int mode)
+static int native_afu_activate_mode(struct cxl_afu *afu, int mode)
 {
        if (!mode)
                return 0;
        if (!(mode & afu->modes_supported))
                return -EINVAL;
 
-       if (!cxl_adapter_link_ok(afu->adapter)) {
+       if (!cxl_ops->link_ok(afu->adapter, afu)) {
                WARN(1, "Device link is down, refusing to activate!\n");
                return -EIO;
        }
@@ -686,9 +663,10 @@ int cxl_afu_activate_mode(struct cxl_afu *afu, int mode)
        return -EINVAL;
 }
 
-int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr)
+static int native_attach_process(struct cxl_context *ctx, bool kernel,
+                               u64 wed, u64 amr)
 {
-       if (!cxl_adapter_link_ok(ctx->afu->adapter)) {
+       if (!cxl_ops->link_ok(ctx->afu->adapter, ctx->afu)) {
                WARN(1, "Device link is down, refusing to attach process!\n");
                return -EIO;
        }
@@ -705,7 +683,7 @@ int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed, u64 amr)
 
 static inline int detach_process_native_dedicated(struct cxl_context *ctx)
 {
-       __cxl_afu_reset(ctx->afu);
+       cxl_ops->afu_reset(ctx->afu);
        cxl_afu_disable(ctx->afu);
        cxl_psl_purge(ctx->afu);
        return 0;
@@ -723,7 +701,7 @@ static inline int detach_process_native_afu_directed(struct cxl_context *ctx)
        return 0;
 }
 
-int cxl_detach_process(struct cxl_context *ctx)
+static int native_detach_process(struct cxl_context *ctx)
 {
        trace_cxl_detach(ctx);
 
@@ -733,14 +711,14 @@ int cxl_detach_process(struct cxl_context *ctx)
        return detach_process_native_afu_directed(ctx);
 }
 
-int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info)
+static int native_get_irq_info(struct cxl_afu *afu, struct cxl_irq_info *info)
 {
        u64 pidtid;
 
        /* If the adapter has gone away, we can't get any meaningful
         * information.
         */
-       if (!cxl_adapter_link_ok(afu->adapter))
+       if (!cxl_ops->link_ok(afu->adapter, afu))
                return -EIO;
 
        info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);
@@ -751,10 +729,214 @@ int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info)
        info->tid = pidtid & 0xffffffff;
        info->afu_err = cxl_p2n_read(afu, CXL_AFU_ERR_An);
        info->errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
+       info->proc_handle = 0;
+
+       return 0;
+}
+
+static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx,
+                                               u64 dsisr, u64 errstat)
+{
+       u64 fir1, fir2, fir_slice, serr, afu_debug;
+
+       fir1 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR1);
+       fir2 = cxl_p1_read(ctx->afu->adapter, CXL_PSL_FIR2);
+       fir_slice = cxl_p1n_read(ctx->afu, CXL_PSL_FIR_SLICE_An);
+       serr = cxl_p1n_read(ctx->afu, CXL_PSL_SERR_An);
+       afu_debug = cxl_p1n_read(ctx->afu, CXL_AFU_DEBUG_An);
+
+       dev_crit(&ctx->afu->dev, "PSL ERROR STATUS: 0x%016llx\n", errstat);
+       dev_crit(&ctx->afu->dev, "PSL_FIR1: 0x%016llx\n", fir1);
+       dev_crit(&ctx->afu->dev, "PSL_FIR2: 0x%016llx\n", fir2);
+       dev_crit(&ctx->afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
+       dev_crit(&ctx->afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
+       dev_crit(&ctx->afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
+
+       dev_crit(&ctx->afu->dev, "STOPPING CXL TRACE\n");
+       cxl_stop_trace(ctx->afu->adapter);
+
+       return cxl_ops->ack_irq(ctx, 0, errstat);
+}
+
+static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
+{
+       if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
+               cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
+       else
+               cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t native_irq_multiplexed(int irq, void *data)
+{
+       struct cxl_afu *afu = data;
+       struct cxl_context *ctx;
+       struct cxl_irq_info irq_info;
+       int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
+       int ret;
+
+       if ((ret = native_get_irq_info(afu, &irq_info))) {
+               WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
+               return fail_psl_irq(afu, &irq_info);
+       }
+
+       rcu_read_lock();
+       ctx = idr_find(&afu->contexts_idr, ph);
+       if (ctx) {
+               ret = cxl_irq(irq, ctx, &irq_info);
+               rcu_read_unlock();
+               return ret;
+       }
+       rcu_read_unlock();
+
+       WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %016llx DAR"
+               " %016llx\n(Possible AFU HW issue - was a term/remove acked"
+               " with outstanding transactions?)\n", ph, irq_info.dsisr,
+               irq_info.dar);
+       return fail_psl_irq(afu, &irq_info);
+}
+
+static irqreturn_t native_slice_irq_err(int irq, void *data)
+{
+       struct cxl_afu *afu = data;
+       u64 fir_slice, errstat, serr, afu_debug;
+
+       WARN(irq, "CXL SLICE ERROR interrupt %i\n", irq);
+
+       serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
+       fir_slice = cxl_p1n_read(afu, CXL_PSL_FIR_SLICE_An);
+       errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
+       afu_debug = cxl_p1n_read(afu, CXL_AFU_DEBUG_An);
+       dev_crit(&afu->dev, "PSL_SERR_An: 0x%016llx\n", serr);
+       dev_crit(&afu->dev, "PSL_FIR_SLICE_An: 0x%016llx\n", fir_slice);
+       dev_crit(&afu->dev, "CXL_PSL_ErrStat_An: 0x%016llx\n", errstat);
+       dev_crit(&afu->dev, "CXL_PSL_AFU_DEBUG_An: 0x%016llx\n", afu_debug);
+
+       cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t native_irq_err(int irq, void *data)
+{
+       struct cxl *adapter = data;
+       u64 fir1, fir2, err_ivte;
+
+       WARN(1, "CXL ERROR interrupt %i\n", irq);
+
+       err_ivte = cxl_p1_read(adapter, CXL_PSL_ErrIVTE);
+       dev_crit(&adapter->dev, "PSL_ErrIVTE: 0x%016llx\n", err_ivte);
+
+       dev_crit(&adapter->dev, "STOPPING CXL TRACE\n");
+       cxl_stop_trace(adapter);
+
+       fir1 = cxl_p1_read(adapter, CXL_PSL_FIR1);
+       fir2 = cxl_p1_read(adapter, CXL_PSL_FIR2);
+
+       dev_crit(&adapter->dev, "PSL_FIR1: 0x%016llx\nPSL_FIR2: 0x%016llx\n", fir1, fir2);
+
+       return IRQ_HANDLED;
+}
+
+int cxl_native_register_psl_err_irq(struct cxl *adapter)
+{
+       int rc;
+
+       adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
+                                     dev_name(&adapter->dev));
+       if (!adapter->irq_name)
+               return -ENOMEM;
+
+       if ((rc = cxl_register_one_irq(adapter, native_irq_err, adapter,
+                                      &adapter->native->err_hwirq,
+                                      &adapter->native->err_virq,
+                                      adapter->irq_name))) {
+               kfree(adapter->irq_name);
+               adapter->irq_name = NULL;
+               return rc;
+       }
+
+       cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->native->err_hwirq & 0xffff);
+
+       return 0;
+}
+
+void cxl_native_release_psl_err_irq(struct cxl *adapter)
+{
+       if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
+               return;
+
+       cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
+       cxl_unmap_irq(adapter->native->err_virq, adapter);
+       cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
+       kfree(adapter->irq_name);
+}
+
+int cxl_native_register_serr_irq(struct cxl_afu *afu)
+{
+       u64 serr;
+       int rc;
+
+       afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
+                                     dev_name(&afu->dev));
+       if (!afu->err_irq_name)
+               return -ENOMEM;
+
+       if ((rc = cxl_register_one_irq(afu->adapter, native_slice_irq_err, afu,
+                                      &afu->serr_hwirq,
+                                      &afu->serr_virq, afu->err_irq_name))) {
+               kfree(afu->err_irq_name);
+               afu->err_irq_name = NULL;
+               return rc;
+       }
+
+       serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
+       serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
+       cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
 
        return 0;
 }
 
+void cxl_native_release_serr_irq(struct cxl_afu *afu)
+{
+       if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+               return;
+
+       cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
+       cxl_unmap_irq(afu->serr_virq, afu);
+       cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
+       kfree(afu->err_irq_name);
+}
+
+int cxl_native_register_psl_irq(struct cxl_afu *afu)
+{
+       int rc;
+
+       afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s",
+                                     dev_name(&afu->dev));
+       if (!afu->psl_irq_name)
+               return -ENOMEM;
+
+       if ((rc = cxl_register_one_irq(afu->adapter, native_irq_multiplexed,
+                                   afu, &afu->native->psl_hwirq, &afu->native->psl_virq,
+                                   afu->psl_irq_name))) {
+               kfree(afu->psl_irq_name);
+               afu->psl_irq_name = NULL;
+       }
+       return rc;
+}
+
+void cxl_native_release_psl_irq(struct cxl_afu *afu)
+{
+       if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
+               return;
+
+       cxl_unmap_irq(afu->native->psl_virq, afu);
+       cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
+       kfree(afu->psl_irq_name);
+}
+
 static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
 {
        u64 dsisr;
@@ -769,7 +951,7 @@ static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
        cxl_p2n_write(afu, CXL_PSL_ErrStat_An, errstat);
 }
 
-int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask)
+static int native_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask)
 {
        trace_cxl_psl_irq_ack(ctx, tfc);
        if (tfc)
@@ -784,3 +966,132 @@ int cxl_check_error(struct cxl_afu *afu)
 {
        return (cxl_p1n_read(afu, CXL_PSL_SCNTL_An) == ~0ULL);
 }
+
+static bool native_support_attributes(const char *attr_name,
+                                     enum cxl_attrs type)
+{
+       return true;
+}
+
+static int native_afu_cr_read64(struct cxl_afu *afu, int cr, u64 off, u64 *out)
+{
+       if (unlikely(!cxl_ops->link_ok(afu->adapter, afu)))
+               return -EIO;
+       if (unlikely(off >= afu->crs_len))
+               return -ERANGE;
+       *out = in_le64(afu->native->afu_desc_mmio + afu->crs_offset +
+               (cr * afu->crs_len) + off);
+       return 0;
+}
+
+static int native_afu_cr_read32(struct cxl_afu *afu, int cr, u64 off, u32 *out)
+{
+       if (unlikely(!cxl_ops->link_ok(afu->adapter, afu)))
+               return -EIO;
+       if (unlikely(off >= afu->crs_len))
+               return -ERANGE;
+       *out = in_le32(afu->native->afu_desc_mmio + afu->crs_offset +
+               (cr * afu->crs_len) + off);
+       return 0;
+}
+
+static int native_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off, u16 *out)
+{
+       u64 aligned_off = off & ~0x3L;
+       u32 val;
+       int rc;
+
+       rc = native_afu_cr_read32(afu, cr, aligned_off, &val);
+       if (!rc)
+               *out = (val >> ((off & 0x3) * 8)) & 0xffff;
+       return rc;
+}
+
+static int native_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off, u8 *out)
+{
+       u64 aligned_off = off & ~0x3L;
+       u32 val;
+       int rc;
+
+       rc = native_afu_cr_read32(afu, cr, aligned_off, &val);
+       if (!rc)
+               *out = (val >> ((off & 0x3) * 8)) & 0xff;
+       return rc;
+}
+
+static int native_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in)
+{
+       if (unlikely(!cxl_ops->link_ok(afu->adapter, afu)))
+               return -EIO;
+       if (unlikely(off >= afu->crs_len))
+               return -ERANGE;
+       out_le32(afu->native->afu_desc_mmio + afu->crs_offset +
+               (cr * afu->crs_len) + off, in);
+       return 0;
+}
+
+static int native_afu_cr_write16(struct cxl_afu *afu, int cr, u64 off, u16 in)
+{
+       u64 aligned_off = off & ~0x3L;
+       u32 val32, mask, shift;
+       int rc;
+
+       rc = native_afu_cr_read32(afu, cr, aligned_off, &val32);
+       if (rc)
+               return rc;
+       shift = (off & 0x3) * 8;
+       WARN_ON(shift == 24);
+       mask = 0xffff << shift;
+       val32 = (val32 & ~mask) | (in << shift);
+
+       rc = native_afu_cr_write32(afu, cr, aligned_off, val32);
+       return rc;
+}
+
+static int native_afu_cr_write8(struct cxl_afu *afu, int cr, u64 off, u8 in)
+{
+       u64 aligned_off = off & ~0x3L;
+       u32 val32, mask, shift;
+       int rc;
+
+       rc = native_afu_cr_read32(afu, cr, aligned_off, &val32);
+       if (rc)
+               return rc;
+       shift = (off & 0x3) * 8;
+       mask = 0xff << shift;
+       val32 = (val32 & ~mask) | (in << shift);
+
+       rc = native_afu_cr_write32(afu, cr, aligned_off, val32);
+       return rc;
+}
+
+const struct cxl_backend_ops cxl_native_ops = {
+       .module = THIS_MODULE,
+       .adapter_reset = cxl_pci_reset,
+       .alloc_one_irq = cxl_pci_alloc_one_irq,
+       .release_one_irq = cxl_pci_release_one_irq,
+       .alloc_irq_ranges = cxl_pci_alloc_irq_ranges,
+       .release_irq_ranges = cxl_pci_release_irq_ranges,
+       .setup_irq = cxl_pci_setup_irq,
+       .handle_psl_slice_error = native_handle_psl_slice_error,
+       .psl_interrupt = NULL,
+       .ack_irq = native_ack_irq,
+       .attach_process = native_attach_process,
+       .detach_process = native_detach_process,
+       .support_attributes = native_support_attributes,
+       .link_ok = cxl_adapter_link_ok,
+       .release_afu = cxl_pci_release_afu,
+       .afu_read_err_buffer = cxl_pci_afu_read_err_buffer,
+       .afu_check_and_enable = native_afu_check_and_enable,
+       .afu_activate_mode = native_afu_activate_mode,
+       .afu_deactivate_mode = native_afu_deactivate_mode,
+       .afu_reset = native_afu_reset,
+       .afu_cr_read8 = native_afu_cr_read8,
+       .afu_cr_read16 = native_afu_cr_read16,
+       .afu_cr_read32 = native_afu_cr_read32,
+       .afu_cr_read64 = native_afu_cr_read64,
+       .afu_cr_write8 = native_afu_cr_write8,
+       .afu_cr_write16 = native_afu_cr_write16,
+       .afu_cr_write32 = native_afu_cr_write32,
+       .read_adapter_vpd = cxl_pci_read_adapter_vpd,
+};
diff --git a/drivers/misc/cxl/of.c b/drivers/misc/cxl/of.c
new file mode 100644 (file)
index 0000000..edc4583
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * Copyright 2015 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include "cxl.h"
+
+
+static const __be32 *read_prop_string(const struct device_node *np,
+                               const char *prop_name)
+{
+       const __be32 *prop;
+
+       prop = of_get_property(np, prop_name, NULL);
+       if (cxl_verbose && prop)
+               pr_info("%s: %s\n", prop_name, (char *) prop);
+       return prop;
+}
+
+static const __be32 *read_prop_dword(const struct device_node *np,
+                               const char *prop_name, u32 *val)
+{
+       const __be32 *prop;
+
+       prop = of_get_property(np, prop_name, NULL);
+       if (prop)
+               *val = be32_to_cpu(prop[0]);
+       if (cxl_verbose && prop)
+               pr_info("%s: %#x (%u)\n", prop_name, *val, *val);
+       return prop;
+}
+
+static const __be64 *read_prop64_dword(const struct device_node *np,
+                               const char *prop_name, u64 *val)
+{
+       const __be64 *prop;
+
+       prop = of_get_property(np, prop_name, NULL);
+       if (prop)
+               *val = be64_to_cpu(prop[0]);
+       if (cxl_verbose && prop)
+               pr_info("%s: %#llx (%llu)\n", prop_name, *val, *val);
+       return prop;
+}
+
+
+static int read_handle(struct device_node *np, u64 *handle)
+{
+       const __be32 *prop;
+       u64 size;
+
+       /* Get address and size of the node */
+       prop = of_get_address(np, 0, &size, NULL);
+       if (size)
+               return -EINVAL;
+
+       /* Helper to read a big number; size is in cells (not bytes) */
+       *handle = of_read_number(prop, of_n_addr_cells(np));
+       return 0;
+}
+
+static int read_phys_addr(struct device_node *np, char *prop_name,
+                       struct cxl_afu *afu)
+{
+       int i, len, entry_size, naddr, nsize, type;
+       u64 addr, size;
+       const __be32 *prop;
+
+       naddr = of_n_addr_cells(np);
+       nsize = of_n_size_cells(np);
+
+       prop = of_get_property(np, prop_name, &len);
+       if (prop) {
+               entry_size = naddr + nsize;
+               for (i = 0; i < (len / 4); i += entry_size, prop += entry_size) {
+                       type = be32_to_cpu(prop[0]);
+                       addr = of_read_number(prop, naddr);
+                       size = of_read_number(&prop[naddr], nsize);
+                       switch (type) {
+                       case 0: /* unit address */
+                               afu->guest->handle = addr;
+                               break;
+                       case 1: /* p2 area */
+                               afu->guest->p2n_phys += addr;
+                               afu->guest->p2n_size = size;
+                               break;
+                       case 2: /* problem state area */
+                               afu->psn_phys += addr;
+                               afu->adapter->ps_size = size;
+                               break;
+                       default:
+                               pr_err("Invalid address type %d found in %s property of AFU\n",
+                                       type, prop_name);
+                               return -EINVAL;
+                       }
+                       if (cxl_verbose)
+                               pr_info("%s: %#x %#llx (size %#llx)\n",
+                                       prop_name, type, addr, size);
+               }
+       }
+       return 0;
+}
+
+static int read_vpd(struct cxl *adapter, struct cxl_afu *afu)
+{
+       char vpd[256];
+       int rc;
+       size_t len = sizeof(vpd);
+
+       memset(vpd, 0, len);
+
+       if (adapter)
+               rc = cxl_guest_read_adapter_vpd(adapter, vpd, len);
+       else
+               rc = cxl_guest_read_afu_vpd(afu, vpd, len);
+
+       if (rc > 0) {
+               cxl_dump_debug_buffer(vpd, rc);
+               rc = 0;
+       }
+       return rc;
+}
+
+int cxl_of_read_afu_handle(struct cxl_afu *afu, struct device_node *afu_np)
+{
+       if (read_handle(afu_np, &afu->guest->handle))
+               return -EINVAL;
+       pr_devel("AFU handle: 0x%.16llx\n", afu->guest->handle);
+
+       return 0;
+}
+
+int cxl_of_read_afu_properties(struct cxl_afu *afu, struct device_node *np)
+{
+       int i, len, rc;
+       char *p;
+       const __be32 *prop;
+       u16 device_id, vendor_id;
+       u32 val = 0, class_code;
+
+       /* Properties are read in the same order as listed in PAPR */
+
+       if (cxl_verbose) {
+               pr_info("Dump of the 'ibm,coherent-platform-function' node properties:\n");
+
+               prop = of_get_property(np, "compatible", &len);
+               i = 0;
+               while (i < len) {
+                       p = (char *) prop + i;
+                       pr_info("compatible: %s\n", p);
+                       i += strlen(p) + 1;
+               }
+               read_prop_string(np, "name");
+       }
+
+       rc = read_phys_addr(np, "reg", afu);
+       if (rc)
+               return rc;
+
+       rc = read_phys_addr(np, "assigned-addresses", afu);
+       if (rc)
+               return rc;
+
+       if (afu->psn_phys == 0)
+               afu->psa = false;
+       else
+               afu->psa = true;
+
+       if (cxl_verbose) {
+               read_prop_string(np, "ibm,loc-code");
+               read_prop_string(np, "device_type");
+       }
+
+       read_prop_dword(np, "ibm,#processes", &afu->max_procs_virtualised);
+
+       if (cxl_verbose) {
+               read_prop_dword(np, "ibm,scratchpad-size", &val);
+               read_prop_dword(np, "ibm,programmable", &val);
+               read_prop_string(np, "ibm,phandle");
+               read_vpd(NULL, afu);
+       }
+
+       read_prop_dword(np, "ibm,max-ints-per-process", &afu->guest->max_ints);
+       afu->irqs_max = afu->guest->max_ints;
+
+       prop = read_prop_dword(np, "ibm,min-ints-per-process", &afu->pp_irqs);
+       if (prop) {
+               /* One extra interrupt for the PSL interrupt is already
+                * included. Remove it now to keep only AFU interrupts and
+                * match the native case.
+                */
+               afu->pp_irqs--;
+       }
+
+       if (cxl_verbose) {
+               read_prop_dword(np, "ibm,max-ints", &val);
+               read_prop_dword(np, "ibm,vpd-size", &val);
+       }
+
+       read_prop64_dword(np, "ibm,error-buffer-size", &afu->eb_len);
+       afu->eb_offset = 0;
+
+       if (cxl_verbose)
+               read_prop_dword(np, "ibm,config-record-type", &val);
+
+       read_prop64_dword(np, "ibm,config-record-size", &afu->crs_len);
+       afu->crs_offset = 0;
+
+       read_prop_dword(np, "ibm,#config-records", &afu->crs_num);
+
+       if (cxl_verbose) {
+               for (i = 0; i < afu->crs_num; i++) {
+                       rc = cxl_ops->afu_cr_read16(afu, i, PCI_DEVICE_ID,
+                                               &device_id);
+                       if (!rc)
+                               pr_info("record %d - device-id: %#x\n",
+                                       i, device_id);
+                       rc = cxl_ops->afu_cr_read16(afu, i, PCI_VENDOR_ID,
+                                               &vendor_id);
+                       if (!rc)
+                               pr_info("record %d - vendor-id: %#x\n",
+                                       i, vendor_id);
+                       rc = cxl_ops->afu_cr_read32(afu, i, PCI_CLASS_REVISION,
+                                               &class_code);
+                       if (!rc) {
+                               class_code >>= 8;
+                               pr_info("record %d - class-code: %#x\n",
+                                       i, class_code);
+                       }
+               }
+
+               read_prop_dword(np, "ibm,function-number", &val);
+               read_prop_dword(np, "ibm,privileged-function", &val);
+               read_prop_dword(np, "vendor-id", &val);
+               read_prop_dword(np, "device-id", &val);
+               read_prop_dword(np, "revision-id", &val);
+               read_prop_dword(np, "class-code", &val);
+               read_prop_dword(np, "subsystem-vendor-id", &val);
+               read_prop_dword(np, "subsystem-id", &val);
+       }
+       /*
+        * if "ibm,process-mmio" doesn't exist then per-process mmio is
+        * not supported
+        */
+       val = 0;
+       prop = read_prop_dword(np, "ibm,process-mmio", &val);
+       if (prop && val == 1)
+               afu->pp_psa = true;
+       else
+               afu->pp_psa = false;
+
+       if (cxl_verbose) {
+               read_prop_dword(np, "ibm,supports-aur", &val);
+               read_prop_dword(np, "ibm,supports-csrp", &val);
+               read_prop_dword(np, "ibm,supports-prr", &val);
+       }
+
+       prop = read_prop_dword(np, "ibm,function-error-interrupt", &val);
+       if (prop)
+               afu->serr_hwirq = val;
+
+       pr_devel("AFU handle: %#llx\n", afu->guest->handle);
+       pr_devel("p2n_phys: %#llx (size %#llx)\n",
+               afu->guest->p2n_phys, afu->guest->p2n_size);
+       pr_devel("psn_phys: %#llx (size %#llx)\n",
+               afu->psn_phys, afu->adapter->ps_size);
+       pr_devel("Max number of processes virtualised=%i\n",
+               afu->max_procs_virtualised);
+       pr_devel("Per-process irqs min=%i, max=%i\n", afu->pp_irqs,
+                afu->irqs_max);
+       pr_devel("Slice error interrupt=%#lx\n", afu->serr_hwirq);
+
+       return 0;
+}
+
+static int read_adapter_irq_config(struct cxl *adapter, struct device_node *np)
+{
+       const __be32 *ranges;
+       int len, nranges, i;
+       struct irq_avail *cur;
+
+       ranges = of_get_property(np, "interrupt-ranges", &len);
+       if (ranges == NULL || len < (2 * sizeof(int)))
+               return -EINVAL;
+
+       /*
+        * encoded array of two cells per entry, each cell encoded as
+        * with encode-int
+        */
+       nranges = len / (2 * sizeof(int));
+       if (nranges == 0 || (nranges * 2 * sizeof(int)) != len)
+               return -EINVAL;
+
+       adapter->guest->irq_avail = kzalloc(nranges * sizeof(struct irq_avail),
+                                           GFP_KERNEL);
+       if (adapter->guest->irq_avail == NULL)
+               return -ENOMEM;
+
+       adapter->guest->irq_base_offset = be32_to_cpu(ranges[0]);
+       for (i = 0; i < nranges; i++) {
+               cur = &adapter->guest->irq_avail[i];
+               cur->offset = be32_to_cpu(ranges[i * 2]);
+               cur->range  = be32_to_cpu(ranges[i * 2 + 1]);
+               cur->bitmap = kcalloc(BITS_TO_LONGS(cur->range),
+                               sizeof(*cur->bitmap), GFP_KERNEL);
+               if (cur->bitmap == NULL)
+                       goto err;
+               if (cur->offset < adapter->guest->irq_base_offset)
+                       adapter->guest->irq_base_offset = cur->offset;
+               if (cxl_verbose)
+                       pr_info("available IRQ range: %#lx-%#lx (%lu)\n",
+                               cur->offset, cur->offset + cur->range - 1,
+                               cur->range);
+       }
+       adapter->guest->irq_nranges = nranges;
+       spin_lock_init(&adapter->guest->irq_alloc_lock);
+
+       return 0;
+err:
+       for (i--; i >= 0; i--) {
+               cur = &adapter->guest->irq_avail[i];
+               kfree(cur->bitmap);
+       }
+       kfree(adapter->guest->irq_avail);
+       adapter->guest->irq_avail = NULL;
+       return -ENOMEM;
+}
+
+int cxl_of_read_adapter_handle(struct cxl *adapter, struct device_node *np)
+{
+       if (read_handle(np, &adapter->guest->handle))
+               return -EINVAL;
+       pr_devel("Adapter handle: 0x%.16llx\n", adapter->guest->handle);
+
+       return 0;
+}
+
+int cxl_of_read_adapter_properties(struct cxl *adapter, struct device_node *np)
+{
+       int rc, len, naddr, i;
+       char *p;
+       const __be32 *prop;
+       u32 val = 0;
+
+       /* Properties are read in the same order as listed in PAPR */
+
+       naddr = of_n_addr_cells(np);
+
+       if (cxl_verbose) {
+               pr_info("Dump of the 'ibm,coherent-platform-facility' node properties:\n");
+
+               read_prop_dword(np, "#address-cells", &val);
+               read_prop_dword(np, "#size-cells", &val);
+
+               prop = of_get_property(np, "compatible", &len);
+               i = 0;
+               while (i < len) {
+                       p = (char *) prop + i;
+                       pr_info("compatible: %s\n", p);
+                       i += strlen(p) + 1;
+               }
+               read_prop_string(np, "name");
+               read_prop_string(np, "model");
+
+               prop = of_get_property(np, "reg", NULL);
+               if (prop) {
+                       pr_info("reg: addr:%#llx size:%#x\n",
+                               of_read_number(prop, naddr),
+                               be32_to_cpu(prop[naddr]));
+               }
+
+               read_prop_string(np, "ibm,loc-code");
+       }
+
+       if ((rc = read_adapter_irq_config(adapter, np)))
+               return rc;
+
+       if (cxl_verbose) {
+               read_prop_string(np, "device_type");
+               read_prop_string(np, "ibm,phandle");
+       }
+
+       prop = read_prop_dword(np, "ibm,caia-version", &val);
+       if (prop) {
+               adapter->caia_major = (val & 0xFF00) >> 8;
+               adapter->caia_minor = val & 0xFF;
+       }
+
+       prop = read_prop_dword(np, "ibm,psl-revision", &val);
+       if (prop)
+               adapter->psl_rev = val;
+
+       prop = read_prop_string(np, "status");
+       if (prop) {
+               adapter->guest->status = kasprintf(GFP_KERNEL, "%s", (char *) prop);
+               if (adapter->guest->status == NULL)
+                       return -ENOMEM;
+       }
+
+       prop = read_prop_dword(np, "vendor-id", &val);
+       if (prop)
+               adapter->guest->vendor = val;
+
+       prop = read_prop_dword(np, "device-id", &val);
+       if (prop)
+               adapter->guest->device = val;
+
+       if (cxl_verbose) {
+               read_prop_dword(np, "ibm,privileged-facility", &val);
+               read_prop_dword(np, "revision-id", &val);
+               read_prop_dword(np, "class-code", &val);
+       }
+
+       prop = read_prop_dword(np, "subsystem-vendor-id", &val);
+       if (prop)
+               adapter->guest->subsystem_vendor = val;
+
+       prop = read_prop_dword(np, "subsystem-id", &val);
+       if (prop)
+               adapter->guest->subsystem = val;
+
+       if (cxl_verbose)
+               read_vpd(adapter, NULL);
+
+       return 0;
+}
+
+static int cxl_of_remove(struct platform_device *pdev)
+{
+       struct cxl *adapter;
+       int afu;
+
+       adapter = dev_get_drvdata(&pdev->dev);
+       for (afu = 0; afu < adapter->slices; afu++)
+               cxl_guest_remove_afu(adapter->afu[afu]);
+
+       cxl_guest_remove_adapter(adapter);
+       return 0;
+}
+
+static void cxl_of_shutdown(struct platform_device *pdev)
+{
+       cxl_of_remove(pdev);
+}
+
+int cxl_of_probe(struct platform_device *pdev)
+{
+       struct device_node *np = NULL;
+       struct device_node *afu_np = NULL;
+       struct cxl *adapter = NULL;
+       int ret;
+       int slice, slice_ok;
+
+       pr_devel("in %s\n", __func__);
+
+       np = pdev->dev.of_node;
+       if (np == NULL)
+               return -ENODEV;
+
+       /* init adapter */
+       adapter = cxl_guest_init_adapter(np, pdev);
+       if (IS_ERR(adapter)) {
+               dev_err(&pdev->dev, "guest_init_adapter failed: %li\n", PTR_ERR(adapter));
+               return PTR_ERR(adapter);
+       }
+
+       /* init afu */
+       slice_ok = 0;
+       for (afu_np = NULL, slice = 0; (afu_np = of_get_next_child(np, afu_np)); slice++) {
+               if ((ret = cxl_guest_init_afu(adapter, slice, afu_np)))
+                       dev_err(&pdev->dev, "AFU %i failed to initialise: %i\n",
+                               slice, ret);
+               else
+                       slice_ok++;
+       }
+
+       if (slice_ok == 0) {
+               dev_info(&pdev->dev, "No active AFU");
+               adapter->slices = 0;
+       }
+
+       if (afu_np)
+               of_node_put(afu_np);
+       return 0;
+}
+
+static const struct of_device_id cxl_of_match[] = {
+       { .compatible = "ibm,coherent-platform-facility",},
+       {},
+};
+MODULE_DEVICE_TABLE(of, cxl_of_match);
+
+struct platform_driver cxl_of_driver = {
+       .driver = {
+               .name = "cxl_of",
+               .of_match_table = cxl_of_match,
+               .owner = THIS_MODULE
+       },
+       .probe = cxl_of_probe,
+       .remove = cxl_of_remove,
+       .shutdown = cxl_of_shutdown,
+};
index a896083..2844e97 100644 (file)
@@ -89,8 +89,8 @@
 
 /* This works a little different than the p1/p2 register accesses to make it
  * easier to pull out individual fields */
-#define AFUD_READ(afu, off)            in_be64(afu->afu_desc_mmio + off)
-#define AFUD_READ_LE(afu, off)         in_le64(afu->afu_desc_mmio + off)
+#define AFUD_READ(afu, off)            in_be64(afu->native->afu_desc_mmio + off)
+#define AFUD_READ_LE(afu, off)         in_le64(afu->native->afu_desc_mmio + off)
 #define EXTRACT_PPC_BIT(val, bit)      (!!(val & PPC_BIT(bit)))
 #define EXTRACT_PPC_BITS(val, bs, be)  ((val & PPC_BITMASK(bs, be)) >> PPC_BITLSHIFT(be))
 
 #define   AFUD_EB_LEN(val)             EXTRACT_PPC_BITS(val, 8, 63)
 #define AFUD_READ_EB_OFF(afu)          AFUD_READ(afu, 0x48)
 
-u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off)
-{
-       u64 aligned_off = off & ~0x3L;
-       u32 val;
-
-       val = cxl_afu_cr_read32(afu, cr, aligned_off);
-       return (val >> ((off & 0x2) * 8)) & 0xffff;
-}
-
-u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off)
-{
-       u64 aligned_off = off & ~0x3L;
-       u32 val;
-
-       val = cxl_afu_cr_read32(afu, cr, aligned_off);
-       return (val >> ((off & 0x3) * 8)) & 0xff;
-}
-
 static const struct pci_device_id cxl_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x0477), },
        { PCI_DEVICE(PCI_VENDOR_ID_IBM, 0x044b), },
@@ -432,8 +414,8 @@ static int init_implementation_afu_regs(struct cxl_afu *afu)
        return 0;
 }
 
-int cxl_setup_irq(struct cxl *adapter, unsigned int hwirq,
-                        unsigned int virq)
+int cxl_pci_setup_irq(struct cxl *adapter, unsigned int hwirq,
+               unsigned int virq)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
 
@@ -475,28 +457,30 @@ int cxl_update_image_control(struct cxl *adapter)
        return 0;
 }
 
-int cxl_alloc_one_irq(struct cxl *adapter)
+int cxl_pci_alloc_one_irq(struct cxl *adapter)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
 
        return pnv_cxl_alloc_hwirqs(dev, 1);
 }
 
-void cxl_release_one_irq(struct cxl *adapter, int hwirq)
+void cxl_pci_release_one_irq(struct cxl *adapter, int hwirq)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
 
        return pnv_cxl_release_hwirqs(dev, hwirq, 1);
 }
 
-int cxl_alloc_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter, unsigned int num)
+int cxl_pci_alloc_irq_ranges(struct cxl_irq_ranges *irqs,
+                       struct cxl *adapter, unsigned int num)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
 
        return pnv_cxl_alloc_hwirq_ranges(irqs, dev, num);
 }
 
-void cxl_release_irq_ranges(struct cxl_irq_ranges *irqs, struct cxl *adapter)
+void cxl_pci_release_irq_ranges(struct cxl_irq_ranges *irqs,
+                               struct cxl *adapter)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
 
@@ -557,7 +541,7 @@ static int switch_card_to_cxl(struct pci_dev *dev)
        return 0;
 }
 
-static int cxl_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev)
+static int pci_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev)
 {
        u64 p1n_base, p2n_base, afu_desc;
        const u64 p1n_size = 0x100;
@@ -565,15 +549,15 @@ static int cxl_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct p
 
        p1n_base = p1_base(dev) + 0x10000 + (afu->slice * p1n_size);
        p2n_base = p2_base(dev) + (afu->slice * p2n_size);
-       afu->psn_phys = p2_base(dev) + (adapter->ps_off + (afu->slice * adapter->ps_size));
-       afu_desc = p2_base(dev) + adapter->afu_desc_off + (afu->slice * adapter->afu_desc_size);
+       afu->psn_phys = p2_base(dev) + (adapter->native->ps_off + (afu->slice * adapter->ps_size));
+       afu_desc = p2_base(dev) + adapter->native->afu_desc_off + (afu->slice * adapter->native->afu_desc_size);
 
-       if (!(afu->p1n_mmio = ioremap(p1n_base, p1n_size)))
+       if (!(afu->native->p1n_mmio = ioremap(p1n_base, p1n_size)))
                goto err;
        if (!(afu->p2n_mmio = ioremap(p2n_base, p2n_size)))
                goto err1;
        if (afu_desc) {
-               if (!(afu->afu_desc_mmio = ioremap(afu_desc, adapter->afu_desc_size)))
+               if (!(afu->native->afu_desc_mmio = ioremap(afu_desc, adapter->native->afu_desc_size)))
                        goto err2;
        }
 
@@ -581,62 +565,41 @@ static int cxl_map_slice_regs(struct cxl_afu *afu, struct cxl *adapter, struct p
 err2:
        iounmap(afu->p2n_mmio);
 err1:
-       iounmap(afu->p1n_mmio);
+       iounmap(afu->native->p1n_mmio);
 err:
        dev_err(&afu->dev, "Error mapping AFU MMIO regions\n");
        return -ENOMEM;
 }
 
-static void cxl_unmap_slice_regs(struct cxl_afu *afu)
+static void pci_unmap_slice_regs(struct cxl_afu *afu)
 {
        if (afu->p2n_mmio) {
                iounmap(afu->p2n_mmio);
                afu->p2n_mmio = NULL;
        }
-       if (afu->p1n_mmio) {
-               iounmap(afu->p1n_mmio);
-               afu->p1n_mmio = NULL;
+       if (afu->native->p1n_mmio) {
+               iounmap(afu->native->p1n_mmio);
+               afu->native->p1n_mmio = NULL;
        }
-       if (afu->afu_desc_mmio) {
-               iounmap(afu->afu_desc_mmio);
-               afu->afu_desc_mmio = NULL;
+       if (afu->native->afu_desc_mmio) {
+               iounmap(afu->native->afu_desc_mmio);
+               afu->native->afu_desc_mmio = NULL;
        }
 }
 
-static void cxl_release_afu(struct device *dev)
+void cxl_pci_release_afu(struct device *dev)
 {
        struct cxl_afu *afu = to_cxl_afu(dev);
 
-       pr_devel("cxl_release_afu\n");
+       pr_devel("%s\n", __func__);
 
        idr_destroy(&afu->contexts_idr);
        cxl_release_spa(afu);
 
+       kfree(afu->native);
        kfree(afu);
 }
 
-static struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice)
-{
-       struct cxl_afu *afu;
-
-       if (!(afu = kzalloc(sizeof(struct cxl_afu), GFP_KERNEL)))
-               return NULL;
-
-       afu->adapter = adapter;
-       afu->dev.parent = &adapter->dev;
-       afu->dev.release = cxl_release_afu;
-       afu->slice = slice;
-       idr_init(&afu->contexts_idr);
-       mutex_init(&afu->contexts_lock);
-       spin_lock_init(&afu->afu_cntl_lock);
-       mutex_init(&afu->spa_mutex);
-
-       afu->prefault_mode = CXL_PREFAULT_NONE;
-       afu->irqs_max = afu->adapter->user_irqs;
-
-       return afu;
-}
-
 /* Expects AFU struct to have recently been zeroed out */
 static int cxl_read_afu_descriptor(struct cxl_afu *afu)
 {
@@ -658,7 +621,7 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)
        afu->pp_size = AFUD_PPPSA_LEN(val) * 4096;
        afu->psa = AFUD_PPPSA_PSA(val);
        if ((afu->pp_psa = AFUD_PPPSA_PP(val)))
-               afu->pp_offset = AFUD_READ_PPPSA_OFF(afu);
+               afu->native->pp_offset = AFUD_READ_PPPSA_OFF(afu);
 
        val = AFUD_READ_CR(afu);
        afu->crs_len = AFUD_CR_LEN(val) * 256;
@@ -685,10 +648,11 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)
 
 static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu)
 {
-       int i;
+       int i, rc;
+       u32 val;
 
        if (afu->psa && afu->adapter->ps_size <
-                       (afu->pp_offset + afu->pp_size*afu->max_procs_virtualised)) {
+                       (afu->native->pp_offset + afu->pp_size*afu->max_procs_virtualised)) {
                dev_err(&afu->dev, "per-process PSA can't fit inside the PSA!\n");
                return -ENODEV;
        }
@@ -697,7 +661,8 @@ static int cxl_afu_descriptor_looks_ok(struct cxl_afu *afu)
                dev_warn(&afu->dev, "AFU uses < PAGE_SIZE per-process PSA!");
 
        for (i = 0; i < afu->crs_num; i++) {
-               if ((cxl_afu_cr_read32(afu, i, 0) == 0)) {
+               rc = cxl_ops->afu_cr_read32(afu, i, 0, &val);
+               if (rc || val == 0) {
                        dev_err(&afu->dev, "ABORTING: AFU configuration record %i is invalid\n", i);
                        return -EINVAL;
                }
@@ -718,7 +683,7 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
        reg = cxl_p2n_read(afu, CXL_AFU_Cntl_An);
        if ((reg & CXL_AFU_Cntl_An_ES_MASK) != CXL_AFU_Cntl_An_ES_Disabled) {
                dev_warn(&afu->dev, "WARNING: AFU was not disabled: %#016llx\n", reg);
-               if (__cxl_afu_reset(afu))
+               if (cxl_ops->afu_reset(afu))
                        return -EIO;
                if (cxl_afu_disable(afu))
                        return -EIO;
@@ -766,13 +731,13 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
  * 4/8 bytes aligned access. So in case the requested offset/count arent 8 byte
  * aligned the function uses a bounce buffer which can be max PAGE_SIZE.
  */
-ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
+ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
                                loff_t off, size_t count)
 {
        loff_t aligned_start, aligned_end;
        size_t aligned_length;
        void *tbuf;
-       const void __iomem *ebuf = afu->afu_desc_mmio + afu->eb_offset;
+       const void __iomem *ebuf = afu->native->afu_desc_mmio + afu->eb_offset;
 
        if (count == 0 || off < 0 || (size_t)off >= afu->eb_len)
                return 0;
@@ -803,18 +768,18 @@ ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
        return count;
 }
 
-static int cxl_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev)
+static int pci_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pci_dev *dev)
 {
        int rc;
 
-       if ((rc = cxl_map_slice_regs(afu, adapter, dev)))
+       if ((rc = pci_map_slice_regs(afu, adapter, dev)))
                return rc;
 
        if ((rc = sanitise_afu_regs(afu)))
                goto err1;
 
        /* We need to reset the AFU before we can read the AFU descriptor */
-       if ((rc = __cxl_afu_reset(afu)))
+       if ((rc = cxl_ops->afu_reset(afu)))
                goto err1;
 
        if (cxl_verbose)
@@ -829,44 +794,50 @@ static int cxl_configure_afu(struct cxl_afu *afu, struct cxl *adapter, struct pc
        if ((rc = init_implementation_afu_regs(afu)))
                goto err1;
 
-       if ((rc = cxl_register_serr_irq(afu)))
+       if ((rc = cxl_native_register_serr_irq(afu)))
                goto err1;
 
-       if ((rc = cxl_register_psl_irq(afu)))
+       if ((rc = cxl_native_register_psl_irq(afu)))
                goto err2;
 
        return 0;
 
 err2:
-       cxl_release_serr_irq(afu);
+       cxl_native_release_serr_irq(afu);
 err1:
-       cxl_unmap_slice_regs(afu);
+       pci_unmap_slice_regs(afu);
        return rc;
 }
 
-static void cxl_deconfigure_afu(struct cxl_afu *afu)
+static void pci_deconfigure_afu(struct cxl_afu *afu)
 {
-       cxl_release_psl_irq(afu);
-       cxl_release_serr_irq(afu);
-       cxl_unmap_slice_regs(afu);
+       cxl_native_release_psl_irq(afu);
+       cxl_native_release_serr_irq(afu);
+       pci_unmap_slice_regs(afu);
 }
 
-static int cxl_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev)
+static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev)
 {
        struct cxl_afu *afu;
-       int rc;
+       int rc = -ENOMEM;
 
        afu = cxl_alloc_afu(adapter, slice);
        if (!afu)
                return -ENOMEM;
 
+       afu->native = kzalloc(sizeof(struct cxl_afu_native), GFP_KERNEL);
+       if (!afu->native)
+               goto err_free_afu;
+
+       mutex_init(&afu->native->spa_mutex);
+
        rc = dev_set_name(&afu->dev, "afu%i.%i", adapter->adapter_num, slice);
        if (rc)
-               goto err_free;
+               goto err_free_native;
 
-       rc = cxl_configure_afu(afu, adapter, dev);
+       rc = pci_configure_afu(afu, adapter, dev);
        if (rc)
-               goto err_free;
+               goto err_free_native;
 
        /* Don't care if this fails */
        cxl_debugfs_afu_add(afu);
@@ -889,24 +860,27 @@ static int cxl_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev)
        return 0;
 
 err_put1:
-       cxl_deconfigure_afu(afu);
+       pci_deconfigure_afu(afu);
        cxl_debugfs_afu_remove(afu);
        device_unregister(&afu->dev);
        return rc;
 
-err_free:
+err_free_native:
+       kfree(afu->native);
+err_free_afu:
        kfree(afu);
        return rc;
 
 }
 
-static void cxl_remove_afu(struct cxl_afu *afu)
+static void cxl_pci_remove_afu(struct cxl_afu *afu)
 {
-       pr_devel("cxl_remove_afu\n");
+       pr_devel("%s\n", __func__);
 
        if (!afu)
                return;
 
+       cxl_pci_vphb_remove(afu);
        cxl_sysfs_afu_remove(afu);
        cxl_debugfs_afu_remove(afu);
 
@@ -915,13 +889,13 @@ static void cxl_remove_afu(struct cxl_afu *afu)
        spin_unlock(&afu->adapter->afu_list_lock);
 
        cxl_context_detach_all(afu);
-       cxl_afu_deactivate_mode(afu);
+       cxl_ops->afu_deactivate_mode(afu, afu->current_mode);
 
-       cxl_deconfigure_afu(afu);
+       pci_deconfigure_afu(afu);
        device_unregister(&afu->dev);
 }
 
-int cxl_reset(struct cxl *adapter)
+int cxl_pci_reset(struct cxl *adapter)
 {
        struct pci_dev *dev = to_pci_dev(adapter->dev.parent);
        int rc;
@@ -955,17 +929,17 @@ static int cxl_map_adapter_regs(struct cxl *adapter, struct pci_dev *dev)
        pr_devel("cxl_map_adapter_regs: p1: %#016llx %#llx, p2: %#016llx %#llx",
                        p1_base(dev), p1_size(dev), p2_base(dev), p2_size(dev));
 
-       if (!(adapter->p1_mmio = ioremap(p1_base(dev), p1_size(dev))))
+       if (!(adapter->native->p1_mmio = ioremap(p1_base(dev), p1_size(dev))))
                goto err3;
 
-       if (!(adapter->p2_mmio = ioremap(p2_base(dev), p2_size(dev))))
+       if (!(adapter->native->p2_mmio = ioremap(p2_base(dev), p2_size(dev))))
                goto err4;
 
        return 0;
 
 err4:
-       iounmap(adapter->p1_mmio);
-       adapter->p1_mmio = NULL;
+       iounmap(adapter->native->p1_mmio);
+       adapter->native->p1_mmio = NULL;
 err3:
        pci_release_region(dev, 0);
 err2:
@@ -976,14 +950,14 @@ err1:
 
 static void cxl_unmap_adapter_regs(struct cxl *adapter)
 {
-       if (adapter->p1_mmio) {
-               iounmap(adapter->p1_mmio);
-               adapter->p1_mmio = NULL;
+       if (adapter->native->p1_mmio) {
+               iounmap(adapter->native->p1_mmio);
+               adapter->native->p1_mmio = NULL;
                pci_release_region(to_pci_dev(adapter->dev.parent), 2);
        }
-       if (adapter->p2_mmio) {
-               iounmap(adapter->p2_mmio);
-               adapter->p2_mmio = NULL;
+       if (adapter->native->p2_mmio) {
+               iounmap(adapter->native->p2_mmio);
+               adapter->native->p2_mmio = NULL;
                pci_release_region(to_pci_dev(adapter->dev.parent), 0);
        }
 }
@@ -1024,10 +998,10 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev)
 
        /* Convert everything to bytes, because there is NO WAY I'd look at the
         * code a month later and forget what units these are in ;-) */
-       adapter->ps_off = ps_off * 64 * 1024;
+       adapter->native->ps_off = ps_off * 64 * 1024;
        adapter->ps_size = ps_size * 64 * 1024;
-       adapter->afu_desc_off = afu_desc_off * 64 * 1024;
-       adapter->afu_desc_size = afu_desc_size *64 * 1024;
+       adapter->native->afu_desc_off = afu_desc_off * 64 * 1024;
+       adapter->native->afu_desc_size = afu_desc_size * 64 * 1024;
 
        /* Total IRQs - 1 PSL ERROR - #AFU*(1 slice error + 1 DSI) */
        adapter->user_irqs = pnv_cxl_get_irq_count(dev) - 1 - 2*adapter->slices;
@@ -1078,21 +1052,26 @@ static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
                return -EINVAL;
        }
 
-       if (!adapter->afu_desc_off || !adapter->afu_desc_size) {
+       if (!adapter->native->afu_desc_off || !adapter->native->afu_desc_size) {
                dev_err(&dev->dev, "ABORTING: VSEC shows no AFU descriptors\n");
                return -EINVAL;
        }
 
-       if (adapter->ps_size > p2_size(dev) - adapter->ps_off) {
+       if (adapter->ps_size > p2_size(dev) - adapter->native->ps_off) {
                dev_err(&dev->dev, "ABORTING: Problem state size larger than "
                                   "available in BAR2: 0x%llx > 0x%llx\n",
-                        adapter->ps_size, p2_size(dev) - adapter->ps_off);
+                        adapter->ps_size, p2_size(dev) - adapter->native->ps_off);
                return -EINVAL;
        }
 
        return 0;
 }
 
+ssize_t cxl_pci_read_adapter_vpd(struct cxl *adapter, void *buf, size_t len)
+{
+       return pci_read_vpd(to_pci_dev(adapter->dev.parent), 0, len, buf);
+}
+
 static void cxl_release_adapter(struct device *dev)
 {
        struct cxl *adapter = to_cxl_adapter(dev);
@@ -1101,33 +1080,10 @@ static void cxl_release_adapter(struct device *dev)
 
        cxl_remove_adapter_nr(adapter);
 
+       kfree(adapter->native);
        kfree(adapter);
 }
 
-static struct cxl *cxl_alloc_adapter(void)
-{
-       struct cxl *adapter;
-
-       if (!(adapter = kzalloc(sizeof(struct cxl), GFP_KERNEL)))
-               return NULL;
-
-       spin_lock_init(&adapter->afu_list_lock);
-
-       if (cxl_alloc_adapter_nr(adapter))
-               goto err1;
-
-       if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
-               goto err2;
-
-       return adapter;
-
-err2:
-       cxl_remove_adapter_nr(adapter);
-err1:
-       kfree(adapter);
-       return NULL;
-}
-
 #define CXL_PSL_ErrIVTE_tberror (0x1ull << (63-31))
 
 static int sanitise_adapter_regs(struct cxl *adapter)
@@ -1191,7 +1147,7 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
        if ((rc = cxl_setup_psl_timebase(adapter, dev)))
                goto err;
 
-       if ((rc = cxl_register_psl_err_irq(adapter)))
+       if ((rc = cxl_native_register_psl_err_irq(adapter)))
                goto err;
 
        return 0;
@@ -1206,13 +1162,13 @@ static void cxl_deconfigure_adapter(struct cxl *adapter)
 {
        struct pci_dev *pdev = to_pci_dev(adapter->dev.parent);
 
-       cxl_release_psl_err_irq(adapter);
+       cxl_native_release_psl_err_irq(adapter);
        cxl_unmap_adapter_regs(adapter);
 
        pci_disable_device(pdev);
 }
 
-static struct cxl *cxl_init_adapter(struct pci_dev *dev)
+static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev)
 {
        struct cxl *adapter;
        int rc;
@@ -1221,6 +1177,12 @@ static struct cxl *cxl_init_adapter(struct pci_dev *dev)
        if (!adapter)
                return ERR_PTR(-ENOMEM);
 
+       adapter->native = kzalloc(sizeof(struct cxl_native), GFP_KERNEL);
+       if (!adapter->native) {
+               rc = -ENOMEM;
+               goto err_release;
+       }
+
        /* Set defaults for parameters which need to persist over
         * configure/reconfigure
         */
@@ -1230,8 +1192,7 @@ static struct cxl *cxl_init_adapter(struct pci_dev *dev)
        rc = cxl_configure_adapter(adapter, dev);
        if (rc) {
                pci_disable_device(dev);
-               cxl_release_adapter(&adapter->dev);
-               return ERR_PTR(rc);
+               goto err_release;
        }
 
        /* Don't care if this one fails: */
@@ -1257,9 +1218,13 @@ err_put1:
        cxl_deconfigure_adapter(adapter);
        device_unregister(&adapter->dev);
        return ERR_PTR(rc);
+
+err_release:
+       cxl_release_adapter(&adapter->dev);
+       return ERR_PTR(rc);
 }
 
-static void cxl_remove_adapter(struct cxl *adapter)
+static void cxl_pci_remove_adapter(struct cxl *adapter)
 {
        pr_devel("cxl_remove_adapter\n");
 
@@ -1277,17 +1242,22 @@ static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id)
        int slice;
        int rc;
 
+       if (cxl_pci_is_vphb_device(dev)) {
+               dev_dbg(&dev->dev, "cxl_init_adapter: Ignoring cxl vphb device\n");
+               return -ENODEV;
+       }
+
        if (cxl_verbose)
                dump_cxl_config_space(dev);
 
-       adapter = cxl_init_adapter(dev);
+       adapter = cxl_pci_init_adapter(dev);
        if (IS_ERR(adapter)) {
                dev_err(&dev->dev, "cxl_init_adapter failed: %li\n", PTR_ERR(adapter));
                return PTR_ERR(adapter);
        }
 
        for (slice = 0; slice < adapter->slices; slice++) {
-               if ((rc = cxl_init_afu(adapter, slice, dev))) {
+               if ((rc = pci_init_afu(adapter, slice, dev))) {
                        dev_err(&dev->dev, "AFU %i failed to initialise: %i\n", slice, rc);
                        continue;
                }
@@ -1312,10 +1282,9 @@ static void cxl_remove(struct pci_dev *dev)
         */
        for (i = 0; i < adapter->slices; i++) {
                afu = adapter->afu[i];
-               cxl_pci_vphb_remove(afu);
-               cxl_remove_afu(afu);
+               cxl_pci_remove_afu(afu);
        }
-       cxl_remove_adapter(adapter);
+       cxl_pci_remove_adapter(adapter);
 }
 
 static pci_ers_result_t cxl_vphb_error_detected(struct cxl_afu *afu,
@@ -1461,8 +1430,8 @@ static pci_ers_result_t cxl_pci_error_detected(struct pci_dev *pdev,
                        return result;
 
                cxl_context_detach_all(afu);
-               cxl_afu_deactivate_mode(afu);
-               cxl_deconfigure_afu(afu);
+               cxl_ops->afu_deactivate_mode(afu, afu->current_mode);
+               pci_deconfigure_afu(afu);
        }
        cxl_deconfigure_adapter(adapter);
 
@@ -1485,14 +1454,12 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev)
        for (i = 0; i < adapter->slices; i++) {
                afu = adapter->afu[i];
 
-               if (cxl_configure_afu(afu, adapter, pdev))
+               if (pci_configure_afu(afu, adapter, pdev))
                        goto err;
 
                if (cxl_afu_select_best_mode(afu))
                        goto err;
 
-               cxl_pci_vphb_reconfigure(afu);
-
                list_for_each_entry(afu_dev, &afu->phb->bus->devices, bus_list) {
                        /* Reset the device context.
                         * TODO: make this less disruptive
@@ -1508,7 +1475,7 @@ static pci_ers_result_t cxl_pci_slot_reset(struct pci_dev *pdev)
 
                        afu_dev->dev.archdata.cxl_ctx = ctx;
 
-                       if (cxl_afu_check_and_enable(afu))
+                       if (cxl_ops->afu_check_and_enable(afu))
                                goto err;
 
                        afu_dev->error_state = pci_channel_io_normal;
index 038af5d..25913c0 100644 (file)
@@ -69,7 +69,7 @@ static ssize_t reset_adapter_store(struct device *device,
        if ((rc != 1) || (val != 1))
                return -EINVAL;
 
-       if ((rc = cxl_reset(adapter)))
+       if ((rc = cxl_ops->adapter_reset(adapter)))
                return rc;
        return count;
 }
@@ -165,7 +165,7 @@ static ssize_t pp_mmio_off_show(struct device *device,
 {
        struct cxl_afu *afu = to_afu_chardev_m(device);
 
-       return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->pp_offset);
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", afu->native->pp_offset);
 }
 
 static ssize_t pp_mmio_len_show(struct device *device,
@@ -211,7 +211,7 @@ static ssize_t reset_store_afu(struct device *device,
                goto err;
        }
 
-       if ((rc = __cxl_afu_reset(afu)))
+       if ((rc = cxl_ops->afu_reset(afu)))
                goto err;
 
        rc = count;
@@ -253,8 +253,14 @@ static ssize_t irqs_max_store(struct device *device,
        if (irqs_max < afu->pp_irqs)
                return -EINVAL;
 
-       if (irqs_max > afu->adapter->user_irqs)
-               return -EINVAL;
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               if (irqs_max > afu->adapter->user_irqs)
+                       return -EINVAL;
+       } else {
+               /* pHyp sets a per-AFU limit */
+               if (irqs_max > afu->guest->max_ints)
+                       return -EINVAL;
+       }
 
        afu->irqs_max = irqs_max;
        return count;
@@ -348,7 +354,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,
        }
 
        /*
-        * cxl_afu_deactivate_mode needs to be done outside the lock, prevent
+        * afu_deactivate_mode needs to be done outside the lock, prevent
         * other contexts coming in before we are ready:
         */
        old_mode = afu->current_mode;
@@ -357,9 +363,9 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,
 
        mutex_unlock(&afu->contexts_lock);
 
-       if ((rc = _cxl_afu_deactivate_mode(afu, old_mode)))
+       if ((rc = cxl_ops->afu_deactivate_mode(afu, old_mode)))
                return rc;
-       if ((rc = cxl_afu_activate_mode(afu, mode)))
+       if ((rc = cxl_ops->afu_activate_mode(afu, mode)))
                return rc;
 
        return count;
@@ -388,7 +394,7 @@ static ssize_t afu_eb_read(struct file *filp, struct kobject *kobj,
 {
        struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj));
 
-       return cxl_afu_read_err_buffer(afu, buf, off, count);
+       return cxl_ops->afu_read_err_buffer(afu, buf, off, count);
 }
 
 static struct device_attribute afu_attrs[] = {
@@ -405,24 +411,39 @@ static struct device_attribute afu_attrs[] = {
 
 int cxl_sysfs_adapter_add(struct cxl *adapter)
 {
+       struct device_attribute *dev_attr;
        int i, rc;
 
        for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) {
-               if ((rc = device_create_file(&adapter->dev, &adapter_attrs[i])))
-                       goto err;
+               dev_attr = &adapter_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_ADAPTER_ATTRS)) {
+                       if ((rc = device_create_file(&adapter->dev, dev_attr)))
+                               goto err;
+               }
        }
        return 0;
 err:
-       for (i--; i >= 0; i--)
-               device_remove_file(&adapter->dev, &adapter_attrs[i]);
+       for (i--; i >= 0; i--) {
+               dev_attr = &adapter_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_ADAPTER_ATTRS))
+                       device_remove_file(&adapter->dev, dev_attr);
+       }
        return rc;
 }
+
 void cxl_sysfs_adapter_remove(struct cxl *adapter)
 {
+       struct device_attribute *dev_attr;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++)
-               device_remove_file(&adapter->dev, &adapter_attrs[i]);
+       for (i = 0; i < ARRAY_SIZE(adapter_attrs); i++) {
+               dev_attr = &adapter_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_ADAPTER_ATTRS))
+                       device_remove_file(&adapter->dev, dev_attr);
+       }
 }
 
 struct afu_config_record {
@@ -468,10 +489,12 @@ static ssize_t afu_read_config(struct file *filp, struct kobject *kobj,
        struct afu_config_record *cr = to_cr(kobj);
        struct cxl_afu *afu = to_cxl_afu(kobj_to_dev(kobj->parent));
 
-       u64 i, j, val;
+       u64 i, j, val, rc;
 
        for (i = 0; i < count;) {
-               val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7);
+               rc = cxl_ops->afu_cr_read64(afu, cr->cr, off & ~0x7, &val);
+               if (rc)
+                       val = ~0ULL;
                for (j = off & 0x7; j < 8 && i < count; i++, j++, off++)
                        buf[i] = (val >> (j * 8)) & 0xff;
        }
@@ -516,14 +539,22 @@ static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int c
                return ERR_PTR(-ENOMEM);
 
        cr->cr = cr_idx;
-       cr->device = cxl_afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID);
-       cr->vendor = cxl_afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID);
-       cr->class = cxl_afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION) >> 8;
+
+       rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_DEVICE_ID, &cr->device);
+       if (rc)
+               goto err;
+       rc = cxl_ops->afu_cr_read16(afu, cr_idx, PCI_VENDOR_ID, &cr->vendor);
+       if (rc)
+               goto err;
+       rc = cxl_ops->afu_cr_read32(afu, cr_idx, PCI_CLASS_REVISION, &cr->class);
+       if (rc)
+               goto err;
+       cr->class >>= 8;
 
        /*
         * Export raw AFU PCIe like config record. For now this is read only by
         * root - we can expand that later to be readable by non-root and maybe
-        * even writable provided we have a good use-case. Once we suport
+        * even writable provided we have a good use-case. Once we support
         * exposing AFUs through a virtual PHB they will get that for free from
         * Linux' PCI infrastructure, but until then it's not clear that we
         * need it for anything since the main use case is just identifying
@@ -561,6 +592,7 @@ err:
 
 void cxl_sysfs_afu_remove(struct cxl_afu *afu)
 {
+       struct device_attribute *dev_attr;
        struct afu_config_record *cr, *tmp;
        int i;
 
@@ -568,8 +600,12 @@ void cxl_sysfs_afu_remove(struct cxl_afu *afu)
        if (afu->eb_len)
                device_remove_bin_file(&afu->dev, &afu->attr_eb);
 
-       for (i = 0; i < ARRAY_SIZE(afu_attrs); i++)
-               device_remove_file(&afu->dev, &afu_attrs[i]);
+       for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
+               dev_attr = &afu_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_ATTRS))
+                       device_remove_file(&afu->dev, &afu_attrs[i]);
+       }
 
        list_for_each_entry_safe(cr, tmp, &afu->crs, list) {
                sysfs_remove_bin_file(&cr->kobj, &cr->config_attr);
@@ -579,14 +615,19 @@ void cxl_sysfs_afu_remove(struct cxl_afu *afu)
 
 int cxl_sysfs_afu_add(struct cxl_afu *afu)
 {
+       struct device_attribute *dev_attr;
        struct afu_config_record *cr;
        int i, rc;
 
        INIT_LIST_HEAD(&afu->crs);
 
        for (i = 0; i < ARRAY_SIZE(afu_attrs); i++) {
-               if ((rc = device_create_file(&afu->dev, &afu_attrs[i])))
-                       goto err;
+               dev_attr = &afu_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_ATTRS)) {
+                       if ((rc = device_create_file(&afu->dev, &afu_attrs[i])))
+                               goto err;
+               }
        }
 
        /* conditionally create the add the binary file for error info buffer */
@@ -625,32 +666,50 @@ err:
        /* reset the eb_len as we havent created the bin attr */
        afu->eb_len = 0;
 
-       for (i--; i >= 0; i--)
+       for (i--; i >= 0; i--) {
+               dev_attr = &afu_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_ATTRS))
                device_remove_file(&afu->dev, &afu_attrs[i]);
+       }
        return rc;
 }
 
 int cxl_sysfs_afu_m_add(struct cxl_afu *afu)
 {
+       struct device_attribute *dev_attr;
        int i, rc;
 
        for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) {
-               if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i])))
-                       goto err;
+               dev_attr = &afu_master_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_MASTER_ATTRS)) {
+                       if ((rc = device_create_file(afu->chardev_m, &afu_master_attrs[i])))
+                               goto err;
+               }
        }
 
        return 0;
 
 err:
-       for (i--; i >= 0; i--)
-               device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
+       for (i--; i >= 0; i--) {
+               dev_attr = &afu_master_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_MASTER_ATTRS))
+                       device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
+       }
        return rc;
 }
 
 void cxl_sysfs_afu_m_remove(struct cxl_afu *afu)
 {
+       struct device_attribute *dev_attr;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++)
-               device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
+       for (i = 0; i < ARRAY_SIZE(afu_master_attrs); i++) {
+               dev_attr = &afu_master_attrs[i];
+               if (cxl_ops->support_attributes(dev_attr->attr.name,
+                                               CXL_AFU_MASTER_ATTRS))
+                       device_remove_file(afu->chardev_m, &afu_master_attrs[i]);
+       }
 }
index 6e1e2ad..751d611 100644 (file)
@@ -450,6 +450,199 @@ DEFINE_EVENT(cxl_pe_class, cxl_slbia,
        TP_ARGS(ctx)
 );
 
+TRACE_EVENT(cxl_hcall,
+       TP_PROTO(u64 unit_address, u64 process_token, long rc),
+
+       TP_ARGS(unit_address, process_token, rc),
+
+       TP_STRUCT__entry(
+               __field(u64, unit_address)
+               __field(u64, process_token)
+               __field(long, rc)
+       ),
+
+       TP_fast_assign(
+               __entry->unit_address = unit_address;
+               __entry->process_token = process_token;
+               __entry->rc = rc;
+       ),
+
+       TP_printk("unit_address=0x%016llx process_token=0x%016llx rc=%li",
+               __entry->unit_address,
+               __entry->process_token,
+               __entry->rc
+       )
+);
+
+TRACE_EVENT(cxl_hcall_control,
+       TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3,
+       u64 p4, unsigned long r4, long rc),
+
+       TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc),
+
+       TP_STRUCT__entry(
+               __field(u64, unit_address)
+               __field(char *, fct)
+               __field(u64, p1)
+               __field(u64, p2)
+               __field(u64, p3)
+               __field(u64, p4)
+               __field(unsigned long, r4)
+               __field(long, rc)
+       ),
+
+       TP_fast_assign(
+               __entry->unit_address = unit_address;
+               __entry->fct = fct;
+               __entry->p1 = p1;
+               __entry->p2 = p2;
+               __entry->p3 = p3;
+               __entry->p4 = p4;
+               __entry->r4 = r4;
+               __entry->rc = rc;
+       ),
+
+       TP_printk("unit_address=%#.16llx %s(%#llx, %#llx, %#llx, %#llx, R4: %#lx)): %li",
+               __entry->unit_address,
+               __entry->fct,
+               __entry->p1,
+               __entry->p2,
+               __entry->p3,
+               __entry->p4,
+               __entry->r4,
+               __entry->rc
+       )
+);
+
+TRACE_EVENT(cxl_hcall_attach,
+       TP_PROTO(u64 unit_address, u64 phys_addr, unsigned long process_token,
+               unsigned long mmio_addr, unsigned long mmio_size, long rc),
+
+       TP_ARGS(unit_address, phys_addr, process_token,
+               mmio_addr, mmio_size, rc),
+
+       TP_STRUCT__entry(
+               __field(u64, unit_address)
+               __field(u64, phys_addr)
+               __field(unsigned long, process_token)
+               __field(unsigned long, mmio_addr)
+               __field(unsigned long, mmio_size)
+               __field(long, rc)
+       ),
+
+       TP_fast_assign(
+               __entry->unit_address = unit_address;
+               __entry->phys_addr = phys_addr;
+               __entry->process_token = process_token;
+               __entry->mmio_addr = mmio_addr;
+               __entry->mmio_size = mmio_size;
+               __entry->rc = rc;
+       ),
+
+       TP_printk("unit_address=0x%016llx phys_addr=0x%016llx "
+               "token=0x%.8lx mmio_addr=0x%lx mmio_size=0x%lx rc=%li",
+               __entry->unit_address,
+               __entry->phys_addr,
+               __entry->process_token,
+               __entry->mmio_addr,
+               __entry->mmio_size,
+               __entry->rc
+       )
+);
+
+DEFINE_EVENT(cxl_hcall, cxl_hcall_detach,
+       TP_PROTO(u64 unit_address, u64 process_token, long rc),
+       TP_ARGS(unit_address, process_token, rc)
+);
+
+DEFINE_EVENT(cxl_hcall_control, cxl_hcall_control_function,
+       TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3,
+       u64 p4, unsigned long r4, long rc),
+       TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc)
+);
+
+DEFINE_EVENT(cxl_hcall, cxl_hcall_collect_int_info,
+       TP_PROTO(u64 unit_address, u64 process_token, long rc),
+       TP_ARGS(unit_address, process_token, rc)
+);
+
+TRACE_EVENT(cxl_hcall_control_faults,
+       TP_PROTO(u64 unit_address, u64 process_token,
+               u64 control_mask, u64 reset_mask, unsigned long r4,
+               long rc),
+
+       TP_ARGS(unit_address, process_token,
+               control_mask, reset_mask, r4, rc),
+
+       TP_STRUCT__entry(
+               __field(u64, unit_address)
+               __field(u64, process_token)
+               __field(u64, control_mask)
+               __field(u64, reset_mask)
+               __field(unsigned long, r4)
+               __field(long, rc)
+       ),
+
+       TP_fast_assign(
+               __entry->unit_address = unit_address;
+               __entry->process_token = process_token;
+               __entry->control_mask = control_mask;
+               __entry->reset_mask = reset_mask;
+               __entry->r4 = r4;
+               __entry->rc = rc;
+       ),
+
+       TP_printk("unit_address=0x%016llx process_token=0x%llx "
+               "control_mask=%#llx reset_mask=%#llx r4=%#lx rc=%li",
+               __entry->unit_address,
+               __entry->process_token,
+               __entry->control_mask,
+               __entry->reset_mask,
+               __entry->r4,
+               __entry->rc
+       )
+);
+
+DEFINE_EVENT(cxl_hcall_control, cxl_hcall_control_facility,
+       TP_PROTO(u64 unit_address, char *fct, u64 p1, u64 p2, u64 p3,
+       u64 p4, unsigned long r4, long rc),
+       TP_ARGS(unit_address, fct, p1, p2, p3, p4, r4, rc)
+);
+
+TRACE_EVENT(cxl_hcall_download_facility,
+       TP_PROTO(u64 unit_address, char *fct, u64 list_address, u64 num,
+       unsigned long r4, long rc),
+
+       TP_ARGS(unit_address, fct, list_address, num, r4, rc),
+
+       TP_STRUCT__entry(
+               __field(u64, unit_address)
+               __field(char *, fct)
+               __field(u64, list_address)
+               __field(u64, num)
+               __field(unsigned long, r4)
+               __field(long, rc)
+       ),
+
+       TP_fast_assign(
+               __entry->unit_address = unit_address;
+               __entry->fct = fct;
+               __entry->list_address = list_address;
+               __entry->num = num;
+               __entry->r4 = r4;
+               __entry->rc = rc;
+       ),
+
+       TP_printk("%#.16llx, %s(%#llx, %#llx), %#lx): %li",
+               __entry->unit_address,
+               __entry->fct,
+               __entry->list_address,
+               __entry->num,
+               __entry->r4,
+               __entry->rc
+       )
+);
+
 #endif /* _CXL_TRACE_H */
 
 /* This part must be outside protection */
index cbd4331..cdc7723 100644 (file)
@@ -49,7 +49,7 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev)
        phb = pci_bus_to_host(dev->bus);
        afu = (struct cxl_afu *)phb->private_data;
 
-       if (!cxl_adapter_link_ok(afu->adapter)) {
+       if (!cxl_ops->link_ok(afu->adapter, afu)) {
                dev_warn(&dev->dev, "%s: Device link is down, refusing to enable AFU\n", __func__);
                return false;
        }
@@ -66,7 +66,7 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev)
                return false;
        dev->dev.archdata.cxl_ctx = ctx;
 
-       return (cxl_afu_check_and_enable(afu) == 0);
+       return (cxl_ops->afu_check_and_enable(afu) == 0);
 }
 
 static void cxl_pci_disable_device(struct pci_dev *dev)
@@ -99,113 +99,90 @@ static int cxl_pcie_cfg_record(u8 bus, u8 devfn)
        return (bus << 8) + devfn;
 }
 
-static unsigned long cxl_pcie_cfg_addr(struct pci_controller* phb,
-                                      u8 bus, u8 devfn, int offset)
-{
-       int record = cxl_pcie_cfg_record(bus, devfn);
-
-       return (unsigned long)phb->cfg_addr + ((unsigned long)phb->cfg_data * record) + offset;
-}
-
-
 static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn,
-                               int offset, int len,
-                               volatile void __iomem **ioaddr,
-                               u32 *mask, int *shift)
+                               struct cxl_afu **_afu, int *_record)
 {
        struct pci_controller *phb;
        struct cxl_afu *afu;
-       unsigned long addr;
+       int record;
 
        phb = pci_bus_to_host(bus);
        if (phb == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       afu = (struct cxl_afu *)phb->private_data;
 
-       if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num)
+       afu = (struct cxl_afu *)phb->private_data;
+       record = cxl_pcie_cfg_record(bus->number, devfn);
+       if (record > afu->crs_num)
                return PCIBIOS_DEVICE_NOT_FOUND;
-       if (offset >= (unsigned long)phb->cfg_data)
-               return PCIBIOS_BAD_REGISTER_NUMBER;
-       addr = cxl_pcie_cfg_addr(phb, bus->number, devfn, offset);
 
-       *ioaddr = (void *)(addr & ~0x3ULL);
-       *shift = ((addr & 0x3) * 8);
-       switch (len) {
-       case 1:
-               *mask = 0xff;
-               break;
-       case 2:
-               *mask = 0xffff;
-               break;
-       default:
-               *mask = 0xffffffff;
-               break;
-       }
+       *_afu = afu;
+       *_record = record;
        return 0;
 }
 
-
-static inline bool cxl_config_link_ok(struct pci_bus *bus)
-{
-       struct pci_controller *phb;
-       struct cxl_afu *afu;
-
-       /* Config space IO is based on phb->cfg_addr, which is based on
-        * afu_desc_mmio. This isn't safe to read/write when the link
-        * goes down, as EEH tears down MMIO space.
-        *
-        * Check if the link is OK before proceeding.
-        */
-
-       phb = pci_bus_to_host(bus);
-       if (phb == NULL)
-               return false;
-       afu = (struct cxl_afu *)phb->private_data;
-       return cxl_adapter_link_ok(afu->adapter);
-}
-
 static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
                                int offset, int len, u32 *val)
 {
-       volatile void __iomem *ioaddr;
-       int shift, rc;
-       u32 mask;
+       int rc, record;
+       struct cxl_afu *afu;
+       u8 val8;
+       u16 val16;
+       u32 val32;
 
-       rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr,
-                                 &mask, &shift);
+       rc = cxl_pcie_config_info(bus, devfn, &afu, &record);
        if (rc)
                return rc;
 
-       if (!cxl_config_link_ok(bus))
+       switch (len) {
+       case 1:
+               rc = cxl_ops->afu_cr_read8(afu, record, offset, &val8);
+               *val = val8;
+               break;
+       case 2:
+               rc = cxl_ops->afu_cr_read16(afu, record, offset, &val16);
+               *val = val16;
+               break;
+       case 4:
+               rc = cxl_ops->afu_cr_read32(afu, record, offset, &val32);
+               *val = val32;
+               break;
+       default:
+               WARN_ON(1);
+       }
+
+       if (rc)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
-       /* Can only read 32 bits */
-       *val = (in_le32(ioaddr) >> shift) & mask;
        return PCIBIOS_SUCCESSFUL;
 }
 
 static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
                                 int offset, int len, u32 val)
 {
-       volatile void __iomem *ioaddr;
-       u32 v, mask;
-       int shift, rc;
+       int rc, record;
+       struct cxl_afu *afu;
 
-       rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr,
-                                 &mask, &shift);
+       rc = cxl_pcie_config_info(bus, devfn, &afu, &record);
        if (rc)
                return rc;
 
-       if (!cxl_config_link_ok(bus))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* Can only write 32 bits so do read-modify-write */
-       mask <<= shift;
-       val <<= shift;
+       switch (len) {
+       case 1:
+               rc = cxl_ops->afu_cr_write8(afu, record, offset, val & 0xff);
+               break;
+       case 2:
+               rc = cxl_ops->afu_cr_write16(afu, record, offset, val & 0xffff);
+               break;
+       case 4:
+               rc = cxl_ops->afu_cr_write32(afu, record, offset, val);
+               break;
+       default:
+               WARN_ON(1);
+       }
 
-       v = (in_le32(ioaddr) & ~mask) | (val & mask);
+       if (rc)
+               return PCIBIOS_SET_FAILED;
 
-       out_le32(ioaddr, v);
        return PCIBIOS_SUCCESSFUL;
 }
 
@@ -233,23 +210,31 @@ int cxl_pci_vphb_add(struct cxl_afu *afu)
 {
        struct pci_dev *phys_dev;
        struct pci_controller *phb, *phys_phb;
-
-       phys_dev = to_pci_dev(afu->adapter->dev.parent);
-       phys_phb = pci_bus_to_host(phys_dev->bus);
+       struct device_node *vphb_dn;
+       struct device *parent;
+
+       if (cpu_has_feature(CPU_FTR_HVMODE)) {
+               phys_dev = to_pci_dev(afu->adapter->dev.parent);
+               phys_phb = pci_bus_to_host(phys_dev->bus);
+               vphb_dn = phys_phb->dn;
+               parent = &phys_dev->dev;
+       } else {
+               vphb_dn = afu->adapter->dev.parent->of_node;
+               parent = afu->adapter->dev.parent;
+       }
 
        /* Alloc and setup PHB data structure */
-       phb = pcibios_alloc_controller(phys_phb->dn);
-
+       phb = pcibios_alloc_controller(vphb_dn);
        if (!phb)
                return -ENODEV;
 
        /* Setup parent in sysfs */
-       phb->parent = &phys_dev->dev;
+       phb->parent = parent;
 
        /* Setup the PHB using arch provided callback */
        phb->ops = &cxl_pcie_pci_ops;
-       phb->cfg_addr = afu->afu_desc_mmio + afu->crs_offset;
-       phb->cfg_data = (void *)(u64)afu->crs_len;
+       phb->cfg_addr = NULL;
+       phb->cfg_data = 0;
        phb->private_data = afu;
        phb->controller_ops = cxl_pci_controller_ops;
 
@@ -272,15 +257,6 @@ int cxl_pci_vphb_add(struct cxl_afu *afu)
        return 0;
 }
 
-void cxl_pci_vphb_reconfigure(struct cxl_afu *afu)
-{
-       /* When we are reconfigured, the AFU's MMIO space is unmapped
-        * and remapped. We need to reflect this in the PHB's view of
-        * the world.
-        */
-       afu->phb->cfg_addr = afu->afu_desc_mmio + afu->crs_offset;
-}
-
 void cxl_pci_vphb_remove(struct cxl_afu *afu)
 {
        struct pci_controller *phb;
@@ -296,6 +272,15 @@ void cxl_pci_vphb_remove(struct cxl_afu *afu)
        pcibios_free_controller(phb);
 }
 
+bool cxl_pci_is_vphb_device(struct pci_dev *dev)
+{
+       struct pci_controller *phb;
+
+       phb = pci_bus_to_host(dev->bus);
+
+       return (phb->ops == &cxl_pcie_pci_ops);
+}
+
 struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev)
 {
        struct pci_controller *phb;
index 3ce6095..6619178 100644 (file)
@@ -2959,7 +2959,7 @@ static int macb_probe(struct platform_device *pdev)
                int gpio = of_get_named_gpio(phy_node, "reset-gpios", 0);
                if (gpio_is_valid(gpio))
                        bp->reset_gpio = gpio_to_desc(gpio);
-               gpiod_set_value(bp->reset_gpio, GPIOD_OUT_HIGH);
+               gpiod_direction_output(bp->reset_gpio, 1);
        }
        of_node_put(phy_node);
 
@@ -3029,7 +3029,7 @@ static int macb_remove(struct platform_device *pdev)
                mdiobus_free(bp->mii_bus);
 
                /* Shutdown the PHY if there is a GPIO reset */
-               gpiod_set_value(bp->reset_gpio, GPIOD_OUT_LOW);
+               gpiod_set_value(bp->reset_gpio, 0);
 
                unregister_netdev(dev);
                clk_disable_unprepare(bp->tx_clk);
index 79a210a..ea83712 100644 (file)
@@ -35,6 +35,7 @@
 #include "fman.h"
 #include "fman_muram.h"
 
+#include <linux/fsl/guts.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/module.h>
@@ -1871,6 +1872,90 @@ err_fm_state:
        return -EINVAL;
 }
 
+static int fman_reset(struct fman *fman)
+{
+       u32 count;
+       int err = 0;
+
+       if (fman->state->rev_info.major < 6) {
+               iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc);
+               /* Wait for reset completion */
+               count = 100;
+               do {
+                       udelay(1);
+               } while (((ioread32be(&fman->fpm_regs->fm_rstc)) &
+                        FPM_RSTC_FM_RESET) && --count);
+               if (count == 0)
+                       err = -EBUSY;
+
+               goto _return;
+       } else {
+               struct device_node *guts_node;
+               struct ccsr_guts __iomem *guts_regs;
+               u32 devdisr2, reg;
+
+               /* Errata A007273 */
+               guts_node =
+                       of_find_compatible_node(NULL, NULL,
+                                               "fsl,qoriq-device-config-2.0");
+               if (!guts_node) {
+                       dev_err(fman->dev, "%s: Couldn't find guts node\n",
+                               __func__);
+                       goto guts_node;
+               }
+
+               guts_regs = of_iomap(guts_node, 0);
+               if (!guts_regs) {
+                       dev_err(fman->dev, "%s: Couldn't map %s regs\n",
+                               __func__, guts_node->full_name);
+                       goto guts_regs;
+               }
+#define FMAN1_ALL_MACS_MASK    0xFCC00000
+#define FMAN2_ALL_MACS_MASK    0x000FCC00
+               /* Read current state */
+               devdisr2 = ioread32be(&guts_regs->devdisr2);
+               if (fman->dts_params.id == 0)
+                       reg = devdisr2 & ~FMAN1_ALL_MACS_MASK;
+               else
+                       reg = devdisr2 & ~FMAN2_ALL_MACS_MASK;
+
+               /* Enable all MACs */
+               iowrite32be(reg, &guts_regs->devdisr2);
+
+               /* Perform FMan reset */
+               iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc);
+
+               /* Wait for reset completion */
+               count = 100;
+               do {
+                       udelay(1);
+               } while (((ioread32be(&fman->fpm_regs->fm_rstc)) &
+                        FPM_RSTC_FM_RESET) && --count);
+               if (count == 0) {
+                       iounmap(guts_regs);
+                       of_node_put(guts_node);
+                       err = -EBUSY;
+                       goto _return;
+               }
+
+               /* Restore devdisr2 value */
+               iowrite32be(devdisr2, &guts_regs->devdisr2);
+
+               iounmap(guts_regs);
+               of_node_put(guts_node);
+
+               goto _return;
+
+guts_regs:
+               of_node_put(guts_node);
+guts_node:
+               dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n",
+                       __func__);
+       }
+_return:
+       return err;
+}
+
 static int fman_init(struct fman *fman)
 {
        struct fman_cfg *cfg = NULL;
@@ -1914,22 +1999,9 @@ static int fman_init(struct fman *fman)
                fman->liodn_base[i] = liodn_base;
        }
 
-       /* FMan Reset (supported only for FMan V2) */
-       if (fman->state->rev_info.major >= 6) {
-               /* Errata A007273 */
-               dev_dbg(fman->dev, "%s: FManV3 reset is not supported!\n",
-                       __func__);
-       } else {
-               iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc);
-               /* Wait for reset completion */
-               count = 100;
-               do {
-                       udelay(1);
-               } while (((ioread32be(&fman->fpm_regs->fm_rstc)) &
-                        FPM_RSTC_FM_RESET) && --count);
-               if (count == 0)
-                       return -EBUSY;
-       }
+       err = fman_reset(fman);
+       if (err)
+               return err;
 
        if (ioread32be(&fman->qmi_regs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) {
                resume(fman->fpm_regs);
index 1cbcb9f..37d0cce 100644 (file)
@@ -147,6 +147,8 @@ enum hnae_led_state {
 
 #define HNSV2_TXD_BUFNUM_S 0
 #define HNSV2_TXD_BUFNUM_M (0x7 << HNSV2_TXD_BUFNUM_S)
+#define HNSV2_TXD_PORTID_S     4
+#define HNSV2_TXD_PORTID_M     (0X7 << HNSV2_TXD_PORTID_S)
 #define HNSV2_TXD_RI_B   1
 #define HNSV2_TXD_L4CS_B   2
 #define HNSV2_TXD_L3CS_B   3
@@ -516,6 +518,7 @@ struct hnae_handle {
        int q_num;
        int vf_id;
        u32 eport_id;
+       u32 dport_id;   /* v2 tx bd should fill the dport_id */
        enum hnae_port_type port_type;
        struct list_head node;    /* list to hnae_ae_dev->handle_list */
        struct hnae_buf_ops *bops; /* operation for the buffer */
index d4f92ed..285c893 100644 (file)
@@ -175,6 +175,7 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev,
        ae_handle->phy_node = vf_cb->mac_cb->phy_node;
        ae_handle->if_support = vf_cb->mac_cb->if_support;
        ae_handle->port_type = vf_cb->mac_cb->mac_type;
+       ae_handle->dport_id = port_idx;
 
        return ae_handle;
 vf_id_err:
@@ -419,7 +420,10 @@ static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable)
 
 static void hns_ae_set_promisc_mode(struct hnae_handle *handle, u32 en)
 {
+       struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
        hns_dsaf_set_promisc_mode(hns_ae_get_dsaf_dev(handle->dev), en);
+       hns_mac_set_promisc(mac_cb, (u8)!!en);
 }
 
 static int hns_ae_get_autoneg(struct hnae_handle *handle)
@@ -787,7 +791,8 @@ static int hns_ae_get_rss(struct hnae_handle *handle, u32 *indir, u8 *key,
                memcpy(key, ppe_cb->rss_key, HNS_PPEV2_RSS_KEY_SIZE);
 
        /* update the current hash->queue mappings from the shadow RSS table */
-       memcpy(indir, ppe_cb->rss_indir_table, HNS_PPEV2_RSS_IND_TBL_SIZE);
+       memcpy(indir, ppe_cb->rss_indir_table,
+              HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir));
 
        return 0;
 }
@@ -799,10 +804,11 @@ static int hns_ae_set_rss(struct hnae_handle *handle, const u32 *indir,
 
        /* set the RSS Hash Key if specififed by the user */
        if (key)
-               hns_ppe_set_rss_key(ppe_cb, (int *)key);
+               hns_ppe_set_rss_key(ppe_cb, (u32 *)key);
 
        /* update the shadow RSS table with user specified qids */
-       memcpy(ppe_cb->rss_indir_table, indir, HNS_PPEV2_RSS_IND_TBL_SIZE);
+       memcpy(ppe_cb->rss_indir_table, indir,
+              HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir));
 
        /* now update the hardware */
        hns_ppe_set_indir_table(ppe_cb, ppe_cb->rss_indir_table);
index b8517b0..6e2b76e 100644 (file)
@@ -290,6 +290,24 @@ static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed,
        return 0;
 }
 
+static void hns_gmac_set_uc_match(void *mac_drv, u16 en)
+{
+       struct mac_driver *drv = mac_drv;
+
+       dsaf_set_dev_bit(drv, GMAC_REC_FILT_CONTROL_REG,
+                        GMAC_UC_MATCH_EN_B, !en);
+       dsaf_set_dev_bit(drv, GMAC_STATION_ADDR_HIGH_2_REG,
+                        GMAC_ADDR_EN_B, !en);
+}
+
+static void hns_gmac_set_promisc(void *mac_drv, u8 en)
+{
+       struct mac_driver *drv = mac_drv;
+
+       if (drv->mac_cb->mac_type == HNAE_PORT_DEBUG)
+               hns_gmac_set_uc_match(mac_drv, en);
+}
+
 static void hns_gmac_init(void *mac_drv)
 {
        u32 port;
@@ -305,6 +323,8 @@ static void hns_gmac_init(void *mac_drv)
        mdelay(10);
        hns_gmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX);
        hns_gmac_tx_loop_pkt_dis(mac_drv);
+       if (drv->mac_cb->mac_type == HNAE_PORT_DEBUG)
+               hns_gmac_set_uc_match(mac_drv, 0);
 }
 
 void hns_gmac_update_stats(void *mac_drv)
@@ -402,14 +422,17 @@ static void hns_gmac_set_mac_addr(void *mac_drv, char *mac_addr)
 {
        struct mac_driver *drv = (struct mac_driver *)mac_drv;
 
-       if (drv->mac_id >= DSAF_SERVICE_NW_NUM) {
-               u32 high_val = mac_addr[1] | (mac_addr[0] << 8);
+       u32 high_val = mac_addr[1] | (mac_addr[0] << 8);
 
-               u32 low_val = mac_addr[5] | (mac_addr[4] << 8)
-                       | (mac_addr[3] << 16) | (mac_addr[2] << 24);
-               dsaf_write_dev(drv, GMAC_STATION_ADDR_LOW_2_REG, low_val);
-               dsaf_write_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG, high_val);
-       }
+       u32 low_val = mac_addr[5] | (mac_addr[4] << 8)
+               | (mac_addr[3] << 16) | (mac_addr[2] << 24);
+
+       u32 val = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG);
+       u32 sta_addr_en = dsaf_get_bit(val, GMAC_ADDR_EN_B);
+
+       dsaf_write_dev(drv, GMAC_STATION_ADDR_LOW_2_REG, low_val);
+       dsaf_write_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG,
+                      high_val | (sta_addr_en << GMAC_ADDR_EN_B));
 }
 
 static int hns_gmac_config_loopback(void *mac_drv, enum hnae_loop loop_mode,
@@ -699,6 +722,7 @@ void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
        mac_drv->get_sset_count = hns_gmac_get_sset_count;
        mac_drv->get_strings = hns_gmac_get_strings;
        mac_drv->update_stats = hns_gmac_update_stats;
+       mac_drv->set_promiscuous = hns_gmac_set_promisc;
 
        return (void *)mac_drv;
 }
index 5ef0e96..a38084a 100644 (file)
@@ -467,8 +467,13 @@ int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu)
        struct mac_driver *drv = hns_mac_get_drv(mac_cb);
        u32 buf_size = mac_cb->dsaf_dev->buf_size;
        u32 new_frm = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+       u32 max_frm = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver) ?
+                       MAC_MAX_MTU : MAC_MAX_MTU_V2;
 
-       if ((new_mtu < MAC_MIN_MTU) || (new_frm > MAC_MAX_MTU) ||
+       if (mac_cb->mac_type == HNAE_PORT_DEBUG)
+               max_frm = MAC_MAX_MTU_DBG;
+
+       if ((new_mtu < MAC_MIN_MTU) || (new_frm > max_frm) ||
            (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size))
                return -EINVAL;
 
@@ -861,6 +866,14 @@ int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset)
        return mac_ctrl_drv->get_sset_count(stringset);
 }
 
+void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en)
+{
+       struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+       if (mac_ctrl_drv->set_promiscuous)
+               mac_ctrl_drv->set_promiscuous(mac_ctrl_drv, en);
+}
+
 int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb)
 {
        struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
index 0b05219..823b6e7 100644 (file)
@@ -26,7 +26,9 @@ struct dsaf_device;
 
 #define MAC_DEFAULT_MTU        (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN + ETH_DATA_LEN)
 #define MAC_MAX_MTU            9600
+#define MAC_MAX_MTU_V2         9728
 #define MAC_MIN_MTU            68
+#define MAC_MAX_MTU_DBG                MAC_DEFAULT_MTU
 
 #define MAC_DEFAULT_PAUSE_TIME 0xff
 
@@ -365,7 +367,7 @@ struct mac_driver {
        /*config rx pause enable*/
        void (*set_rx_ignore_pause_frames)(void *mac_drv, u32 enable);
        /* config rx mode for promiscuous*/
-       int (*set_promiscuous)(void *mac_drv, u8 enable);
+       void (*set_promiscuous)(void *mac_drv, u8 enable);
        /* get mac id */
        void (*mac_get_id)(void *mac_drv, u8 *mac_id);
        void (*mac_pausefrm_cfg)(void *mac_drv, u32 rx_en, u32 tx_en);
@@ -453,4 +455,6 @@ int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb);
 void hns_set_led_opt(struct hns_mac_cb *mac_cb);
 int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb,
                        enum hnae_led_state status);
+void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en);
+
 #endif /* _HNS_DSAF_MAC_H */
index 38fc5be..5c1ac9b 100644 (file)
@@ -748,8 +748,9 @@ static void hns_dsaf_tbl_stat_en(struct dsaf_device *dsaf_dev)
  */
 static void hns_dsaf_rocee_bp_en(struct dsaf_device *dsaf_dev)
 {
-       dsaf_set_dev_bit(dsaf_dev, DSAF_XGE_CTRL_SIG_CFG_0_REG,
-                        DSAF_FC_XGE_TX_PAUSE_S, 1);
+       if (AE_IS_VER1(dsaf_dev->dsaf_ver))
+               dsaf_set_dev_bit(dsaf_dev, DSAF_XGE_CTRL_SIG_CFG_0_REG,
+                                DSAF_FC_XGE_TX_PAUSE_S, 1);
 }
 
 /* set msk for dsaf exception irq*/
index f302ef9..5b7ae5f 100644 (file)
@@ -27,7 +27,7 @@ void hns_ppe_set_tso_enable(struct hns_ppe_cb *ppe_cb, u32 value)
 void hns_ppe_set_rss_key(struct hns_ppe_cb *ppe_cb,
                         const u32 rss_key[HNS_PPEV2_RSS_KEY_NUM])
 {
-       int key_item = 0;
+       u32 key_item;
 
        for (key_item = 0; key_item < HNS_PPEV2_RSS_KEY_NUM; key_item++)
                dsaf_write_dev(ppe_cb, PPEV2_RSS_KEY_REG + key_item * 0x4,
@@ -343,6 +343,9 @@ static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb)
        if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) {
                hns_ppe_set_vlan_strip(ppe_cb, 0);
 
+               dsaf_write_dev(ppe_cb, PPE_CFG_MAX_FRAME_LEN_REG,
+                              HNS_PPEV2_MAX_FRAME_LEN);
+
                /* set default RSS key in h/w */
                hns_ppe_set_rss_key(ppe_cb, ppe_cb->rss_key);
 
index 0f5cb69..e9c0ec2 100644 (file)
@@ -30,6 +30,8 @@
 #define HNS_PPEV2_RSS_KEY_SIZE 40 /* in bytes or 320 bits */
 #define HNS_PPEV2_RSS_KEY_NUM (HNS_PPEV2_RSS_KEY_SIZE / sizeof(u32))
 
+#define HNS_PPEV2_MAX_FRAME_LEN 0X980
+
 enum ppe_qid_mode {
        PPE_QID_MODE0 = 0, /* fixed queue id mode */
        PPE_QID_MODE1,     /* switch:128VM non switch:6Port/4VM/4TC */
index 60d695d..bf62687 100644 (file)
 #define GMAC_LP_REG_CF2MI_LP_EN_B      2
 
 #define GMAC_MODE_CHANGE_EB_B  0
+#define GMAC_UC_MATCH_EN_B     0
+#define GMAC_ADDR_EN_B         16
 
 #define GMAC_RECV_CTRL_STRIP_PAD_EN_B  3
 #define GMAC_RECV_CTRL_RUNT_PKT_EN_B   4
index 3f77ff7..71aa37b 100644 (file)
@@ -48,7 +48,6 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
        struct iphdr *iphdr;
        struct ipv6hdr *ipv6hdr;
        struct sk_buff *skb;
-       int skb_tmp_len;
        __be16 protocol;
        u8 bn_pid = 0;
        u8 rrcfv = 0;
@@ -66,10 +65,14 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
        desc->addr = cpu_to_le64(dma);
        desc->tx.send_size = cpu_to_le16((u16)size);
 
-       /*config bd buffer end */
+       /* config bd buffer end */
        hnae_set_bit(rrcfv, HNSV2_TXD_VLD_B, 1);
        hnae_set_field(bn_pid, HNSV2_TXD_BUFNUM_M, 0, buf_num - 1);
 
+       /* fill port_id in the tx bd for sending management pkts */
+       hnae_set_field(bn_pid, HNSV2_TXD_PORTID_M,
+                      HNSV2_TXD_PORTID_S, ring->q->handle->dport_id);
+
        if (type == DESC_TYPE_SKB) {
                skb = (struct sk_buff *)priv;
 
@@ -90,13 +93,13 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
                                hnae_set_bit(rrcfv, HNSV2_TXD_L4CS_B, 1);
 
                                /* check for tcp/udp header */
-                               if (iphdr->protocol == IPPROTO_TCP) {
+                               if (iphdr->protocol == IPPROTO_TCP &&
+                                   skb_is_gso(skb)) {
                                        hnae_set_bit(tvsvsn,
                                                     HNSV2_TXD_TSE_B, 1);
-                                       skb_tmp_len = SKB_TMP_LEN(skb);
                                        l4_len = tcp_hdrlen(skb);
-                                       mss = mtu - skb_tmp_len - ETH_FCS_LEN;
-                                       paylen = skb->len - skb_tmp_len;
+                                       mss = skb_shinfo(skb)->gso_size;
+                                       paylen = skb->len - SKB_TMP_LEN(skb);
                                }
                        } else if (skb->protocol == htons(ETH_P_IPV6)) {
                                hnae_set_bit(tvsvsn, HNSV2_TXD_IPV6_B, 1);
@@ -104,13 +107,13 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
                                hnae_set_bit(rrcfv, HNSV2_TXD_L4CS_B, 1);
 
                                /* check for tcp/udp header */
-                               if (ipv6hdr->nexthdr == IPPROTO_TCP) {
+                               if (ipv6hdr->nexthdr == IPPROTO_TCP &&
+                                   skb_is_gso(skb) && skb_is_gso_v6(skb)) {
                                        hnae_set_bit(tvsvsn,
                                                     HNSV2_TXD_TSE_B, 1);
-                                       skb_tmp_len = SKB_TMP_LEN(skb);
                                        l4_len = tcp_hdrlen(skb);
-                                       mss = mtu - skb_tmp_len - ETH_FCS_LEN;
-                                       paylen = skb->len - skb_tmp_len;
+                                       mss = skb_shinfo(skb)->gso_size;
+                                       paylen = skb->len - SKB_TMP_LEN(skb);
                                }
                        }
                        desc->tx.ip_offset = ip_offset;
@@ -564,6 +567,7 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
        struct sk_buff *skb;
        struct hnae_desc *desc;
        struct hnae_desc_cb *desc_cb;
+       struct ethhdr *eh;
        unsigned char *va;
        int bnum, length, i;
        int pull_len;
@@ -670,6 +674,14 @@ out_bnum_err:
                return -EFAULT;
        }
 
+       /* filter out multicast pkt with the same src mac as this port */
+       eh = eth_hdr(skb);
+       if (unlikely(is_multicast_ether_addr(eh->h_dest) &&
+                    ether_addr_equal(ndev->dev_addr, eh->h_source))) {
+               dev_kfree_skb_any(skb);
+               return -EFAULT;
+       }
+
        ring->stats.rx_pkts++;
        ring->stats.rx_bytes += skb->len;
 
index 3c4a3bc..9c3ba65 100644 (file)
@@ -1173,18 +1173,15 @@ hns_get_rss_key_size(struct net_device *netdev)
 {
        struct hns_nic_priv *priv = netdev_priv(netdev);
        struct hnae_ae_ops *ops;
-       u32 ret;
 
        if (AE_IS_VER1(priv->enet_ver)) {
                netdev_err(netdev,
                           "RSS feature is not supported on this hardware\n");
-               return -EOPNOTSUPP;
+               return 0;
        }
 
        ops = priv->ae_handle->dev->ops;
-       ret = ops->get_rss_key_size(priv->ae_handle);
-
-       return ret;
+       return ops->get_rss_key_size(priv->ae_handle);
 }
 
 static u32
@@ -1192,18 +1189,15 @@ hns_get_rss_indir_size(struct net_device *netdev)
 {
        struct hns_nic_priv *priv = netdev_priv(netdev);
        struct hnae_ae_ops *ops;
-       u32 ret;
 
        if (AE_IS_VER1(priv->enet_ver)) {
                netdev_err(netdev,
                           "RSS feature is not supported on this hardware\n");
-               return -EOPNOTSUPP;
+               return 0;
        }
 
        ops = priv->ae_handle->dev->ops;
-       ret = ops->get_rss_indir_size(priv->ae_handle);
-
-       return ret;
+       return ops->get_rss_indir_size(priv->ae_handle);
 }
 
 static int
@@ -1211,7 +1205,6 @@ hns_get_rss(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc)
 {
        struct hns_nic_priv *priv = netdev_priv(netdev);
        struct hnae_ae_ops *ops;
-       int ret;
 
        if (AE_IS_VER1(priv->enet_ver)) {
                netdev_err(netdev,
@@ -1224,9 +1217,7 @@ hns_get_rss(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc)
        if (!indir)
                return 0;
 
-       ret = ops->get_rss(priv->ae_handle, indir, key, hfunc);
-
-       return 0;
+       return ops->get_rss(priv->ae_handle, indir, key, hfunc);
 }
 
 static int
@@ -1235,7 +1226,6 @@ hns_set_rss(struct net_device *netdev, const u32 *indir, const u8 *key,
 {
        struct hns_nic_priv *priv = netdev_priv(netdev);
        struct hnae_ae_ops *ops;
-       int ret;
 
        if (AE_IS_VER1(priv->enet_ver)) {
                netdev_err(netdev,
@@ -1252,7 +1242,22 @@ hns_set_rss(struct net_device *netdev, const u32 *indir, const u8 *key,
        if (!indir)
                return 0;
 
-       ret = ops->set_rss(priv->ae_handle, indir, key, hfunc);
+       return ops->set_rss(priv->ae_handle, indir, key, hfunc);
+}
+
+static int hns_get_rxnfc(struct net_device *netdev,
+                        struct ethtool_rxnfc *cmd,
+                        u32 *rule_locs)
+{
+       struct hns_nic_priv *priv = netdev_priv(netdev);
+
+       switch (cmd->cmd) {
+       case ETHTOOL_GRXRINGS:
+               cmd->data = priv->ae_handle->q_num;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
 
        return 0;
 }
@@ -1280,6 +1285,7 @@ static struct ethtool_ops hns_ethtool_ops = {
        .get_rxfh_indir_size = hns_get_rss_indir_size,
        .get_rxfh = hns_get_rss,
        .set_rxfh = hns_set_rss,
+       .get_rxnfc = hns_get_rxnfc,
 };
 
 void hns_ethtool_set_ops(struct net_device *ndev)
index 42d8de8..6aa7397 100644 (file)
@@ -39,8 +39,6 @@
 
 #include "mlx4.h"
 
-static const u8 zero_gid[16];  /* automatically initialized to 0 */
-
 int mlx4_get_mgm_entry_size(struct mlx4_dev *dev)
 {
        return 1 << dev->oper_log_mgm_entry_size;
index 3f57110..a733868 100644 (file)
@@ -1791,9 +1791,11 @@ static int smc911x_probe(struct net_device *dev)
        unsigned int val, chip_id, revision;
        const char *version_string;
        unsigned long irq_flags;
+#ifdef SMC_USE_DMA
        struct dma_slave_config config;
        dma_cap_mask_t mask;
        struct pxad_param param;
+#endif
 
        DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__);
 
index 192631a..bc16889 100644 (file)
@@ -843,8 +843,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
        if (info) {
                fl6->daddr = info->key.u.ipv6.dst;
                fl6->saddr = info->key.u.ipv6.src;
-               fl6->flowi6_tos = RT_TOS(info->key.tos);
-               fl6->flowlabel = info->key.label;
+               fl6->flowlabel = ip6_make_flowinfo(RT_TOS(info->key.tos),
+                                                  info->key.label);
                dst_cache = &info->dst_cache;
        } else {
                prio = geneve->tos;
@@ -855,8 +855,8 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
                        use_cache = false;
                }
 
-               fl6->flowi6_tos = RT_TOS(prio);
-               fl6->flowlabel = geneve->label;
+               fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
+                                                  geneve->label);
                fl6->daddr = geneve->remote.sin6.sin6_addr;
                dst_cache = &geneve->dst_cache;
        }
@@ -1049,7 +1049,8 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
+                                          iip, skb);
                ttl = geneve->ttl;
                if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
                        ttl = 1;
index f70522c..1352965 100644 (file)
@@ -122,6 +122,7 @@ static int sun4i_mdio_probe(struct platform_device *pdev)
                        return -EPROBE_DEFER;
 
                dev_info(&pdev->dev, "no regulator found\n");
+               data->regulator = NULL;
        } else {
                ret = regulator_enable(data->regulator);
                if (ret)
@@ -137,7 +138,8 @@ static int sun4i_mdio_probe(struct platform_device *pdev)
        return 0;
 
 err_out_disable_regulator:
-       regulator_disable(data->regulator);
+       if (data->regulator)
+               regulator_disable(data->regulator);
 err_out_free_mdiobus:
        mdiobus_free(bus);
        return ret;
index d36d5eb..f20890e 100644 (file)
@@ -3261,54 +3261,6 @@ void lan78xx_tx_timeout(struct net_device *net)
        tasklet_schedule(&dev->bh);
 }
 
-struct rtnl_link_stats64 *lan78xx_get_stats64(struct net_device *netdev,
-                                             struct rtnl_link_stats64 *storage)
-{
-       struct lan78xx_net *dev = netdev_priv(netdev);
-       struct lan78xx_statstage64 stats;
-
-       /* curr_stat is updated by timer.
-        * periodic reading from HW will prevent from entering USB auto suspend.
-        * if autosuspend is disabled, read from HW.
-        */
-       if (!dev->udev->dev.power.runtime_auto)
-               lan78xx_update_stats(dev);
-
-       mutex_lock(&dev->stats.access_lock);
-       memcpy(&stats, &dev->stats.curr_stat, sizeof(stats));
-       mutex_unlock(&dev->stats.access_lock);
-
-       /* calc by driver */
-       storage->rx_packets = (__u64)netdev->stats.rx_packets;
-       storage->tx_packets = (__u64)netdev->stats.tx_packets;
-       storage->rx_bytes = (__u64)netdev->stats.rx_bytes;
-       storage->tx_bytes = (__u64)netdev->stats.tx_bytes;
-
-       /* use counter */
-       storage->rx_length_errors = stats.rx_undersize_frame_errors +
-                                   stats.rx_oversize_frame_errors;
-       storage->rx_crc_errors = stats.rx_fcs_errors;
-       storage->rx_frame_errors = stats.rx_alignment_errors;
-       storage->rx_fifo_errors = stats.rx_dropped_frames;
-       storage->rx_over_errors = stats.rx_oversize_frame_errors;
-       storage->rx_errors = stats.rx_fcs_errors +
-                            stats.rx_alignment_errors +
-                            stats.rx_fragment_errors +
-                            stats.rx_jabber_errors +
-                            stats.rx_undersize_frame_errors +
-                            stats.rx_oversize_frame_errors +
-                            stats.rx_dropped_frames;
-
-       storage->tx_carrier_errors = stats.tx_carrier_errors;
-       storage->tx_errors = stats.tx_fcs_errors +
-                            stats.tx_excess_deferral_errors +
-                            stats.tx_carrier_errors;
-
-       storage->multicast = stats.rx_multicast_frames;
-
-       return storage;
-}
-
 static const struct net_device_ops lan78xx_netdev_ops = {
        .ndo_open               = lan78xx_open,
        .ndo_stop               = lan78xx_stop,
@@ -3322,7 +3274,6 @@ static const struct net_device_ops lan78xx_netdev_ops = {
        .ndo_set_features       = lan78xx_set_features,
        .ndo_vlan_rx_add_vid    = lan78xx_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = lan78xx_vlan_rx_kill_vid,
-       .ndo_get_stats64        = lan78xx_get_stats64,
 };
 
 static void lan78xx_stat_monitor(unsigned long param)
index 800106a..1c0fa36 100644 (file)
@@ -1143,7 +1143,7 @@ static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
 static bool vxlan_remcsum(struct vxlanhdr *unparsed,
                          struct sk_buff *skb, u32 vxflags)
 {
-       size_t start, offset, plen;
+       size_t start, offset;
 
        if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
                goto out;
@@ -1151,9 +1151,7 @@ static bool vxlan_remcsum(struct vxlanhdr *unparsed,
        start = vxlan_rco_start(unparsed->vx_vni);
        offset = start + vxlan_rco_offset(unparsed->vx_vni);
 
-       plen = sizeof(struct vxlanhdr) + offset + sizeof(u16);
-
-       if (!pskb_may_pull(skb, plen))
+       if (!pskb_may_pull(skb, offset + sizeof(u16)))
                return false;
 
        skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset,
@@ -1810,10 +1808,9 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = oif;
-       fl6.flowi6_tos = RT_TOS(tos);
        fl6.daddr = *daddr;
        fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
-       fl6.flowlabel = label;
+       fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
        fl6.flowi6_mark = skb->mark;
        fl6.flowi6_proto = IPPROTO_UDP;
 
index 8f87930..1b271b9 100644 (file)
@@ -274,6 +274,9 @@ void ar5008_hw_cmn_spur_mitigate(struct ath_hw *ah,
        };
        static const int inc[4] = { 0, 100, 0, 0 };
 
+       memset(&mask_m, 0, sizeof(int8_t) * 123);
+       memset(&mask_p, 0, sizeof(int8_t) * 123);
+
        cur_bin = -6000;
        upper = bin + 100;
        lower = bin - 100;
@@ -424,14 +427,9 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
        int tmp, new;
        int i;
 
-       int8_t mask_m[123];
-       int8_t mask_p[123];
        int cur_bb_spur;
        bool is2GHz = IS_CHAN_2GHZ(chan);
 
-       memset(&mask_m, 0, sizeof(int8_t) * 123);
-       memset(&mask_p, 0, sizeof(int8_t) * 123);
-
        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
                cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
                if (AR_NO_SPUR == cur_bb_spur)
index db66245..53d7445 100644 (file)
@@ -178,14 +178,9 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
        int i;
        struct chan_centers centers;
 
-       int8_t mask_m[123];
-       int8_t mask_p[123];
        int cur_bb_spur;
        bool is2GHz = IS_CHAN_2GHZ(chan);
 
-       memset(&mask_m, 0, sizeof(int8_t) * 123);
-       memset(&mask_p, 0, sizeof(int8_t) * 123);
-
        ath9k_hw_get_channel_centers(ah, chan, &centers);
        freq = centers.synth_center;
 
index 72380af..b0603e7 100644 (file)
@@ -5680,11 +5680,12 @@ static int b43_bcma_probe(struct bcma_device *core)
        INIT_WORK(&wl->firmware_load, b43_request_firmware);
        schedule_work(&wl->firmware_load);
 
-bcma_out:
        return err;
 
 bcma_err_wireless_exit:
        ieee80211_free_hw(wl->hw);
+bcma_out:
+       kfree(dev);
        return err;
 }
 
@@ -5712,8 +5713,8 @@ static void b43_bcma_remove(struct bcma_device *core)
        b43_rng_exit(wl);
 
        b43_leds_unregister(wl);
-
        ieee80211_free_hw(wl->hw);
+       kfree(wldev->dev);
 }
 
 static struct bcma_driver b43_bcma_driver = {
@@ -5796,6 +5797,7 @@ static void b43_ssb_remove(struct ssb_device *sdev)
 
        b43_leds_unregister(wl);
        b43_wireless_exit(dev, wl);
+       kfree(dev);
 }
 
 static struct ssb_driver b43_ssb_driver = {
index 95dcbff..6a8245c 100644 (file)
@@ -2488,9 +2488,9 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
                for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
                        rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
 
-                       RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-                                "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
-                                rtldm->thermalvalue, thermal_value);
+               RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+                        "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
+                        rtldm->thermalvalue, thermal_value);
                /*Record last Power Tracking Thermal Value*/
                rtldm->thermalvalue = thermal_value;
        }
index 3355748..fc82743 100644 (file)
@@ -62,7 +62,7 @@ static int nvdimm_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct nd_device_driver *nd_drv = to_nd_device_driver(drv);
 
-       return test_bit(to_nd_device_type(dev), &nd_drv->type);
+       return !!test_bit(to_nd_device_type(dev), &nd_drv->type);
 }
 
 static struct module *to_bus_provider(struct device *dev)
index 017dd94..b299de2 100644 (file)
@@ -1341,10 +1341,10 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_array);
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-int of_property_read_string(struct device_node *np, const char *propname,
+int of_property_read_string(const struct device_node *np, const char *propname,
                                const char **out_string)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        if (!prop)
                return -EINVAL;
        if (!prop->value)
@@ -1365,10 +1365,10 @@ EXPORT_SYMBOL_GPL(of_property_read_string);
  * This function searches a string list property and returns the index
  * of a specific string value.
  */
-int of_property_match_string(struct device_node *np, const char *propname,
+int of_property_match_string(const struct device_node *np, const char *propname,
                             const char *string)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        size_t l;
        int i;
        const char *p, *end;
@@ -1404,10 +1404,11 @@ EXPORT_SYMBOL_GPL(of_property_match_string);
  * Don't call this function directly. It is a utility helper for the
  * of_property_read_string*() family of functions.
  */
-int of_property_read_string_helper(struct device_node *np, const char *propname,
-                                  const char **out_strs, size_t sz, int skip)
+int of_property_read_string_helper(const struct device_node *np,
+                                  const char *propname, const char **out_strs,
+                                  size_t sz, int skip)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const struct property *prop = of_find_property(np, propname, NULL);
        int l = 0, i = 0;
        const char *p, *end;
 
index 1a3556a..ed01c01 100644 (file)
@@ -32,11 +32,13 @@ int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
        phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
        phys_addr_t *res_base)
 {
+       phys_addr_t base;
        /*
         * We use __memblock_alloc_base() because memblock_alloc_base()
         * panic()s on allocation failure.
         */
-       phys_addr_t base = __memblock_alloc_base(size, align, end);
+       end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
+       base = __memblock_alloc_base(size, align, end);
        if (!base)
                return -ENOMEM;
 
index 640eb4c..d313d49 100644 (file)
@@ -36,12 +36,14 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node,
 
        /* check */
        if (of_node_cmp(node->full_name, full_name) == 0)
-               return node;
+               return of_node_get(node);
 
        for_each_child_of_node(node, child) {
                found = __of_find_node_by_full_name(child, full_name);
-               if (found != NULL)
+               if (found != NULL) {
+                       of_node_put(child);
                        return found;
+               }
        }
 
        return NULL;
@@ -174,6 +176,7 @@ static int __of_adjust_phandle_ref(struct device_node *node,
                        if (of_prop_cmp(sprop->name, propstr) == 0)
                                break;
                }
+               of_node_put(refnode);
 
                if (!sprop) {
                        pr_err("%s: Could not find property '%s'\n",
index 979b6e4..e986e6e 100644 (file)
@@ -1165,6 +1165,11 @@ static void of_unittest_destroy_tracked_overlays(void)
                                continue;
 
                        ret = of_overlay_destroy(id + overlay_first_id);
+                       if (ret == -ENODEV) {
+                               pr_warn("%s: no overlay to destroy for #%d\n",
+                                       __func__, id + overlay_first_id);
+                               continue;
+                       }
                        if (ret != 0) {
                                defers++;
                                pr_warn("%s: overlay destroy failed for #%d\n",
index f2187d4..6c9f546 100644 (file)
@@ -271,6 +271,8 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
 
 void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
 
+void __weak pcibios_bus_add_device(struct pci_dev *pdev) { }
+
 /**
  * pci_bus_add_device - start driver for a single device
  * @dev: device to add
@@ -285,6 +287,7 @@ void pci_bus_add_device(struct pci_dev *dev)
         * Can not put in pci_device_add yet because resources
         * are not assigned yet for some devices.
         */
+       pcibios_bus_add_device(dev);
        pci_fixup_device(pci_fixup_final, dev);
        pci_create_sysfs_dev_files(dev);
        pci_proc_attach_device(dev);
index fe4bd0a..2194b44 100644 (file)
@@ -113,7 +113,7 @@ resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
        return dev->sriov->barsz[resno - PCI_IOV_RESOURCES];
 }
 
-static int virtfn_add(struct pci_dev *dev, int id, int reset)
+int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
 {
        int i;
        int rc = -ENOMEM;
@@ -188,7 +188,7 @@ failed:
        return rc;
 }
 
-static void virtfn_remove(struct pci_dev *dev, int id, int reset)
+void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset)
 {
        char buf[VIRTFN_ID_LEN];
        struct pci_dev *virtfn;
@@ -321,7 +321,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
        }
 
        for (i = 0; i < initial; i++) {
-               rc = virtfn_add(dev, i, 0);
+               rc = pci_iov_add_virtfn(dev, i, 0);
                if (rc)
                        goto failed;
        }
@@ -333,7 +333,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
 
 failed:
        while (i--)
-               virtfn_remove(dev, i, 0);
+               pci_iov_remove_virtfn(dev, i, 0);
 
        pcibios_sriov_disable(dev);
 err_pcibios:
@@ -359,7 +359,7 @@ static void sriov_disable(struct pci_dev *dev)
                return;
 
        for (i = 0; i < iov->num_VFs; i++)
-               virtfn_remove(dev, i, 0);
+               pci_iov_remove_virtfn(dev, i, 0);
 
        pcibios_sriov_disable(dev);
 
index a8ac4c0..6e68155 100644 (file)
@@ -108,7 +108,6 @@ struct cxlflash_cfg {
        atomic_t scan_host_needed;
 
        struct cxl_afu *cxl_afu;
-       struct pci_dev *parent_dev;
 
        atomic_t recovery_threads;
        struct mutex ctx_recovery_mutex;
index 3879b46..35968bd 100644 (file)
@@ -1355,7 +1355,7 @@ static int start_context(struct cxlflash_cfg *cfg)
  */
 static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
 {
-       struct pci_dev *dev = cfg->parent_dev;
+       struct pci_dev *dev = cfg->dev;
        int rc = 0;
        int ro_start, ro_size, i, j, k;
        ssize_t vpd_size;
@@ -1364,7 +1364,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
        char *wwpn_vpd_tags[NUM_FC_PORTS] = { "V5", "V6" };
 
        /* Get the VPD data from the device */
-       vpd_size = pci_read_vpd(dev, 0, sizeof(vpd_data), vpd_data);
+       vpd_size = cxl_read_adapter_vpd(dev, vpd_data, sizeof(vpd_data));
        if (unlikely(vpd_size <= 0)) {
                dev_err(&dev->dev, "%s: Unable to read VPD (size = %ld)\n",
                       __func__, vpd_size);
@@ -2350,7 +2350,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
 {
        struct Scsi_Host *host;
        struct cxlflash_cfg *cfg = NULL;
-       struct device *phys_dev;
        struct dev_dependent_vals *ddv;
        int rc = 0;
 
@@ -2416,19 +2415,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, cfg);
 
-       /*
-        * Use the special service provided to look up the physical
-        * PCI device, since we are called on the probe of the virtual
-        * PCI host bus (vphb)
-        */
-       phys_dev = cxl_get_phys_dev(pdev);
-       if (!dev_is_pci(phys_dev)) {
-               dev_err(&pdev->dev, "%s: not a pci dev\n", __func__);
-               rc = -ENODEV;
-               goto out_remove;
-       }
-       cfg->parent_dev = to_pci_dev(phys_dev);
-
        cfg->cxl_afu = cxl_pci_to_afu(pdev);
 
        rc = init_pci(cfg);
index 419fa5b..41eff80 100644 (file)
@@ -102,6 +102,39 @@ out_muram:
        return ret;
 }
 
+/*
+ * cpm_muram_alloc_common - cpm_muram_alloc common code
+ * @size: number of bytes to allocate
+ * @algo: algorithm for alloc.
+ * @data: data for genalloc's algorithm.
+ *
+ * This function returns an offset into the muram area.
+ */
+static unsigned long cpm_muram_alloc_common(unsigned long size,
+               genpool_algo_t algo, void *data)
+{
+       struct muram_block *entry;
+       unsigned long start;
+
+       start = gen_pool_alloc_algo(muram_pool, size, algo, data);
+       if (!start)
+               goto out2;
+       start = start - GENPOOL_OFFSET;
+       memset_io(cpm_muram_addr(start), 0, size);
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry)
+               goto out1;
+       entry->start = start;
+       entry->size = size;
+       list_add(&entry->head, &muram_block_list);
+
+       return start;
+out1:
+       gen_pool_free(muram_pool, start, size);
+out2:
+       return (unsigned long)-ENOMEM;
+}
+
 /*
  * cpm_muram_alloc - allocate the requested size worth of multi-user ram
  * @size: number of bytes to allocate
@@ -175,39 +208,6 @@ unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
 }
 EXPORT_SYMBOL(cpm_muram_alloc_fixed);
 
-/*
- * cpm_muram_alloc_common - cpm_muram_alloc common code
- * @size: number of bytes to allocate
- * @algo: algorithm for alloc.
- * @data: data for genalloc's algorithm.
- *
- * This function returns an offset into the muram area.
- */
-unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
-                                    void *data)
-{
-       struct muram_block *entry;
-       unsigned long start;
-
-       start = gen_pool_alloc_algo(muram_pool, size, algo, data);
-       if (!start)
-               goto out2;
-       start = start - GENPOOL_OFFSET;
-       memset_io(cpm_muram_addr(start), 0, size);
-       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-       if (!entry)
-               goto out1;
-       entry->start = start;
-       entry->size = size;
-       list_add(&entry->head, &muram_block_list);
-
-       return start;
-out1:
-       gen_pool_free(muram_pool, start, size);
-out2:
-       return (unsigned long)-ENOMEM;
-}
-
 /**
  * cpm_muram_addr - turn a muram offset into a virtual address
  * @offset: muram offset to convert
index b77d01f..ec2ca86 100644 (file)
@@ -259,6 +259,11 @@ static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,
        struct qe_ic *qe_ic = h->host_data;
        struct irq_chip *chip;
 
+       if (hw >= ARRAY_SIZE(qe_ic_info)) {
+               pr_err("%s: Invalid hw irq number for QEIC\n", __func__);
+               return -EINVAL;
+       }
+
        if (qe_ic_info[hw].mask == 0) {
                printk(KERN_ERR "Can't map reserved IRQ\n");
                return -EINVAL;
@@ -407,7 +412,8 @@ int qe_ic_set_priority(unsigned int virq, unsigned int priority)
 
        if (priority > 8 || priority == 0)
                return -EINVAL;
-       if (src > 127)
+       if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info),
+                     "%s: Invalid hw irq number for QEIC\n", __func__))
                return -EINVAL;
        if (qe_ic_info[src].pri_reg == 0)
                return -EINVAL;
@@ -436,6 +442,9 @@ int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
 
        if (priority > 2 || priority == 0)
                return -EINVAL;
+       if (WARN_ONCE(src >= ARRAY_SIZE(qe_ic_info),
+                     "%s: Invalid hw irq number for QEIC\n", __func__))
+               return -EINVAL;
 
        switch (qe_ic_info[src].pri_reg) {
        case QEIC_CIPZCC:
index 6c502cb..df4f369 100644 (file)
  * The idea here is to build acquire/release variants by adding explicit
  * barriers on top of the relaxed variant. In the case where the relaxed
  * variant is already fully ordered, no additional barriers are needed.
+ *
+ * Besides, if an arch has a special barrier for acquire/release, it could
+ * implement its own __atomic_op_* and use the same framework for building
+ * variants
  */
+#ifndef __atomic_op_acquire
 #define __atomic_op_acquire(op, args...)                               \
 ({                                                                     \
        typeof(op##_relaxed(args)) __ret  = op##_relaxed(args);         \
        smp_mb__after_atomic();                                         \
        __ret;                                                          \
 })
+#endif
 
+#ifndef __atomic_op_release
 #define __atomic_op_release(op, args...)                               \
 ({                                                                     \
        smp_mb__before_atomic();                                        \
        op##_relaxed(args);                                             \
 })
+#endif
 
+#ifndef __atomic_op_fence
 #define __atomic_op_fence(op, args...)                                 \
 ({                                                                     \
        typeof(op##_relaxed(args)) __ret;                               \
@@ -56,6 +65,7 @@
        smp_mb__after_atomic();                                         \
        __ret;                                                          \
 })
+#endif
 
 /* atomic_add_return_relaxed */
 #ifndef atomic_add_return_relaxed
index 7f48186..e51b070 100644 (file)
@@ -20,6 +20,7 @@ struct pt_regs;
 #define BUILD_BUG_ON_MSG(cond, msg) (0)
 #define BUILD_BUG_ON(condition) (0)
 #define BUILD_BUG() (0)
+#define MAYBE_BUILD_BUG_ON(cond) (0)
 #else /* __CHECKER__ */
 
 /* Force a compilation error if a constant expression is not a power of 2 */
@@ -83,6 +84,14 @@ struct pt_regs;
  */
 #define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
 
+#define MAYBE_BUILD_BUG_ON(cond)                       \
+       do {                                            \
+               if (__builtin_constant_p((cond)))       \
+                       BUILD_BUG_ON(cond);             \
+               else                                    \
+                       BUG_ON(cond);                   \
+       } while (0)
+
 #endif /* __CHECKER__ */
 
 #ifdef CONFIG_GENERIC_BUG
index 08bffcc..c2c04f7 100644 (file)
@@ -44,8 +44,7 @@ struct clk_lookup *clkdev_create(struct clk *clk, const char *con_id,
 void clkdev_add_table(struct clk_lookup *, size_t);
 int clk_add_alias(const char *, const char *, const char *, struct device *);
 
-int clk_register_clkdev(struct clk *, const char *, const char *, ...)
-       __printf(3, 4);
+int clk_register_clkdev(struct clk *, const char *, const char *);
 int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
 
 #ifdef CONFIG_COMMON_CLK
index 2d0e6e5..88192d0 100644 (file)
@@ -70,8 +70,11 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
  * @dev_groups:        Default attributes of the devices on the bus.
  * @drv_groups: Default attributes of the device drivers on the bus.
  * @match:     Called, perhaps multiple times, whenever a new device or driver
- *             is added for this bus. It should return a nonzero value if the
- *             given device can be handled by the given driver.
+ *             is added for this bus. It should return a positive value if the
+ *             given device can be handled by the given driver and zero
+ *             otherwise. It may also return error code if determining that
+ *             the driver supports the device is not possible. In case of
+ *             -EPROBE_DEFER it will queue the device for deferred probing.
  * @uevent:    Called when a device is added, removed, or a few other things
  *             that generate uevents to add the environment variables.
  * @probe:     Called when a new device or driver add to this bus, and callback
index 99c0be0..5246239 100644 (file)
@@ -18,6 +18,7 @@ enum dma_attr {
        DMA_ATTR_NO_KERNEL_MAPPING,
        DMA_ATTR_SKIP_CPU_SYNC,
        DMA_ATTR_FORCE_CONTIGUOUS,
+       DMA_ATTR_ALLOC_SINGLE_PAGES,
        DMA_ATTR_MAX,
 };
 
index 84d971f..649e917 100644 (file)
@@ -189,4 +189,109 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
 
 #endif
 
+struct ccsr_rcpm_v1 {
+       u8      res0000[4];
+       __be32  cdozsr;     /* 0x0004 Core Doze Status Register */
+       u8      res0008[4];
+       __be32  cdozcr;     /* 0x000c Core Doze Control Register */
+       u8      res0010[4];
+       __be32  cnapsr;     /* 0x0014 Core Nap Status Register */
+       u8      res0018[4];
+       __be32  cnapcr;     /* 0x001c Core Nap Control Register */
+       u8      res0020[4];
+       __be32  cdozpsr;    /* 0x0024 Core Doze Previous Status Register */
+       u8      res0028[4];
+       __be32  cnappsr;    /* 0x002c Core Nap Previous Status Register */
+       u8      res0030[4];
+       __be32  cwaitsr;    /* 0x0034 Core Wait Status Register */
+       u8      res0038[4];
+       __be32  cwdtdsr;    /* 0x003c Core Watchdog Detect Status Register */
+       __be32  powmgtcsr;  /* 0x0040 PM Control&Status Register */
+#define RCPM_POWMGTCSR_SLP     0x00020000
+       u8      res0044[12];
+       __be32  ippdexpcr;  /* 0x0050 IP Powerdown Exception Control Register */
+       u8      res0054[16];
+       __be32  cpmimr;     /* 0x0064 Core PM IRQ Mask Register */
+       u8      res0068[4];
+       __be32  cpmcimr;    /* 0x006c Core PM Critical IRQ Mask Register */
+       u8      res0070[4];
+       __be32  cpmmcmr;    /* 0x0074 Core PM Machine Check Mask Register */
+       u8      res0078[4];
+       __be32  cpmnmimr;   /* 0x007c Core PM NMI Mask Register */
+       u8      res0080[4];
+       __be32  ctbenr;     /* 0x0084 Core Time Base Enable Register */
+       u8      res0088[4];
+       __be32  ctbckselr;  /* 0x008c Core Time Base Clock Select Register */
+       u8      res0090[4];
+       __be32  ctbhltcr;   /* 0x0094 Core Time Base Halt Control Register */
+       u8      res0098[4];
+       __be32  cmcpmaskcr; /* 0x00a4 Core Machine Check Mask Register */
+};
+
+struct ccsr_rcpm_v2 {
+       u8      res_00[12];
+       __be32  tph10sr0;       /* Thread PH10 Status Register */
+       u8      res_10[12];
+       __be32  tph10setr0;     /* Thread PH10 Set Control Register */
+       u8      res_20[12];
+       __be32  tph10clrr0;     /* Thread PH10 Clear Control Register */
+       u8      res_30[12];
+       __be32  tph10psr0;      /* Thread PH10 Previous Status Register */
+       u8      res_40[12];
+       __be32  twaitsr0;       /* Thread Wait Status Register */
+       u8      res_50[96];
+       __be32  pcph15sr;       /* Physical Core PH15 Status Register */
+       __be32  pcph15setr;     /* Physical Core PH15 Set Control Register */
+       __be32  pcph15clrr;     /* Physical Core PH15 Clear Control Register */
+       __be32  pcph15psr;      /* Physical Core PH15 Prev Status Register */
+       u8      res_c0[16];
+       __be32  pcph20sr;       /* Physical Core PH20 Status Register */
+       __be32  pcph20setr;     /* Physical Core PH20 Set Control Register */
+       __be32  pcph20clrr;     /* Physical Core PH20 Clear Control Register */
+       __be32  pcph20psr;      /* Physical Core PH20 Prev Status Register */
+       __be32  pcpw20sr;       /* Physical Core PW20 Status Register */
+       u8      res_e0[12];
+       __be32  pcph30sr;       /* Physical Core PH30 Status Register */
+       __be32  pcph30setr;     /* Physical Core PH30 Set Control Register */
+       __be32  pcph30clrr;     /* Physical Core PH30 Clear Control Register */
+       __be32  pcph30psr;      /* Physical Core PH30 Prev Status Register */
+       u8      res_100[32];
+       __be32  ippwrgatecr;    /* IP Power Gating Control Register */
+       u8      res_124[12];
+       __be32  powmgtcsr;      /* Power Management Control & Status Reg */
+#define RCPM_POWMGTCSR_LPM20_RQ                0x00100000
+#define RCPM_POWMGTCSR_LPM20_ST                0x00000200
+#define RCPM_POWMGTCSR_P_LPM20_ST      0x00000100
+       u8      res_134[12];
+       __be32  ippdexpcr[4];   /* IP Powerdown Exception Control Reg */
+       u8      res_150[12];
+       __be32  tpmimr0;        /* Thread PM Interrupt Mask Reg */
+       u8      res_160[12];
+       __be32  tpmcimr0;       /* Thread PM Crit Interrupt Mask Reg */
+       u8      res_170[12];
+       __be32  tpmmcmr0;       /* Thread PM Machine Check Interrupt Mask Reg */
+       u8      res_180[12];
+       __be32  tpmnmimr0;      /* Thread PM NMI Mask Reg */
+       u8      res_190[12];
+       __be32  tmcpmaskcr0;    /* Thread Machine Check Mask Control Reg */
+       __be32  pctbenr;        /* Physical Core Time Base Enable Reg */
+       __be32  pctbclkselr;    /* Physical Core Time Base Clock Select */
+       __be32  tbclkdivr;      /* Time Base Clock Divider Register */
+       u8      res_1ac[4];
+       __be32  ttbhltcr[4];    /* Thread Time Base Halt Control Register */
+       __be32  clpcl10sr;      /* Cluster PCL10 Status Register */
+       __be32  clpcl10setr;    /* Cluster PCL30 Set Control Register */
+       __be32  clpcl10clrr;    /* Cluster PCL30 Clear Control Register */
+       __be32  clpcl10psr;     /* Cluster PCL30 Prev Status Register */
+       __be32  cddslpsetr;     /* Core Domain Deep Sleep Set Register */
+       __be32  cddslpclrr;     /* Core Domain Deep Sleep Clear Register */
+       __be32  cdpwroksetr;    /* Core Domain Power OK Set Register */
+       __be32  cdpwrokclrr;    /* Core Domain Power OK Clear Register */
+       __be32  cdpwrensr;      /* Core Domain Power Enable Status Register */
+       __be32  cddslsr;        /* Core Domain Deep Sleep Status Register */
+       u8      res_1e8[8];
+       __be32  dslpcntcr[8];   /* Deep Sleep Counter Cfg Register */
+       u8      res_300[3568];
+};
+
 #endif
index 5307dfb..79b0ef6 100644 (file)
@@ -111,9 +111,6 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
 void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address,
                bool freeze, struct page *page);
 
-#if HPAGE_PMD_ORDER >= MAX_ORDER
-#error "hugepages can't be allocated by the buddy allocator"
-#endif
 extern int hugepage_madvise(struct vm_area_struct *vma,
                            unsigned long *vm_flags, int advice);
 extern void vma_adjust_trans_huge(struct vm_area_struct *vma,
index 246a352..ac02c54 100644 (file)
@@ -596,7 +596,7 @@ static inline struct mISDNdevice *dev_to_mISDN(struct device *dev)
 }
 
 extern void    set_channel_address(struct mISDNchannel *, u_int, u_int);
-extern void    mISDN_clock_update(struct mISDNclock *, int, struct timeval *);
+extern void    mISDN_clock_update(struct mISDNclock *, int, ktime_t *);
 extern unsigned short mISDN_clock_get(void);
 extern const char *mISDNDevName4ch(struct mISDNchannel *);
 
index be693b3..3f6385d 100644 (file)
@@ -1320,6 +1320,10 @@ struct net_device_ops {
  * @IFF_LIVE_ADDR_CHANGE: device supports hardware address
  *     change when it's running
  * @IFF_MACVLAN: Macvlan device
+ * @IFF_XMIT_DST_RELEASE_PERM: IFF_XMIT_DST_RELEASE not taking into account
+ *     underlying stacked devices
+ * @IFF_IPVLAN_MASTER: IPvlan master device
+ * @IFF_IPVLAN_SLAVE: IPvlan slave device
  * @IFF_L3MDEV_MASTER: device is an L3 master device
  * @IFF_NO_QUEUE: device can run without qdisc attached
  * @IFF_OPENVSWITCH: device is a Open vSwitch master
@@ -1414,6 +1418,8 @@ enum netdev_priv_flags {
  *     @unreg_list:    List entry, that is used, when we are unregistering the
  *                     device, see the function unregister_netdev
  *     @close_list:    List entry, that is used, when we are closing the device
+ *     @ptype_all:     Device-specific packet handlers for all protocols
+ *     @ptype_specific: Device-specific, protocol-specific packet handlers
  *
  *     @adj_list:      Directly linked devices, like slaves for bonding
  *     @all_adj_list:  All linked devices, *including* neighbours
@@ -2096,8 +2102,8 @@ struct napi_gro_cb {
        /* This is non-zero if the packet may be of the same flow. */
        u8      same_flow:1;
 
-       /* Used in udp_gro_receive */
-       u8      udp_mark:1;
+       /* Used in tunnel GRO receive */
+       u8      encap_mark:1;
 
        /* GRO checksum is valid */
        u8      csum_valid:1;
index dc6e396..7fcb681 100644 (file)
@@ -296,13 +296,13 @@ extern int of_property_read_u64_array(const struct device_node *np,
                                      u64 *out_values,
                                      size_t sz);
 
-extern int of_property_read_string(struct device_node *np,
+extern int of_property_read_string(const struct device_node *np,
                                   const char *propname,
                                   const char **out_string);
-extern int of_property_match_string(struct device_node *np,
+extern int of_property_match_string(const struct device_node *np,
                                    const char *propname,
                                    const char *string);
-extern int of_property_read_string_helper(struct device_node *np,
+extern int of_property_read_string_helper(const struct device_node *np,
                                              const char *propname,
                                              const char **out_strs, size_t sz, int index);
 extern int of_device_is_compatible(const struct device_node *device,
@@ -538,14 +538,14 @@ static inline int of_property_read_u64_array(const struct device_node *np,
        return -ENOSYS;
 }
 
-static inline int of_property_read_string(struct device_node *np,
+static inline int of_property_read_string(const struct device_node *np,
                                          const char *propname,
                                          const char **out_string)
 {
        return -ENOSYS;
 }
 
-static inline int of_property_read_string_helper(struct device_node *np,
+static inline int of_property_read_string_helper(const struct device_node *np,
                                                 const char *propname,
                                                 const char **out_strs, size_t sz, int index)
 {
@@ -571,7 +571,7 @@ static inline int of_property_read_u64(const struct device_node *np,
        return -ENOSYS;
 }
 
-static inline int of_property_match_string(struct device_node *np,
+static inline int of_property_match_string(const struct device_node *np,
                                           const char *propname,
                                           const char *string)
 {
@@ -773,7 +773,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np,
  *
  * If @out_strs is NULL, the number of strings in the property is returned.
  */
-static inline int of_property_read_string_array(struct device_node *np,
+static inline int of_property_read_string_array(const struct device_node *np,
                                                const char *propname, const char **out_strs,
                                                size_t sz)
 {
@@ -792,7 +792,7 @@ static inline int of_property_read_string_array(struct device_node *np,
  * does not have a value, and -EILSEQ if the string is not null-terminated
  * within the length of the property data.
  */
-static inline int of_property_count_strings(struct device_node *np,
+static inline int of_property_count_strings(const struct device_node *np,
                                            const char *propname)
 {
        return of_property_read_string_helper(np, propname, NULL, 0, 0);
@@ -816,7 +816,7 @@ static inline int of_property_count_strings(struct device_node *np,
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
-static inline int of_property_read_string_index(struct device_node *np,
+static inline int of_property_read_string_index(const struct device_node *np,
                                                const char *propname,
                                                int index, const char **output)
 {
index 17e17c2..004b813 100644 (file)
@@ -784,6 +784,7 @@ extern struct list_head pci_root_buses;     /* list of all known PCI buses */
 int no_pci_devices(void);
 
 void pcibios_resource_survey_bus(struct pci_bus *bus);
+void pcibios_bus_add_device(struct pci_dev *pdev);
 void pcibios_add_bus(struct pci_bus *bus);
 void pcibios_remove_bus(struct pci_bus *bus);
 void pcibios_fixup_bus(struct pci_bus *);
@@ -1733,6 +1734,8 @@ int pci_iov_virtfn_devfn(struct pci_dev *dev, int id);
 
 int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
 void pci_disable_sriov(struct pci_dev *dev);
+int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset);
+void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset);
 int pci_num_vf(struct pci_dev *dev);
 int pci_vfs_assigned(struct pci_dev *dev);
 int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
@@ -1749,6 +1752,12 @@ static inline int pci_iov_virtfn_devfn(struct pci_dev *dev, int id)
 }
 static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
 { return -ENODEV; }
+static inline int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
+{
+       return -ENOSYS;
+}
+static inline void pci_iov_remove_virtfn(struct pci_dev *dev,
+                                        int id, int reset) { }
 static inline void pci_disable_sriov(struct pci_dev *dev) { }
 static inline int pci_num_vf(struct pci_dev *dev) { return 0; }
 static inline int pci_vfs_assigned(struct pci_dev *dev)
index 12c4865..393efe2 100644 (file)
@@ -24,6 +24,9 @@ bool psci_tos_resident_on(int cpu);
 bool psci_power_state_loses_context(u32 state);
 bool psci_power_state_is_valid(u32 state);
 
+int psci_cpu_init_idle(unsigned int cpu);
+int psci_cpu_suspend_enter(unsigned long index);
+
 struct psci_operations {
        int (*cpu_suspend)(u32 state, unsigned long entry_point);
        int (*cpu_off)(u32 state);
index c33dfa6..2087c9a 100644 (file)
@@ -16,6 +16,8 @@
 #include <media/videobuf2-v4l2.h>
 #include <linux/dma-mapping.h>
 
+struct dma_attrs;
+
 static inline dma_addr_t
 vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
 {
@@ -24,7 +26,14 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
        return *addr;
 }
 
-void *vb2_dma_contig_init_ctx(struct device *dev);
+void *vb2_dma_contig_init_ctx_attrs(struct device *dev,
+                                   struct dma_attrs *attrs);
+
+static inline void *vb2_dma_contig_init_ctx(struct device *dev)
+{
+       return vb2_dma_contig_init_ctx_attrs(dev, NULL);
+}
+
 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
 
 extern const struct vb2_mem_ops vb2_dma_contig_memops;
index f2ffe5b..7d5e261 100644 (file)
@@ -30,9 +30,6 @@ struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev);
 /* Get the AFU conf record number associated with a pci_dev */
 unsigned int cxl_pci_to_cfg_record(struct pci_dev *dev);
 
-/* Get the physical device (ie. the PCIe card) which the AFU is attached */
-struct device *cxl_get_phys_dev(struct pci_dev *dev);
-
 
 /*
  * Context lifetime overview:
@@ -210,4 +207,9 @@ ssize_t cxl_fd_read(struct file *file, char __user *buf, size_t count,
 void cxl_perst_reloads_same_image(struct cxl_afu *afu,
                                  bool perst_reloads_same_image);
 
+/*
+ * Read the VPD for the card where the AFU resides
+ */
+ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count);
+
 #endif /* _MISC_CXL_H */
index 83969ee..d47ef4b 100644 (file)
@@ -127,7 +127,6 @@ struct flowi6 {
 #define flowi6_oif             __fl_common.flowic_oif
 #define flowi6_iif             __fl_common.flowic_iif
 #define flowi6_mark            __fl_common.flowic_mark
-#define flowi6_tos             __fl_common.flowic_tos
 #define flowi6_scope           __fl_common.flowic_scope
 #define flowi6_proto           __fl_common.flowic_proto
 #define flowi6_flags           __fl_common.flowic_flags
@@ -135,6 +134,7 @@ struct flowi6 {
 #define flowi6_tun_key         __fl_common.flowic_tun_key
        struct in6_addr         daddr;
        struct in6_addr         saddr;
+       /* Note: flowi6_tos is encoded in flowlabel, too. */
        __be32                  flowlabel;
        union flowi_uli         uli;
 #define fl6_sport              uli.ports.sport
index 064cfbe..954ad6b 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/types.h>
 
-struct in6_addr;
 struct inet_bind_bucket;
 struct request_sock;
 struct sk_buff;
index c35dda9..56050f9 100644 (file)
@@ -305,6 +305,22 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
 
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask);
 
+static inline int iptunnel_pull_offloads(struct sk_buff *skb)
+{
+       if (skb_is_gso(skb)) {
+               int err;
+
+               err = skb_unclone(skb, GFP_ATOMIC);
+               if (unlikely(err))
+                       return err;
+               skb_shinfo(skb)->gso_type &= ~(NETIF_F_GSO_ENCAP_ALL >>
+                                              NETIF_F_GSO_SHIFT);
+       }
+
+       skb->encapsulation = 0;
+       return 0;
+}
+
 static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
 {
        if (pkt_len > 0) {
index f3c9857..d0aeb97 100644 (file)
@@ -835,6 +835,12 @@ static inline u8 ip6_tclass(__be32 flowinfo)
 {
        return ntohl(flowinfo & IPV6_TCLASS_MASK) >> IPV6_TCLASS_SHIFT;
 }
+
+static inline __be32 ip6_make_flowinfo(unsigned int tclass, __be32 flowlabel)
+{
+       return htonl(tclass << IPV6_TCLASS_SHIFT) | flowlabel;
+}
+
 /*
  *     Prototypes exported by ipv6
  */
index 835aa2e..65521cf 100644 (file)
 #define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT
 #endif
 
+/* Round an int up to the next multiple of 4.  */
+#define WORD_ROUND(s) (((s)+3)&~3)
+/* Truncate to the previous multiple of 4.  */
+#define WORD_TRUNC(s) ((s)&~3)
+
 /*
  * Function declarations.
  */
@@ -426,7 +431,7 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
        if (asoc->user_frag)
                frag = min_t(int, frag, asoc->user_frag);
 
-       frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN);
+       frag = WORD_TRUNC(min_t(int, frag, SCTP_MAX_CHUNK_LEN));
 
        return frag;
 }
@@ -475,9 +480,6 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\
      (void *)pos <= (void *)chunk->subh.fwdtsn_hdr->skip + end - sizeof(struct sctp_fwdtsn_skip);\
      pos++)
 
-/* Round an int up to the next multiple of 4.  */
-#define WORD_ROUND(s) (((s)+3)&~3)
-
 /* External references. */
 
 extern struct proto sctp_prot;
index e2ac062..6df1ce7 100644 (file)
@@ -1097,7 +1097,7 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
                        const struct sctp_bind_addr *src,
                        gfp_t gfp);
 int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
-                      __u8 addr_state, gfp_t gfp);
+                      int new_size, __u8 addr_state, gfp_t gfp);
 int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
 int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
                         struct sctp_sock *);
index a763c96..73ed2e9 100644 (file)
@@ -271,36 +271,36 @@ static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
 static inline __be32 vxlan_vni(__be32 vni_field)
 {
 #if defined(__BIG_ENDIAN)
-       return vni_field >> 8;
+       return (__force __be32)((__force u32)vni_field >> 8);
 #else
-       return (vni_field & VXLAN_VNI_MASK) << 8;
+       return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8);
 #endif
 }
 
 static inline __be32 vxlan_vni_field(__be32 vni)
 {
 #if defined(__BIG_ENDIAN)
-       return vni << 8;
+       return (__force __be32)((__force u32)vni << 8);
 #else
-       return vni >> 8;
+       return (__force __be32)((__force u32)vni >> 8);
 #endif
 }
 
 static inline __be32 vxlan_tun_id_to_vni(__be64 tun_id)
 {
 #if defined(__BIG_ENDIAN)
-       return tun_id;
+       return (__force __be32)tun_id;
 #else
-       return tun_id >> 32;
+       return (__force __be32)((__force u64)tun_id >> 32);
 #endif
 }
 
 static inline __be64 vxlan_vni_to_tun_id(__be32 vni)
 {
 #if defined(__BIG_ENDIAN)
-       return (__be64)vni;
+       return (__force __be64)vni;
 #else
-       return (__be64)vni << 32;
+       return (__force __be64)((u64)(__force u32)vni << 32);
 #endif
 }
 
index c7fa36c..33b29ea 100644 (file)
@@ -103,8 +103,6 @@ int cpm_muram_init(void);
 unsigned long cpm_muram_alloc(unsigned long size, unsigned long align);
 int cpm_muram_free(unsigned long offset);
 unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
-unsigned long cpm_muram_alloc_common(unsigned long size, genpool_algo_t algo,
-                                    void *data);
 void __iomem *cpm_muram_addr(unsigned long offset);
 unsigned long cpm_muram_offset(void __iomem *addr);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
index 4cf6bac..d60096c 100644 (file)
@@ -37,7 +37,7 @@ TRACE_EVENT(fib6_table_lookup,
                __entry->tb_id = tb_id;
                __entry->oif = flp->flowi6_oif;
                __entry->iif = flp->flowi6_iif;
-               __entry->tos = flp->flowi6_tos;
+               __entry->tos = ip6_tclass(flp->flowlabel);
                __entry->scope = flp->flowi6_scope;
                __entry->flags = flp->flowi6_flags;
 
index 2835b07..9222db8 100644 (file)
@@ -1648,9 +1648,9 @@ enum ethtool_reset_flags {
  *     %ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user
  *     (>= 0); on return, if handshake in progress, negative if
  *     request size unsupported by kernel: absolute value indicates
- *     kernel recommended size and cmd field is 0, as well as all the
- *     other fields; otherwise (handshake completed), strictly
- *     positive to indicate size used by kernel and cmd field is
+ *     kernel expected size and all the other fields but cmd
+ *     are 0; otherwise (handshake completed), strictly positive
+ *     to indicate size used by kernel and cmd field stays
  *     %ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For
  *     %ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive
  *     value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise
index 8e3f88f..76d315c 100644 (file)
@@ -153,6 +153,8 @@ enum {
        IFLA_LINK_NETNSID,
        IFLA_PHYS_PORT_NAME,
        IFLA_PROTO_DOWN,
+       IFLA_GSO_MAX_SEGS,
+       IFLA_GSO_MAX_SIZE,
        __IFLA_MAX
 };
 
index 1e889aa..8cd334f 100644 (file)
@@ -55,11 +55,35 @@ struct cxl_afu_id {
        __u64 reserved6;
 };
 
+/* base adapter image header is included in the image */
+#define CXL_AI_NEED_HEADER     0x0000000000000001ULL
+#define CXL_AI_ALL             CXL_AI_NEED_HEADER
+
+#define CXL_AI_HEADER_SIZE 128
+#define CXL_AI_BUFFER_SIZE 4096
+#define CXL_AI_MAX_ENTRIES 256
+#define CXL_AI_MAX_CHUNK_SIZE (CXL_AI_BUFFER_SIZE * CXL_AI_MAX_ENTRIES)
+
+struct cxl_adapter_image {
+       __u64 flags;
+       __u64 data;
+       __u64 len_data;
+       __u64 len_image;
+       __u64 reserved1;
+       __u64 reserved2;
+       __u64 reserved3;
+       __u64 reserved4;
+};
+
 /* ioctl numbers */
 #define CXL_MAGIC 0xCA
+/* AFU devices */
 #define CXL_IOCTL_START_WORK           _IOW(CXL_MAGIC, 0x00, struct cxl_ioctl_start_work)
 #define CXL_IOCTL_GET_PROCESS_ELEMENT  _IOR(CXL_MAGIC, 0x01, __u32)
 #define CXL_IOCTL_GET_AFU_ID            _IOR(CXL_MAGIC, 0x02, struct cxl_afu_id)
+/* adapter devices */
+#define CXL_IOCTL_DOWNLOAD_IMAGE        _IOW(CXL_MAGIC, 0x0A, struct cxl_adapter_image)
+#define CXL_IOCTL_VALIDATE_IMAGE        _IOW(CXL_MAGIC, 0x0B, struct cxl_adapter_image)
 
 #define CXL_READ_MIN_SIZE 0x1000 /* 4K */
 
index 021db17..fbfb1b8 100644 (file)
@@ -83,7 +83,7 @@ unsigned long transparent_hugepage_flags __read_mostly =
        (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
 
 /* default scan 8*512 pte (or vmas) every 30 second */
-static unsigned int khugepaged_pages_to_scan __read_mostly = HPAGE_PMD_NR*8;
+static unsigned int khugepaged_pages_to_scan __read_mostly;
 static unsigned int khugepaged_pages_collapsed;
 static unsigned int khugepaged_full_scans;
 static unsigned int khugepaged_scan_sleep_millisecs __read_mostly = 10000;
@@ -98,7 +98,7 @@ static DECLARE_WAIT_QUEUE_HEAD(khugepaged_wait);
  * it would have happened if the vma was large enough during page
  * fault.
  */
-static unsigned int khugepaged_max_ptes_none __read_mostly = HPAGE_PMD_NR-1;
+static unsigned int khugepaged_max_ptes_none __read_mostly;
 
 static int khugepaged(void *none);
 static int khugepaged_slab_init(void);
@@ -669,6 +669,18 @@ static int __init hugepage_init(void)
                return -EINVAL;
        }
 
+       khugepaged_pages_to_scan = HPAGE_PMD_NR * 8;
+       khugepaged_max_ptes_none = HPAGE_PMD_NR - 1;
+       /*
+        * hugepages can't be allocated by the buddy allocator
+        */
+       MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER >= MAX_ORDER);
+       /*
+        * we use page->mapping and page->index in second tail page
+        * as list_head: assuming THP order >= 2
+        */
+       MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER < 2);
+
        err = hugepage_init_sysfs(&hugepage_kobj);
        if (err)
                goto err_sysfs;
@@ -773,7 +785,6 @@ void prep_transhuge_page(struct page *page)
         * we use page->mapping and page->indexlru in second tail page
         * as list_head: assuming THP order >= 2
         */
-       BUILD_BUG_ON(HPAGE_PMD_ORDER < 2);
 
        INIT_LIST_HEAD(page_deferred_list(page));
        set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
index e134498..a8934d8 100644 (file)
@@ -397,7 +397,7 @@ config LWTUNNEL
          with light weight tunnel state associated with fib routes.
 
 config DST_CACHE
-       bool "dst cache"
+       bool
        default n
 
 config NET_DEVLINK
index a73df33..8217aec 100644 (file)
@@ -437,6 +437,20 @@ int br_min_mtu(const struct net_bridge *br)
        return mtu;
 }
 
+static void br_set_gso_limits(struct net_bridge *br)
+{
+       unsigned int gso_max_size = GSO_MAX_SIZE;
+       u16 gso_max_segs = GSO_MAX_SEGS;
+       const struct net_bridge_port *p;
+
+       list_for_each_entry(p, &br->port_list, list) {
+               gso_max_size = min(gso_max_size, p->dev->gso_max_size);
+               gso_max_segs = min(gso_max_segs, p->dev->gso_max_segs);
+       }
+       br->dev->gso_max_size = gso_max_size;
+       br->dev->gso_max_segs = gso_max_segs;
+}
+
 /*
  * Recomputes features using slave's features
  */
@@ -564,6 +578,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
                call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
 
        dev_set_mtu(br->dev, br_min_mtu(br));
+       br_set_gso_limits(br);
 
        kobject_uevent(&p->kobj, KOBJ_ADD);
 
@@ -610,6 +625,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
        del_nbp(p);
 
        dev_set_mtu(br->dev, br_min_mtu(br));
+       br_set_gso_limits(br);
 
        spin_lock_bh(&br->lock);
        changed_addr = br_stp_recalculate_bridge_id(br);
index edb7179..b9bcbe7 100644 (file)
@@ -4438,7 +4438,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
                NAPI_GRO_CB(skb)->same_flow = 0;
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
-               NAPI_GRO_CB(skb)->udp_mark = 0;
+               NAPI_GRO_CB(skb)->encap_mark = 0;
                NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
                /* Setup for GRO checksum validation */
@@ -6445,6 +6445,7 @@ EXPORT_SYMBOL(dev_get_phys_port_id);
  *     dev_get_phys_port_name - Get device physical port name
  *     @dev: device
  *     @name: port name
+ *     @len: limit of bytes to copy to name
  *
  *     Get device physical port name
  */
index 92d886f..4573d81 100644 (file)
@@ -191,6 +191,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
 /**
  * gen_new_estimator - create a new rate estimator
  * @bstats: basic statistics
+ * @cpu_bstats: bstats per cpu
  * @rate_est: rate estimator statistics
  * @stats_lock: statistics lock
  * @opt: rate estimator configuration TLV
@@ -287,6 +288,7 @@ EXPORT_SYMBOL(gen_kill_estimator);
 /**
  * gen_replace_estimator - replace rate estimator configuration
  * @bstats: basic statistics
+ * @cpu_bstats: bstats per cpu
  * @rate_est: rate estimator statistics
  * @stats_lock: statistics lock
  * @opt: rate estimator configuration TLV
index 1e2f46a..e640462 100644 (file)
@@ -140,6 +140,7 @@ EXPORT_SYMBOL(__gnet_stats_copy_basic);
 /**
  * gnet_stats_copy_basic - copy basic statistics into statistic TLV
  * @d: dumping handle
+ * @cpu: copy statistic per cpu
  * @b: basic statistics
  *
  * Appends the basic statistics to the top level TLV created by
index d2d9e5e..a69cd0c 100644 (file)
@@ -895,6 +895,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
               + nla_total_size(4) /* IFLA_PROMISCUITY */
               + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */
               + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
+              + nla_total_size(4) /* IFLA_MAX_GSO_SEGS */
+              + nla_total_size(4) /* IFLA_MAX_GSO_SIZE */
               + nla_total_size(1) /* IFLA_OPERSTATE */
               + nla_total_size(1) /* IFLA_LINKMODE */
               + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
@@ -1223,6 +1225,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
            nla_put_u32(skb, IFLA_GROUP, dev->group) ||
            nla_put_u32(skb, IFLA_PROMISCUITY, dev->promiscuity) ||
            nla_put_u32(skb, IFLA_NUM_TX_QUEUES, dev->num_tx_queues) ||
+           nla_put_u32(skb, IFLA_GSO_MAX_SEGS, dev->gso_max_segs) ||
+           nla_put_u32(skb, IFLA_GSO_MAX_SIZE, dev->gso_max_size) ||
 #ifdef CONFIG_RPS
            nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
 #endif
index f044f97..d04c2d1 100644 (file)
@@ -815,7 +815,7 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
        trace_consume_skb(skb);
 
        /* if SKB is a clone, don't handle this case */
-       if (unlikely(skb->fclone != SKB_FCLONE_UNAVAILABLE)) {
+       if (skb->fclone != SKB_FCLONE_UNAVAILABLE) {
                __kfree_skb(skb);
                return;
        }
index 0cc923f..9e48199 100644 (file)
@@ -1380,6 +1380,19 @@ out:
        return pp;
 }
 
+static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
+                                        struct sk_buff *skb)
+{
+       if (NAPI_GRO_CB(skb)->encap_mark) {
+               NAPI_GRO_CB(skb)->flush = 1;
+               return NULL;
+       }
+
+       NAPI_GRO_CB(skb)->encap_mark = 1;
+
+       return inet_gro_receive(head, skb);
+}
+
 #define SECONDS_PER_DAY        86400
 
 /* inet_current_timestamp - Return IP network timestamp
@@ -1402,7 +1415,7 @@ __be32 inet_current_timestamp(void)
        msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC;
 
        /* Convert to network byte order. */
-       return htons(msecs);
+       return htonl(msecs);
 }
 EXPORT_SYMBOL(inet_current_timestamp);
 
@@ -1448,6 +1461,13 @@ out_unlock:
        return err;
 }
 
+static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
+{
+       skb->encapsulation = 1;
+       skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
+       return inet_gro_complete(skb, nhoff);
+}
+
 int inet_ctl_sock_create(struct sock **sk, unsigned short family,
                         unsigned short type, unsigned char protocol,
                         struct net *net)
@@ -1675,8 +1695,8 @@ static struct packet_offload ip_packet_offload __read_mostly = {
 static const struct net_offload ipip_offload = {
        .callbacks = {
                .gso_segment    = inet_gso_segment,
-               .gro_receive    = inet_gro_receive,
-               .gro_complete   = inet_gro_complete,
+               .gro_receive    = ipip_gro_receive,
+               .gro_complete   = ipip_gro_complete,
        },
 };
 
index 21add55..8a9246d 100644 (file)
@@ -280,7 +280,6 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
        struct in_device *in_dev;
        struct fib_result res;
        struct rtable *rt;
-       struct flowi4 fl4;
        struct net *net;
        int scope;
 
@@ -296,14 +295,13 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
 
        scope = RT_SCOPE_UNIVERSE;
        if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
-               fl4.flowi4_oif = 0;
-               fl4.flowi4_iif = LOOPBACK_IFINDEX;
-               fl4.daddr = ip_hdr(skb)->saddr;
-               fl4.saddr = 0;
-               fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
-               fl4.flowi4_scope = scope;
-               fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
-               fl4.flowi4_tun_key.tun_id = 0;
+               struct flowi4 fl4 = {
+                       .flowi4_iif = LOOPBACK_IFINDEX,
+                       .daddr = ip_hdr(skb)->saddr,
+                       .flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
+                       .flowi4_scope = scope,
+                       .flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0,
+               };
                if (!fib_lookup(net, &fl4, &res, 0))
                        return FIB_RES_PREFSRC(net, res);
        } else {
index 7804842..a0586b4 100644 (file)
@@ -48,7 +48,7 @@ static inline struct fou *fou_from_sock(struct sock *sk)
        return sk->sk_user_data;
 }
 
-static void fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, size_t len)
 {
        struct iphdr *iph = ip_hdr(skb);
 
@@ -59,6 +59,7 @@ static void fou_recv_pull(struct sk_buff *skb, size_t len)
        __skb_pull(skb, len);
        skb_postpull_rcsum(skb, udp_hdr(skb), len);
        skb_reset_transport_header(skb);
+       return iptunnel_pull_offloads(skb);
 }
 
 static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
@@ -68,9 +69,14 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
        if (!fou)
                return 1;
 
-       fou_recv_pull(skb, sizeof(struct udphdr));
+       if (fou_recv_pull(skb, sizeof(struct udphdr)))
+               goto drop;
 
        return -fou->protocol;
+
+drop:
+       kfree_skb(skb);
+       return 0;
 }
 
 static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
@@ -170,6 +176,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
        __skb_pull(skb, sizeof(struct udphdr) + hdrlen);
        skb_reset_transport_header(skb);
 
+       if (iptunnel_pull_offloads(skb))
+               goto drop;
+
        return -guehdr->proto_ctype;
 
 drop:
index 540866d..dd03161 100644 (file)
@@ -126,6 +126,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
        struct packet_offload *ptype;
        __be16 type;
 
+       if (NAPI_GRO_CB(skb)->encap_mark)
+               goto out;
+
+       NAPI_GRO_CB(skb)->encap_mark = 1;
+
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*greh);
        greh = skb_gro_header_fast(skb, off);
index d27276f..02dd990 100644 (file)
@@ -114,7 +114,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto,
        skb->vlan_tci = 0;
        skb_set_queue_mapping(skb, 0);
        skb_scrub_packet(skb, xnet);
-       return 0;
+
+       return iptunnel_pull_offloads(skb);
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
index 836abe5..08eed5e 100644 (file)
@@ -2070,10 +2070,14 @@ void udp_v4_early_demux(struct sk_buff *skb)
                if (!in_dev)
                        return;
 
-               ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
-                                      iph->protocol);
-               if (!ours)
-                       return;
+               /* we are supposed to accept bcast packets */
+               if (skb->pkt_type == PACKET_MULTICAST) {
+                       ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
+                                              iph->protocol);
+                       if (!ours)
+                               return;
+               }
+
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
                                                   uh->source, iph->saddr, dif);
        } else if (skb->pkt_type == PACKET_HOST) {
index 8a3405a..8007f73 100644 (file)
@@ -311,14 +311,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
        unsigned int off = skb_gro_offset(skb);
        int flush = 1;
 
-       if (NAPI_GRO_CB(skb)->udp_mark ||
+       if (NAPI_GRO_CB(skb)->encap_mark ||
            (skb->ip_summed != CHECKSUM_PARTIAL &&
             NAPI_GRO_CB(skb)->csum_cnt == 0 &&
             !NAPI_GRO_CB(skb)->csum_valid))
                goto out;
 
-       /* mark that this skb passed once through the udp gro layer */
-       NAPI_GRO_CB(skb)->udp_mark = 1;
+       /* mark that this skb passed once through the tunnel gro layer */
+       NAPI_GRO_CB(skb)->encap_mark = 1;
 
        rcu_read_lock();
        uo_priv = rcu_dereference(udp_offload_base);
index eeca943..82e9f30 100644 (file)
@@ -258,6 +258,19 @@ out:
        return pp;
 }
 
+static struct sk_buff **sit_gro_receive(struct sk_buff **head,
+                                       struct sk_buff *skb)
+{
+       if (NAPI_GRO_CB(skb)->encap_mark) {
+               NAPI_GRO_CB(skb)->flush = 1;
+               return NULL;
+       }
+
+       NAPI_GRO_CB(skb)->encap_mark = 1;
+
+       return ipv6_gro_receive(head, skb);
+}
+
 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 {
        const struct net_offload *ops;
@@ -302,7 +315,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
 static const struct net_offload sit_offload = {
        .callbacks = {
                .gso_segment    = ipv6_gso_segment,
-               .gro_receive    = ipv6_gro_receive,
+               .gro_receive    = sit_gro_receive,
                .gro_complete   = sit_gro_complete,
        },
 };
index f45b8ff..8338430 100644 (file)
@@ -681,14 +681,16 @@ static int ipip6_rcv(struct sk_buff *skb)
                skb->mac_header = skb->network_header;
                skb_reset_network_header(skb);
                IPCB(skb)->flags = 0;
-               skb->protocol = htons(ETH_P_IPV6);
+               skb->dev = tunnel->dev;
 
                if (packet_is_spoofed(skb, iph, tunnel)) {
                        tunnel->dev->stats.rx_errors++;
                        goto out;
                }
 
-               __skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
+               if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
+                   !net_eq(tunnel->net, dev_net(tunnel->dev))))
+                       goto out;
 
                err = IP_ECN_decapsulate(iph, skb);
                if (unlikely(err)) {
index c841679..215fc08 100644 (file)
@@ -1033,6 +1033,14 @@ static int netlink_getname(struct socket *sock, struct sockaddr *addr,
        return 0;
 }
 
+static int netlink_ioctl(struct socket *sock, unsigned int cmd,
+                        unsigned long arg)
+{
+       /* try to hand this ioctl down to the NIC drivers.
+        */
+       return -ENOIOCTLCMD;
+}
+
 static struct sock *netlink_getsockbyportid(struct sock *ssk, u32 portid)
 {
        struct sock *sock;
@@ -2494,7 +2502,7 @@ static const struct proto_ops netlink_ops = {
        .accept =       sock_no_accept,
        .getname =      netlink_getname,
        .poll =         datagram_poll,
-       .ioctl =        sock_no_ioctl,
+       .ioctl =        netlink_ioctl,
        .listen =       sock_no_listen,
        .shutdown =     sock_no_shutdown,
        .setsockopt =   netlink_setsockopt,
index a19b3e6..e1849f3 100644 (file)
@@ -1406,7 +1406,8 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc)
        list_for_each_entry(t, &asoc->peer.transport_addr_list,
                                transports) {
                if (t->pmtu_pending && t->dst) {
-                       sctp_transport_update_pmtu(sk, t, dst_mtu(t->dst));
+                       sctp_transport_update_pmtu(sk, t,
+                                                  WORD_TRUNC(dst_mtu(t->dst)));
                        t->pmtu_pending = 0;
                }
                if (!pmtu || (t->pathmtu < pmtu))
index 871cdf9..401c607 100644 (file)
@@ -111,7 +111,8 @@ int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
        dest->port = src->port;
 
        list_for_each_entry(addr, &src->address_list, list) {
-               error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
+               error = sctp_add_bind_addr(dest, &addr->a, sizeof(addr->a),
+                                          1, gfp);
                if (error < 0)
                        break;
        }
@@ -150,7 +151,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 
 /* Add an address to the bind address list in the SCTP_bind_addr structure. */
 int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
-                      __u8 addr_state, gfp_t gfp)
+                      int new_size, __u8 addr_state, gfp_t gfp)
 {
        struct sctp_sockaddr_entry *addr;
 
@@ -159,7 +160,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
        if (!addr)
                return -ENOMEM;
 
-       memcpy(&addr->a, new, sizeof(*new));
+       memcpy(&addr->a, new, min_t(size_t, sizeof(*new), new_size));
 
        /* Fix up the port if it has not yet been set.
         * Both v4 and v6 have the port at the same offset.
@@ -291,7 +292,8 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
                }
 
                af->from_addr_param(&addr, rawaddr, htons(port), 0);
-               retval = sctp_add_bind_addr(bp, &addr, SCTP_ADDR_SRC, gfp);
+               retval = sctp_add_bind_addr(bp, &addr, sizeof(addr),
+                                           SCTP_ADDR_SRC, gfp);
                if (retval) {
                        /* Can't finish building the list, clean up. */
                        sctp_bind_addr_clean(bp);
@@ -453,8 +455,8 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
                    (((AF_INET6 == addr->sa.sa_family) &&
                      (flags & SCTP_ADDR6_ALLOWED) &&
                      (flags & SCTP_ADDR6_PEERSUPP))))
-                       error = sctp_add_bind_addr(dest, addr, SCTP_ADDR_SRC,
-                                                   gfp);
+                       error = sctp_add_bind_addr(dest, addr, sizeof(*addr),
+                                                  SCTP_ADDR_SRC, gfp);
        }
 
        return error;
index db76f1a..00b8445 100644 (file)
@@ -606,7 +606,8 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 
                /* PMTU discovery (RFC1191) */
                if (ICMP_FRAG_NEEDED == code) {
-                       sctp_icmp_frag_needed(sk, asoc, transport, info);
+                       sctp_icmp_frag_needed(sk, asoc, transport,
+                                             WORD_TRUNC(info));
                        goto out_unlock;
                } else {
                        if (ICMP_PROT_UNREACH == code) {
index f03541d..8d3d362 100644 (file)
@@ -978,8 +978,12 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
                             (new_transport->state == SCTP_UNCONFIRMED) ||
                             (new_transport->state == SCTP_PF)))
                                new_transport = asoc->peer.active_path;
-                       if (new_transport->state == SCTP_UNCONFIRMED)
+                       if (new_transport->state == SCTP_UNCONFIRMED) {
+                               WARN_ONCE(1, "Atempt to send packet on unconfirmed path.");
+                               sctp_chunk_fail(chunk, 0);
+                               sctp_chunk_free(chunk);
                                continue;
+                       }
 
                        /* Change packets if necessary.  */
                        if (new_transport != transport) {
index 1099e99..d3d50da 100644 (file)
@@ -216,6 +216,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
                              (copy_flags & SCTP_ADDR6_ALLOWED) &&
                              (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
                                error = sctp_add_bind_addr(bp, &addr->a,
+                                                   sizeof(addr->a),
                                                    SCTP_ADDR_SRC, GFP_ATOMIC);
                                if (error)
                                        goto end_copy;
index e47abf2..7f0bf79 100644 (file)
@@ -1849,7 +1849,8 @@ no_hmac:
        /* Also, add the destination address. */
        if (list_empty(&retval->base.bind_addr.address_list)) {
                sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
-                               SCTP_ADDR_SRC, GFP_ATOMIC);
+                                  sizeof(chunk->dest), SCTP_ADDR_SRC,
+                                  GFP_ATOMIC);
        }
 
        retval->next_tsn = retval->c.initial_tsn;
index 3c22c41..7fe56d0 100644 (file)
@@ -215,10 +215,14 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
        } else {
+               __u32 old_a_rwnd = asoc->a_rwnd;
+
                asoc->a_rwnd = asoc->rwnd;
                sack = sctp_make_sack(asoc);
-               if (!sack)
+               if (!sack) {
+                       asoc->a_rwnd = old_a_rwnd;
                        goto nomem;
+               }
 
                asoc->peer.sack_needed = 0;
                asoc->peer.sack_cnt = 0;
index 96e0811..a44a97c 100644 (file)
@@ -386,7 +386,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
        /* Add the address to the bind address list.
         * Use GFP_ATOMIC since BHs will be disabled.
         */
-       ret = sctp_add_bind_addr(bp, addr, SCTP_ADDR_SRC, GFP_ATOMIC);
+       ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
+                                SCTP_ADDR_SRC, GFP_ATOMIC);
 
        /* Copy back into socket for getsockname() use. */
        if (!ret) {
@@ -577,6 +578,7 @@ static int sctp_send_asconf_add_ip(struct sock              *sk,
                        af = sctp_get_af_specific(addr->v4.sin_family);
                        memcpy(&saveaddr, addr, af->sockaddr_len);
                        retval = sctp_add_bind_addr(bp, &saveaddr,
+                                                   sizeof(saveaddr),
                                                    SCTP_ADDR_NEW, GFP_ATOMIC);
                        addr_buf += af->sockaddr_len;
                }
index d517153..9b6b48c 100644 (file)
@@ -226,7 +226,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
        }
 
        if (transport->dst) {
-               transport->pathmtu = dst_mtu(transport->dst);
+               transport->pathmtu = WORD_TRUNC(dst_mtu(transport->dst));
        } else
                transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
 }
@@ -280,7 +280,7 @@ void sctp_transport_route(struct sctp_transport *transport,
                return;
        }
        if (transport->dst) {
-               transport->pathmtu = dst_mtu(transport->dst);
+               transport->pathmtu = WORD_TRUNC(dst_mtu(transport->dst));
 
                /* Initialize sk->sk_rcv_saddr, if the transport is the
                 * association's active path for getsockname().
index bbe65dc..3dce53e 100644 (file)
@@ -1209,10 +1209,14 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
 
                if (signal_pending(current)) {
                        err = sock_intr_errno(timeout);
-                       goto out_wait_error;
+                       sk->sk_state = SS_UNCONNECTED;
+                       sock->state = SS_UNCONNECTED;
+                       goto out_wait;
                } else if (timeout == 0) {
                        err = -ETIMEDOUT;
-                       goto out_wait_error;
+                       sk->sk_state = SS_UNCONNECTED;
+                       sock->state = SS_UNCONNECTED;
+                       goto out_wait;
                }
 
                prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
@@ -1220,20 +1224,17 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
 
        if (sk->sk_err) {
                err = -sk->sk_err;
-               goto out_wait_error;
-       } else
+               sk->sk_state = SS_UNCONNECTED;
+               sock->state = SS_UNCONNECTED;
+       } else {
                err = 0;
+       }
 
 out_wait:
        finish_wait(sk_sleep(sk), &wait);
 out:
        release_sock(sk);
        return err;
-
-out_wait_error:
-       sk->sk_state = SS_UNCONNECTED;
-       sock->state = SS_UNCONNECTED;
-       goto out_wait;
 }
 
 static int vsock_accept(struct socket *sock, struct socket *newsock, int flags)
@@ -1270,18 +1271,20 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags)
               listener->sk_err == 0) {
                release_sock(listener);
                timeout = schedule_timeout(timeout);
+               finish_wait(sk_sleep(listener), &wait);
                lock_sock(listener);
 
                if (signal_pending(current)) {
                        err = sock_intr_errno(timeout);
-                       goto out_wait;
+                       goto out;
                } else if (timeout == 0) {
                        err = -EAGAIN;
-                       goto out_wait;
+                       goto out;
                }
 
                prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
        }
+       finish_wait(sk_sleep(listener), &wait);
 
        if (listener->sk_err)
                err = -listener->sk_err;
@@ -1301,19 +1304,15 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags)
                 */
                if (err) {
                        vconnected->rejected = true;
-                       release_sock(connected);
-                       sock_put(connected);
-                       goto out_wait;
+               } else {
+                       newsock->state = SS_CONNECTED;
+                       sock_graft(connected, newsock);
                }
 
-               newsock->state = SS_CONNECTED;
-               sock_graft(connected, newsock);
                release_sock(connected);
                sock_put(connected);
        }
 
-out_wait:
-       finish_wait(sk_sleep(listener), &wait);
 out:
        release_sock(listener);
        return err;
@@ -1557,9 +1556,11 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
        if (err < 0)
                goto out;
 
+
        while (total_written < len) {
                ssize_t written;
 
+               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
                while (vsock_stream_has_space(vsk) == 0 &&
                       sk->sk_err == 0 &&
                       !(sk->sk_shutdown & SEND_SHUTDOWN) &&
@@ -1568,27 +1569,33 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                        /* Don't wait for non-blocking sockets. */
                        if (timeout == 0) {
                                err = -EAGAIN;
-                               goto out_wait;
+                               finish_wait(sk_sleep(sk), &wait);
+                               goto out_err;
                        }
 
                        err = transport->notify_send_pre_block(vsk, &send_data);
-                       if (err < 0)
-                               goto out_wait;
+                       if (err < 0) {
+                               finish_wait(sk_sleep(sk), &wait);
+                               goto out_err;
+                       }
 
                        release_sock(sk);
-                       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
                        timeout = schedule_timeout(timeout);
-                       finish_wait(sk_sleep(sk), &wait);
                        lock_sock(sk);
                        if (signal_pending(current)) {
                                err = sock_intr_errno(timeout);
-                               goto out_wait;
+                               finish_wait(sk_sleep(sk), &wait);
+                               goto out_err;
                        } else if (timeout == 0) {
                                err = -EAGAIN;
-                               goto out_wait;
+                               finish_wait(sk_sleep(sk), &wait);
+                               goto out_err;
                        }
 
+                       prepare_to_wait(sk_sleep(sk), &wait,
+                                       TASK_INTERRUPTIBLE);
                }
+               finish_wait(sk_sleep(sk), &wait);
 
                /* These checks occur both as part of and after the loop
                 * conditional since we need to check before and after
@@ -1596,16 +1603,16 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                 */
                if (sk->sk_err) {
                        err = -sk->sk_err;
-                       goto out_wait;
+                       goto out_err;
                } else if ((sk->sk_shutdown & SEND_SHUTDOWN) ||
                           (vsk->peer_shutdown & RCV_SHUTDOWN)) {
                        err = -EPIPE;
-                       goto out_wait;
+                       goto out_err;
                }
 
                err = transport->notify_send_pre_enqueue(vsk, &send_data);
                if (err < 0)
-                       goto out_wait;
+                       goto out_err;
 
                /* Note that enqueue will only write as many bytes as are free
                 * in the produce queue, so we don't need to ensure len is
@@ -1618,7 +1625,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                                len - total_written);
                if (written < 0) {
                        err = -ENOMEM;
-                       goto out_wait;
+                       goto out_err;
                }
 
                total_written += written;
@@ -1626,11 +1633,11 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                err = transport->notify_send_post_enqueue(
                                vsk, written, &send_data);
                if (err < 0)
-                       goto out_wait;
+                       goto out_err;
 
        }
 
-out_wait:
+out_err:
        if (total_written > 0)
                err = total_written;
 out:
@@ -1715,18 +1722,59 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
 
        while (1) {
-               s64 ready = vsock_stream_has_data(vsk);
+               s64 ready;
 
-               if (ready < 0) {
-                       /* Invalid queue pair content. XXX This should be
-                        * changed to a connection reset in a later change.
-                        */
+               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+               ready = vsock_stream_has_data(vsk);
 
-                       err = -ENOMEM;
-                       goto out;
-               } else if (ready > 0) {
+               if (ready == 0) {
+                       if (sk->sk_err != 0 ||
+                           (sk->sk_shutdown & RCV_SHUTDOWN) ||
+                           (vsk->peer_shutdown & SEND_SHUTDOWN)) {
+                               finish_wait(sk_sleep(sk), &wait);
+                               break;
+                       }
+                       /* Don't wait for non-blocking sockets. */
+                       if (timeout == 0) {
+                               err = -EAGAIN;
+                               finish_wait(sk_sleep(sk), &wait);
+                               break;
+                       }
+
+                       err = transport->notify_recv_pre_block(
+                                       vsk, target, &recv_data);
+                       if (err < 0) {
+                               finish_wait(sk_sleep(sk), &wait);
+                               break;
+                       }
+                       release_sock(sk);
+                       timeout = schedule_timeout(timeout);
+                       lock_sock(sk);
+
+                       if (signal_pending(current)) {
+                               err = sock_intr_errno(timeout);
+                               finish_wait(sk_sleep(sk), &wait);
+                               break;
+                       } else if (timeout == 0) {
+                               err = -EAGAIN;
+                               finish_wait(sk_sleep(sk), &wait);
+                               break;
+                       }
+               } else {
                        ssize_t read;
 
+                       finish_wait(sk_sleep(sk), &wait);
+
+                       if (ready < 0) {
+                               /* Invalid queue pair content. XXX This should
+                               * be changed to a connection reset in a later
+                               * change.
+                               */
+
+                               err = -ENOMEM;
+                               goto out;
+                       }
+
                        err = transport->notify_recv_pre_dequeue(
                                        vsk, target, &recv_data);
                        if (err < 0)
@@ -1752,35 +1800,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
                                break;
 
                        target -= read;
-               } else {
-                       if (sk->sk_err != 0 || (sk->sk_shutdown & RCV_SHUTDOWN)
-                           || (vsk->peer_shutdown & SEND_SHUTDOWN)) {
-                               break;
-                       }
-                       /* Don't wait for non-blocking sockets. */
-                       if (timeout == 0) {
-                               err = -EAGAIN;
-                               break;
-                       }
-
-                       err = transport->notify_recv_pre_block(
-                                       vsk, target, &recv_data);
-                       if (err < 0)
-                               break;
-
-                       release_sock(sk);
-                       prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
-                       timeout = schedule_timeout(timeout);
-                       finish_wait(sk_sleep(sk), &wait);
-                       lock_sock(sk);
-
-                       if (signal_pending(current)) {
-                               err = sock_intr_errno(timeout);
-                               break;
-                       } else if (timeout == 0) {
-                               err = -EAGAIN;
-                               break;
-                       }
                }
        }
 
index 2edbcad..ad50d58 100644 (file)
@@ -269,6 +269,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
 
 # DTC
 # ---------------------------------------------------------------------------
+DTC ?= $(objtree)/scripts/dtc/dtc
 
 # Generate an assembly file to wrap the output of the device tree compiler
 quiet_cmd_dt_S_dtb= DTB     $@
@@ -291,7 +292,7 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
        $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
-       $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
+       $(DTC) -O dtb -o $@ -b 0 \
                -i $(dir $<) $(DTC_FLAGS) \
                -d $(depfile).dtc.tmp $(dtc-tmp) ; \
        cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
index e81a8c7..0c03ac9 100644 (file)
@@ -560,7 +560,7 @@ static void check_reg_format(struct check *c, struct node *dt,
        size_cells = node_size_cells(node->parent);
        entrylen = (addr_cells + size_cells) * sizeof(cell_t);
 
-       if ((prop->val.len % entrylen) != 0)
+       if (!entrylen || (prop->val.len % entrylen) != 0)
                FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
                     "(#address-cells == %d, #size-cells == %d)",
                     node->fullpath, prop->val.len, addr_cells, size_cells);
index 0ee1caf..790fbf6 100644 (file)
@@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...);
                }
 
 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
-                       char *line, *tmp, *fn;
+                       char *line, *fnstart, *fnend;
+                       struct data fn;
                        /* skip text before line # */
                        line = yytext;
                        while (!isdigit((unsigned char)*line))
                                line++;
-                       /* skip digits in line # */
-                       tmp = line;
-                       while (!isspace((unsigned char)*tmp))
-                               tmp++;
-                       /* "NULL"-terminate line # */
-                       *tmp = '\0';
-                       /* start of filename */
-                       fn = strchr(tmp + 1, '"') + 1;
-                       /* strip trailing " from filename */
-                       tmp = strchr(fn, '"');
-                       *tmp = 0;
+
+                       /* regexp ensures that first and list "
+                        * in the whole yytext are those at
+                        * beginning and end of the filename string */
+                       fnstart = memchr(yytext, '"', yyleng);
+                       for (fnend = yytext + yyleng - 1;
+                            *fnend != '"'; fnend--)
+                               ;
+                       assert(fnstart && fnend && (fnend > fnstart));
+
+                       fn = data_copy_escape_string(fnstart + 1,
+                                                    fnend - fnstart - 1);
+
+                       /* Don't allow nuls in filenames */
+                       if (memchr(fn.val, '\0', fn.len - 1))
+                               lexical_error("nul in line number directive");
+
                        /* -1 since #line is the number of the next line */
-                       srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+                       srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+                       data_free(fn);
                }
 
 <*><<EOF>>             {
@@ -153,7 +161,10 @@ static void lexical_error(const char *fmt, ...);
                        errno = 0;
                        yylval.integer = strtoull(yytext, &e, 0);
 
-                       assert(!(*e) || !e[strspn(e, "UL")]);
+                       if (*e && e[strspn(e, "UL")]) {
+                               lexical_error("Bad integer literal '%s'",
+                                             yytext);
+                       }
 
                        if (errno == ERANGE)
                                lexical_error("Integer literal '%s' out of range",
index 11cd78e..ba525c2 100644 (file)
@@ -951,31 +951,39 @@ case 2:
 YY_RULE_SETUP
 #line 75 "dtc-lexer.l"
 {
-                       char *line, *tmp, *fn;
+                       char *line, *fnstart, *fnend;
+                       struct data fn;
                        /* skip text before line # */
                        line = yytext;
                        while (!isdigit((unsigned char)*line))
                                line++;
-                       /* skip digits in line # */
-                       tmp = line;
-                       while (!isspace((unsigned char)*tmp))
-                               tmp++;
-                       /* "NULL"-terminate line # */
-                       *tmp = '\0';
-                       /* start of filename */
-                       fn = strchr(tmp + 1, '"') + 1;
-                       /* strip trailing " from filename */
-                       tmp = strchr(fn, '"');
-                       *tmp = 0;
+
+                       /* regexp ensures that first and list "
+                        * in the whole yytext are those at
+                        * beginning and end of the filename string */
+                       fnstart = memchr(yytext, '"', yyleng);
+                       for (fnend = yytext + yyleng - 1;
+                            *fnend != '"'; fnend--)
+                               ;
+                       assert(fnstart && fnend && (fnend > fnstart));
+
+                       fn = data_copy_escape_string(fnstart + 1,
+                                                    fnend - fnstart - 1);
+
+                       /* Don't allow nuls in filenames */
+                       if (memchr(fn.val, '\0', fn.len - 1))
+                               lexical_error("nul in line number directive");
+
                        /* -1 since #line is the number of the next line */
-                       srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+                       srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
+                       data_free(fn);
                }
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(BYTESTRING):
 case YY_STATE_EOF(PROPNODENAME):
 case YY_STATE_EOF(V1):
-#line 96 "dtc-lexer.l"
+#line 104 "dtc-lexer.l"
 {
                        if (!pop_input_file()) {
                                yyterminate();
@@ -985,7 +993,7 @@ case YY_STATE_EOF(V1):
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 102 "dtc-lexer.l"
+#line 110 "dtc-lexer.l"
 {
                        DPRINT("String: %s\n", yytext);
                        yylval.data = data_copy_escape_string(yytext+1,
@@ -995,7 +1003,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 109 "dtc-lexer.l"
+#line 117 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /dts-v1/\n");
                        dts_version = 1;
@@ -1005,7 +1013,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 116 "dtc-lexer.l"
+#line 124 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /memreserve/\n");
                        BEGIN_DEFAULT();
@@ -1014,7 +1022,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 122 "dtc-lexer.l"
+#line 130 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /bits/\n");
                        BEGIN_DEFAULT();
@@ -1023,7 +1031,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 128 "dtc-lexer.l"
+#line 136 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-property/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1033,7 +1041,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 135 "dtc-lexer.l"
+#line 143 "dtc-lexer.l"
 {
                        DPRINT("Keyword: /delete-node/\n");
                        DPRINT("<PROPNODENAME>\n");
@@ -1043,7 +1051,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 142 "dtc-lexer.l"
+#line 150 "dtc-lexer.l"
 {
                        DPRINT("Label: %s\n", yytext);
                        yylval.labelref = xstrdup(yytext);
@@ -1053,7 +1061,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 149 "dtc-lexer.l"
+#line 157 "dtc-lexer.l"
 {
                        char *e;
                        DPRINT("Integer Literal: '%s'\n", yytext);
@@ -1061,7 +1069,10 @@ YY_RULE_SETUP
                        errno = 0;
                        yylval.integer = strtoull(yytext, &e, 0);
 
-                       assert(!(*e) || !e[strspn(e, "UL")]);
+                       if (*e && e[strspn(e, "UL")]) {
+                               lexical_error("Bad integer literal '%s'",
+                                             yytext);
+                       }
 
                        if (errno == ERANGE)
                                lexical_error("Integer literal '%s' out of range",
@@ -1076,7 +1087,7 @@ YY_RULE_SETUP
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 168 "dtc-lexer.l"
+#line 179 "dtc-lexer.l"
 {
                        struct data d;
                        DPRINT("Character literal: %s\n", yytext);
@@ -1100,7 +1111,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 189 "dtc-lexer.l"
+#line 200 "dtc-lexer.l"
 {      /* label reference */
                        DPRINT("Ref: %s\n", yytext+1);
                        yylval.labelref = xstrdup(yytext+1);
@@ -1109,7 +1120,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 195 "dtc-lexer.l"
+#line 206 "dtc-lexer.l"
 {      /* new-style path reference */
                        yytext[yyleng-1] = '\0';
                        DPRINT("Ref: %s\n", yytext+2);
@@ -1119,7 +1130,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 202 "dtc-lexer.l"
+#line 213 "dtc-lexer.l"
 {
                        yylval.byte = strtol(yytext, NULL, 16);
                        DPRINT("Byte: %02x\n", (int)yylval.byte);
@@ -1128,7 +1139,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 208 "dtc-lexer.l"
+#line 219 "dtc-lexer.l"
 {
                        DPRINT("/BYTESTRING\n");
                        BEGIN_DEFAULT();
@@ -1137,7 +1148,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 214 "dtc-lexer.l"
+#line 225 "dtc-lexer.l"
 {
                        DPRINT("PropNodeName: %s\n", yytext);
                        yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1148,7 +1159,7 @@ YY_RULE_SETUP
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 222 "dtc-lexer.l"
+#line 233 "dtc-lexer.l"
 {
                        DPRINT("Binary Include\n");
                        return DT_INCBIN;
@@ -1157,64 +1168,64 @@ YY_RULE_SETUP
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
-#line 227 "dtc-lexer.l"
+#line 238 "dtc-lexer.l"
 /* eat whitespace */
        YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 228 "dtc-lexer.l"
+#line 239 "dtc-lexer.l"
 /* eat C-style comments */
        YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 229 "dtc-lexer.l"
+#line 240 "dtc-lexer.l"
 /* eat C++-style comments */
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 231 "dtc-lexer.l"
+#line 242 "dtc-lexer.l"
 { return DT_LSHIFT; };
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 232 "dtc-lexer.l"
+#line 243 "dtc-lexer.l"
 { return DT_RSHIFT; };
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 233 "dtc-lexer.l"
+#line 244 "dtc-lexer.l"
 { return DT_LE; };
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 234 "dtc-lexer.l"
+#line 245 "dtc-lexer.l"
 { return DT_GE; };
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 235 "dtc-lexer.l"
+#line 246 "dtc-lexer.l"
 { return DT_EQ; };
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 236 "dtc-lexer.l"
+#line 247 "dtc-lexer.l"
 { return DT_NE; };
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 237 "dtc-lexer.l"
+#line 248 "dtc-lexer.l"
 { return DT_AND; };
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 238 "dtc-lexer.l"
+#line 249 "dtc-lexer.l"
 { return DT_OR; };
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 240 "dtc-lexer.l"
+#line 251 "dtc-lexer.l"
 {
                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
                                (unsigned)yytext[0]);
@@ -1232,10 +1243,10 @@ YY_RULE_SETUP
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 255 "dtc-lexer.l"
+#line 266 "dtc-lexer.l"
 ECHO;
        YY_BREAK
-#line 1239 "dtc-lexer.lex.c"
+#line 1250 "dtc-lexer.lex.c"
 
        case YY_END_OF_BUFFER:
                {
@@ -2195,7 +2206,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 254 "dtc-lexer.l"
+#line 265 "dtc-lexer.l"
 
 
 
index 116458c..31cec50 100644 (file)
@@ -499,9 +499,9 @@ static const yytype_uint16 yyrline[] =
      298,   303,   322,   336,   343,   344,   345,   352,   356,   357,
      361,   362,   366,   367,   371,   372,   376,   377,   381,   382,
      386,   387,   388,   392,   393,   394,   395,   396,   400,   401,
-     402,   406,   407,   408,   412,   413,   414,   415,   419,   420,
-     421,   422,   427,   430,   434,   442,   445,   449,   457,   461,
-     465
+     402,   406,   407,   408,   412,   413,   422,   431,   435,   436,
+     437,   438,   443,   446,   450,   458,   461,   465,   473,   477,
+     481
 };
 #endif
 
@@ -1909,111 +1909,125 @@ yyreduce:
     break;
 
   case 65:
-#line 413 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
-#line 1915 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 414 "dtc-parser.y" /* yacc.c:1646  */
+    {
+                       if ((yyvsp[0].integer) != 0) {
+                               (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
+                       } else {
+                               ERROR(&(yyloc), "Division by zero");
+                               (yyval.integer) = 0;
+                       }
+               }
+#line 1922 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 414 "dtc-parser.y" /* yacc.c:1646  */
-    { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
-#line 1921 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 423 "dtc-parser.y" /* yacc.c:1646  */
+    {
+                       if ((yyvsp[0].integer) != 0) {
+                               (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
+                       } else {
+                               ERROR(&(yyloc), "Division by zero");
+                               (yyval.integer) = 0;
+                       }
+               }
+#line 1935 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 420 "dtc-parser.y" /* yacc.c:1646  */
+#line 436 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = -(yyvsp[0].integer); }
-#line 1927 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1941 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 421 "dtc-parser.y" /* yacc.c:1646  */
+#line 437 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = ~(yyvsp[0].integer); }
-#line 1933 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1947 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 422 "dtc-parser.y" /* yacc.c:1646  */
+#line 438 "dtc-parser.y" /* yacc.c:1646  */
     { (yyval.integer) = !(yyvsp[0].integer); }
-#line 1939 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1953 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 427 "dtc-parser.y" /* yacc.c:1646  */
+#line 443 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = empty_data;
                }
-#line 1947 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1961 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 431 "dtc-parser.y" /* yacc.c:1646  */
+#line 447 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
                }
-#line 1955 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1969 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 435 "dtc-parser.y" /* yacc.c:1646  */
+#line 451 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
                }
-#line 1963 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1977 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 442 "dtc-parser.y" /* yacc.c:1646  */
+#line 458 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.nodelist) = NULL;
                }
-#line 1971 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1985 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 446 "dtc-parser.y" /* yacc.c:1646  */
+#line 462 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
                }
-#line 1979 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 1993 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 450 "dtc-parser.y" /* yacc.c:1646  */
+#line 466 "dtc-parser.y" /* yacc.c:1646  */
     {
                        ERROR(&(yylsp[0]), "Properties must precede subnodes");
                        YYERROR;
                }
-#line 1988 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2002 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 458 "dtc-parser.y" /* yacc.c:1646  */
+#line 474 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
                }
-#line 1996 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2010 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 462 "dtc-parser.y" /* yacc.c:1646  */
+#line 478 "dtc-parser.y" /* yacc.c:1646  */
     {
                        (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
                }
-#line 2004 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2018 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 466 "dtc-parser.y" /* yacc.c:1646  */
+#line 482 "dtc-parser.y" /* yacc.c:1646  */
     {
                        add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
                        (yyval.node) = (yyvsp[0].node);
                }
-#line 2013 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2027 "dtc-parser.tab.c" /* yacc.c:1646  */
     break;
 
 
-#line 2017 "dtc-parser.tab.c" /* yacc.c:1646  */
+#line 2031 "dtc-parser.tab.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2248,7 +2262,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 472 "dtc-parser.y" /* yacc.c:1906  */
+#line 488 "dtc-parser.y" /* yacc.c:1906  */
 
 
 void yyerror(char const *s)
index 5a897e3..000873f 100644 (file)
@@ -410,8 +410,24 @@ integer_add:
 
 integer_mul:
          integer_mul '*' integer_unary { $$ = $1 * $3; }
-       | integer_mul '/' integer_unary { $$ = $1 / $3; }
-       | integer_mul '%' integer_unary { $$ = $1 % $3; }
+       | integer_mul '/' integer_unary
+               {
+                       if ($3 != 0) {
+                               $$ = $1 / $3;
+                       } else {
+                               ERROR(&@$, "Division by zero");
+                               $$ = 0;
+                       }
+               }
+       | integer_mul '%' integer_unary
+               {
+                       if ($3 != 0) {
+                               $$ = $1 % $3;
+                       } else {
+                               ERROR(&@$, "Division by zero");
+                               $$ = 0;
+                       }
+               }
        | integer_unary
        ;
 
index 8c4add6..5fa23c4 100644 (file)
@@ -18,6 +18,8 @@
  *                                                                   USA
  */
 
+#include <sys/stat.h>
+
 #include "dtc.h"
 #include "srcpos.h"
 
@@ -104,11 +106,56 @@ static const char * const usage_opts_help[] = {
        NULL,
 };
 
+static const char *guess_type_by_name(const char *fname, const char *fallback)
+{
+       const char *s;
+
+       s = strrchr(fname, '.');
+       if (s == NULL)
+               return fallback;
+       if (!strcasecmp(s, ".dts"))
+               return "dts";
+       if (!strcasecmp(s, ".dtb"))
+               return "dtb";
+       return fallback;
+}
+
+static const char *guess_input_format(const char *fname, const char *fallback)
+{
+       struct stat statbuf;
+       uint32_t magic;
+       FILE *f;
+
+       if (stat(fname, &statbuf) != 0)
+               return fallback;
+
+       if (S_ISDIR(statbuf.st_mode))
+               return "fs";
+
+       if (!S_ISREG(statbuf.st_mode))
+               return fallback;
+
+       f = fopen(fname, "r");
+       if (f == NULL)
+               return fallback;
+       if (fread(&magic, 4, 1, f) != 1) {
+               fclose(f);
+               return fallback;
+       }
+       fclose(f);
+
+       magic = fdt32_to_cpu(magic);
+       if (magic == FDT_MAGIC)
+               return "dtb";
+
+       return guess_type_by_name(fname, fallback);
+}
+
 int main(int argc, char *argv[])
 {
        struct boot_info *bi;
-       const char *inform = "dts";
-       const char *outform = "dts";
+       const char *inform = NULL;
+       const char *outform = NULL;
        const char *outname = "-";
        const char *depname = NULL;
        bool force = false, sort = false;
@@ -213,6 +260,17 @@ int main(int argc, char *argv[])
                fprintf(depfile, "%s:", outname);
        }
 
+       if (inform == NULL)
+               inform = guess_input_format(arg, "dts");
+       if (outform == NULL) {
+               outform = guess_type_by_name(outname, NULL);
+               if (outform == NULL) {
+                       if (streq(inform, "dts"))
+                               outform = "dtb";
+                       else
+                               outform = "dts";
+               }
+       }
        if (streq(inform, "dts"))
                bi = dt_from_source(arg);
        else if (streq(inform, "fs"))
diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff
new file mode 100755 (executable)
index 0000000..959ab26
--- /dev/null
@@ -0,0 +1,349 @@
+#! /bin/bash
+
+# Copyright (C) 2015 Frank Rowand
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+
+
+usage() {
+
+       # use spaces instead of tabs in the usage message
+       cat >&2 <<eod
+
+Usage:
+
+   `basename $0` DTx
+        decompile DTx
+
+   `basename $0` DTx_1 DTx_2
+        diff DTx_1 and DTx_2
+
+
+       -f           print full dts in diff (--unified=99999)
+       -h           synonym for --help
+       -help        synonym for --help
+      --help        print this message and exit
+       -s SRCTREE   linux kernel source tree is at path SRCTREE
+                        (default is current directory)
+       -S           linux kernel source tree is at root of current git repo
+       -u           unsorted, do not sort DTx
+
+
+Each DTx is processed by the dtc compiler to produce a sorted dts source
+file.  If DTx is a dts source file then it is pre-processed in the same
+manner as done for the compile of the dts source file in the Linux kernel
+build system ('#include' and '/include/' directives are processed).
+
+If two DTx are provided, the resulting dts source files are diffed.
+
+If DTx is a directory, it is treated as a DT subtree, such as
+  /proc/device-tree.
+
+If DTx contains the binary blob magic value in the first four bytes,
+  it is treated as a binary blob (aka .dtb or FDT).
+
+Otherwise DTx is treated as a dts source file (aka .dts).
+
+   If this script is not run from the root of the linux source tree,
+   and DTx utilizes '#include' or '/include/' then the path of the
+   linux source tree can be provided by '-s SRCTREE' or '-S' so that
+   include paths will be set properly.
+
+   The shell variable \${ARCH} must provide the architecture containing
+   the dts source file for include paths to be set properly for '#include'
+   or '/include/' to be processed.
+
+   If DTx_1 and DTx_2 are in different architectures, then this script
+   may not work since \${ARCH} is part of the include path.  Two possible
+   workarounds:
+
+      `basename $0` \\
+          <(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\
+          <(ARCH=arch_of_dtx_2 `basename $0` DTx_2)
+
+      `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
+      `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+   If DTx_1 and DTx_2 are in different directories, then this script will
+   add the path of DTx_1 and DTx_2 to the include paths.  If DTx_2 includes
+   a local file that exists in both the path of DTx_1 and DTx_2 then the
+   file in the path of DTx_1 will incorrectly be included.  Possible
+   workaround:
+
+      `basename $0` DTx_1 >tmp_dtx_1.dts
+      `basename $0` DTx_2 >tmp_dtx_2.dts
+      `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
+      rm tmp_dtx_1.dts tmp_dtx_2.dts
+
+eod
+}
+
+
+compile_to_dts() {
+
+       dtx="$1"
+
+       if [ -d "${dtx}" ] ; then
+
+               # -----  input is file tree
+
+               if ( ! ${DTC} -I fs ${dtx} ) ; then
+                       exit 3
+               fi
+
+       elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
+
+               magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
+               if [ "${magic}" = "d00dfeed" ] ; then
+
+                       # -----  input is FDT (binary blob)
+
+                       if ( ! ${DTC} -I dtb ${dtx} ) ; then
+                               exit 3
+                       fi
+
+                       return
+
+               fi
+
+               # -----  input is DTS (source)
+
+               if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
+                       | ${DTC} -I dts ) ; then
+                       return
+               fi
+
+               echo ""                                                      >&2
+               echo "Possible hints to resolve the above error:"            >&2
+               echo "  (hints might not fix the problem)"                   >&2
+
+               hint_given=0
+
+               if [ "${ARCH}" = "" ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  shell variable \$ARCH not set"               >&2
+               fi
+
+               dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
+
+               if [ "${dtx_arch}" != ""  -a "${dtx_arch}" != "${ARCH}" ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  architecture ${dtx_arch} is in file path,"   >&2
+                       echo "  but does not match shell variable \$ARCH"    >&2
+                       echo "  >>\$ARCH<< is: >>${ARCH}<<"                  >&2
+               fi
+
+               if [ ! -d ${srctree}/arch/${ARCH} ] ; then
+                       hint_given=1
+                       echo ""                                              >&2
+                       echo "  ${srctree}/arch/${ARCH}/ does not exist"     >&2
+                       echo "  Is \$ARCH='${ARCH}' correct?"                >&2
+                       echo "  Possible fix: use '-s' option"               >&2
+
+                       git_root=`git rev-parse --show-toplevel 2>/dev/null`
+                       if [ -d ${git_root}/arch/ ] ; then
+                               echo "  Possible fix: use '-S' option"       >&2
+                       fi
+               fi
+
+               if [ $hint_given = 0 ] ; then
+                       echo ""                                              >&2
+                       echo "  No hints available."                         >&2
+               fi
+
+               echo ""                                                      >&2
+
+               exit 3
+
+       else
+               echo ""                                                     >&2
+               echo "ERROR: ${dtx} does not exist or is not readable"      >&2
+               echo ""                                                     >&2
+               exit 2
+       fi
+
+}
+
+
+# -----  start of script
+
+cmd_diff=0
+diff_flags="-u"
+dtx_file_1=""
+dtx_file_2=""
+dtc_sort="-s"
+help=0
+srctree=""
+
+
+while [ $# -gt 0 ] ; do
+
+       case $1 in
+
+       -f )
+               diff_flags="--unified=999999"
+               shift
+               ;;
+
+       -h | -help | --help )
+               help=1
+               shift
+               ;;
+
+       -s )
+               srctree="$2"
+               shift 2
+               ;;
+
+       -S )
+               git_root=`git rev-parse --show-toplevel 2>/dev/null`
+               srctree="${git_root}"
+               shift
+               ;;
+
+       -u )
+               dtc_sort=""
+               shift
+               ;;
+
+       *)
+               if [ "${dtx_file_1}"  = "" ] ; then
+                       dtx_file_1="$1"
+               elif [ "${dtx_file_2}" = "" ] ; then
+                       dtx_file_2="$1"
+               else
+                       echo ""                                             >&2
+                       echo "ERROR: Unexpected parameter: $1"              >&2
+                       echo ""                                             >&2
+                       exit 2
+               fi
+               shift
+               ;;
+
+       esac
+
+done
+
+if [ "${srctree}" = "" ] ; then
+       srctree="."
+fi
+
+if [ "${dtx_file_2}" != "" ]; then
+       cmd_diff=1
+fi
+
+if (( ${help} )) ; then
+       usage
+       exit 1
+fi
+
+# this must follow check for ${help}
+if [ "${dtx_file_1}" = "" ]; then
+       echo ""                                                             >&2
+       echo "ERROR: parameter DTx required"                                >&2
+       echo ""                                                             >&2
+       exit 2
+fi
+
+
+# -----  prefer dtc from linux kernel, allow fallback to dtc in $PATH
+
+if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
+       __KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
+elif [ "${KBUILD_OUTPUT}" = "" ] ; then
+       __KBUILD_OUTPUT="."
+else
+       __KBUILD_OUTPUT="${KBUILD_OUTPUT}"
+fi
+
+DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
+
+if [ ! -x ${DTC} ] ; then
+       __DTC="dtc"
+       if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then
+               make_command='
+         make scripts'
+       else
+               make_command='
+         Enable CONFIG_DTC in the kernel configuration
+         make scripts'
+       fi
+       if ( ! which ${__DTC} >/dev/null ) ; then
+
+               # use spaces instead of tabs in the error message
+               cat >&2 <<eod
+
+ERROR: unable to find a 'dtc' program
+
+   Preferred 'dtc' (built from Linux kernel source tree) was not found or
+   is not executable.
+
+      'dtc' is: ${DTC}
+
+      If it does not exist, create it from the root of the Linux source tree:
+${make_command}
+
+      If not at the root of the Linux kernel source tree -s SRCTREE or -S
+      may need to be specified to find 'dtc'.
+
+      If 'O=\${dir}' is specified in your Linux builds, this script requires
+      'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
+      before running.
+
+      If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
+      this script from the root of the Linux kernel source tree is required.
+
+   Fallback '${__DTC}' was also not in \${PATH} or is not executable.
+
+eod
+               exit 2
+       fi
+       DTC=${__DTC}
+fi
+
+
+# -----  cpp and dtc flags same as for linux source tree build of .dtb files,
+#        plus directories of the dtx file(s)
+
+dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
+
+dtx_path_2_dtc_include=""
+if (( ${cmd_diff} )) ; then
+       dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
+fi
+
+cpp_flags="\
+       -nostdinc                                  \
+       -I${srctree}/arch/${ARCH}/boot/dts         \
+       -I${srctree}/arch/${ARCH}/boot/dts/include \
+       -I${srctree}/drivers/of/testcase-data      \
+       -undef -D__DTS__"
+
+dtc_flags="\
+       -i ${srctree}/arch/${ARCH}/boot/dts/ \
+       -i ${srctree}/kernel/dts             \
+       ${dtx_path_1_dtc_include}            \
+       ${dtx_path_2_dtc_include}"
+
+DTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -"
+
+
+# -----  do the diff or decompile
+
+if (( ${cmd_diff} )) ; then
+
+       diff ${diff_flags} \
+               <(compile_to_dts "${dtx_file_1}") \
+               <(compile_to_dts "${dtx_file_2}")
+
+else
+
+       compile_to_dts "${dtx_file_1}"
+
+fi
index 2ce6a44..22286a1 100644 (file)
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
 
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
-       const char *p;
+       unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+
+       if ((absoffset < offset)
+           || ((absoffset + len) < absoffset)
+           || (absoffset + len) > fdt_totalsize(fdt))
+               return NULL;
 
        if (fdt_version(fdt) >= 0x11)
                if (((offset + len) < offset)
                    || ((offset + len) > fdt_size_dt_struct(fdt)))
                        return NULL;
 
-       p = _fdt_offset_ptr(fdt, offset);
-
-       if (p + len < p)
-               return NULL;
-       return p;
+       return _fdt_offset_ptr(fdt, offset);
 }
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
index a65e4b5..e5b3136 100644 (file)
@@ -538,6 +538,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;
 }
 
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
+{
+       const char *list, *end;
+       int length, count = 0;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list)
+               return -length;
+
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
+
+               list += length;
+               count++;
+       }
+
+       return count;
+}
+
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string)
+{
+       int length, len, idx = 0;
+       const char *list, *end;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list)
+               return -length;
+
+       len = strlen(string) + 1;
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
+
+               if (length == len && memcmp(list, string, length) == 0)
+                       return idx;
+
+               list += length;
+               idx++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int idx,
+                              int *lenp)
+{
+       const char *list, *end;
+       int length;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list) {
+               if (lenp)
+                       *lenp = length;
+
+               return NULL;
+       }
+
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end) {
+                       if (lenp)
+                               *lenp = -FDT_ERR_BADVALUE;
+
+                       return NULL;
+               }
+
+               if (idx == 0) {
+                       if (lenp)
+                               *lenp = length - 1;
+
+                       return list;
+               }
+
+               list += length;
+               idx--;
+       }
+
+       if (lenp)
+               *lenp = -FDT_ERR_NOTFOUND;
+
+       return NULL;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
                              const char *compatible)
 {
index 70adec6..8be02b1 100644 (file)
@@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
 
        if (((p + oldlen) < p) || ((p + oldlen) > end))
                return -FDT_ERR_BADOFFSET;
+       if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+               return -FDT_ERR_BADOFFSET;
        if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
                return -FDT_ERR_NOSPACE;
        memmove(p + newlen, p + oldlen, end - p - oldlen);
index ea35ac3..59ca339 100644 (file)
        /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
         * or similar property with a bad format or value */
 
-#define FDT_ERR_MAX            14
+#define FDT_ERR_BADVALUE       15
+       /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+        * value. For example: a property expected to contain a string list
+        * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_MAX            15
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -457,8 +462,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
  * @namelen: number of characters of name to consider
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
- * Identical to fdt_get_property_namelen(), but only examine the first
- * namelen characters of name for matching the property name.
+ * Identical to fdt_get_property(), but only examine the first namelen
+ * characters of name for matching the property name.
  */
 const struct fdt_property *fdt_get_property_namelen(const void *fdt,
                                                    int nodeoffset,
@@ -868,6 +873,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_stringlist_count - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
+ */
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
+
+/**
+ * fdt_stringlist_search - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
+ */
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string);
+
+/**
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @return:
+ *   A pointer to the string at the given index in the string list or NULL on
+ *   failure. On success the length of the string will be stored in the memory
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of
+ *   the following negative error codes will be returned in the lenp parameter
+ *   (if non-NULL):
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *     -FDT_ERR_NOTFOUND if the property does not exist
+ */
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int index,
+                              int *lenp);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
index 9d65226..fb124ee 100644 (file)
@@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i)
        int     j = *i + 1;
        char    val;
 
-       assert(c);
        switch (c) {
        case 'a':
                val = '\a';
@@ -349,7 +348,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 void utilfdt_print_data(const char *data, int len)
 {
        int i;
-       const char *p = data;
        const char *s;
 
        /* no data, don't print */
@@ -376,6 +374,7 @@ void utilfdt_print_data(const char *data, int len)
                               i < (len - 1) ? " " : "");
                printf(">");
        } else {
+               const unsigned char *p = (const unsigned char *)data;
                printf(" = [");
                for (i = 0; i < len; i++)
                        printf("%02x%s", *p++, i < len - 1 ? " " : "");
index 5b8c7d5..11d93e6 100644 (file)
@@ -1 +1 @@
-#define DTC_VERSION "DTC 1.4.1-g9d3649bd"
+#define DTC_VERSION "DTC 1.4.1-gb06e55c8"
index 0c2706b..b08f77c 100644 (file)
@@ -8,7 +8,7 @@ ifeq ($(ARCH),powerpc)
 
 GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
 
-CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
+CFLAGS := -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
 
 export CFLAGS
 
@@ -22,7 +22,8 @@ SUB_DIRS = benchmarks                 \
           switch_endian        \
           syscalls             \
           tm                   \
-          vphn
+          vphn         \
+          math
 
 endif
 
diff --git a/tools/testing/selftests/powerpc/basic_asm.h b/tools/testing/selftests/powerpc/basic_asm.h
new file mode 100644 (file)
index 0000000..3349a07
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _SELFTESTS_POWERPC_BASIC_ASM_H
+#define _SELFTESTS_POWERPC_BASIC_ASM_H
+
+#include <ppc-asm.h>
+#include <asm/unistd.h>
+
+#define LOAD_REG_IMMEDIATE(reg,expr) \
+       lis     reg,(expr)@highest;     \
+       ori     reg,reg,(expr)@higher;  \
+       rldicr  reg,reg,32,31;  \
+       oris    reg,reg,(expr)@high;    \
+       ori     reg,reg,(expr)@l;
+
+/*
+ * Note: These macros assume that variables being stored on the stack are
+ * doublewords, while this is usually the case it may not always be the
+ * case for each use case.
+ */
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+#define STACK_FRAME_MIN_SIZE 32
+#define STACK_FRAME_TOC_POS  24
+#define __STACK_FRAME_PARAM(_param)  (32 + ((_param)*8))
+#define __STACK_FRAME_LOCAL(_num_params,_var_num)  ((STACK_FRAME_PARAM(_num_params)) + ((_var_num)*8))
+#else
+#define STACK_FRAME_MIN_SIZE 112
+#define STACK_FRAME_TOC_POS  40
+#define __STACK_FRAME_PARAM(i)  (48 + ((i)*8))
+
+/*
+ * Caveat: if a function passed more than 8 doublewords, the caller will have
+ * made more space... which would render the 112 incorrect.
+ */
+#define __STACK_FRAME_LOCAL(_num_params,_var_num)  (112 + ((_var_num)*8))
+#endif
+
+/* Parameter x saved to the stack */
+#define STACK_FRAME_PARAM(var)    __STACK_FRAME_PARAM(var)
+
+/* Local variable x saved to the stack after x parameters */
+#define STACK_FRAME_LOCAL(num_params,var)    __STACK_FRAME_LOCAL(num_params,var)
+#define STACK_FRAME_LR_POS   16
+#define STACK_FRAME_CR_POS   8
+
+/*
+ * It is very important to note here that _extra is the extra amount of
+ * stack space needed. This space can be accessed using STACK_FRAME_PARAM()
+ * or STACK_FRAME_LOCAL() macros.
+ *
+ * r1 and r2 are not defined in ppc-asm.h (instead they are defined as sp
+ * and toc). Kernel programmers tend to prefer rX even for r1 and r2, hence
+ * %1 and %r2. r0 is defined in ppc-asm.h and therefore %r0 gets
+ * preprocessed incorrectly, hence r0.
+ */
+#define PUSH_BASIC_STACK(_extra) \
+       mflr    r0; \
+       std     r0,STACK_FRAME_LR_POS(%r1); \
+       stdu    %r1,-(_extra + STACK_FRAME_MIN_SIZE)(%r1); \
+       mfcr    r0; \
+       stw     r0,STACK_FRAME_CR_POS(%r1); \
+       std     %r2,STACK_FRAME_TOC_POS(%r1);
+
+#define POP_BASIC_STACK(_extra) \
+       ld      %r2,STACK_FRAME_TOC_POS(%r1); \
+       lwz     r0,STACK_FRAME_CR_POS(%r1); \
+       mtcr    r0; \
+       addi    %r1,%r1,(_extra + STACK_FRAME_MIN_SIZE); \
+       ld      r0,STACK_FRAME_LR_POS(%r1); \
+       mtlr    r0;
+
+#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */
diff --git a/tools/testing/selftests/powerpc/math/.gitignore b/tools/testing/selftests/powerpc/math/.gitignore
new file mode 100644 (file)
index 0000000..4fe13a4
--- /dev/null
@@ -0,0 +1,6 @@
+fpu_syscall
+vmx_syscall
+fpu_preempt
+vmx_preempt
+fpu_signal
+vmx_signal
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
new file mode 100644 (file)
index 0000000..5b88875
--- /dev/null
@@ -0,0 +1,19 @@
+TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal
+
+all: $(TEST_PROGS)
+
+$(TEST_PROGS): ../harness.c
+$(TEST_PROGS): CFLAGS += -O2 -g -pthread -m64 -maltivec
+
+fpu_syscall: fpu_asm.S
+fpu_preempt: fpu_asm.S
+fpu_signal:  fpu_asm.S
+
+vmx_syscall: vmx_asm.S
+vmx_preempt: vmx_asm.S
+vmx_signal: vmx_asm.S
+
+include ../../lib.mk
+
+clean:
+       rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
new file mode 100644 (file)
index 0000000..f3711d8
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "../basic_asm.h"
+
+#define PUSH_FPU(pos) \
+       stfd    f14,pos(sp); \
+       stfd    f15,pos+8(sp); \
+       stfd    f16,pos+16(sp); \
+       stfd    f17,pos+24(sp); \
+       stfd    f18,pos+32(sp); \
+       stfd    f19,pos+40(sp); \
+       stfd    f20,pos+48(sp); \
+       stfd    f21,pos+56(sp); \
+       stfd    f22,pos+64(sp); \
+       stfd    f23,pos+72(sp); \
+       stfd    f24,pos+80(sp); \
+       stfd    f25,pos+88(sp); \
+       stfd    f26,pos+96(sp); \
+       stfd    f27,pos+104(sp); \
+       stfd    f28,pos+112(sp); \
+       stfd    f29,pos+120(sp); \
+       stfd    f30,pos+128(sp); \
+       stfd    f31,pos+136(sp);
+
+#define POP_FPU(pos) \
+       lfd     f14,pos(sp); \
+       lfd     f15,pos+8(sp); \
+       lfd     f16,pos+16(sp); \
+       lfd     f17,pos+24(sp); \
+       lfd     f18,pos+32(sp); \
+       lfd     f19,pos+40(sp); \
+       lfd     f20,pos+48(sp); \
+       lfd     f21,pos+56(sp); \
+       lfd     f22,pos+64(sp); \
+       lfd     f23,pos+72(sp); \
+       lfd     f24,pos+80(sp); \
+       lfd     f25,pos+88(sp); \
+       lfd     f26,pos+96(sp); \
+       lfd     f27,pos+104(sp); \
+       lfd     f28,pos+112(sp); \
+       lfd     f29,pos+120(sp); \
+       lfd     f30,pos+128(sp); \
+       lfd     f31,pos+136(sp);
+
+# Careful calling this, it will 'clobber' fpu (by design)
+# Don't call this from C
+FUNC_START(load_fpu)
+       lfd     f14,0(r3)
+       lfd     f15,8(r3)
+       lfd     f16,16(r3)
+       lfd     f17,24(r3)
+       lfd     f18,32(r3)
+       lfd     f19,40(r3)
+       lfd     f20,48(r3)
+       lfd     f21,56(r3)
+       lfd     f22,64(r3)
+       lfd     f23,72(r3)
+       lfd     f24,80(r3)
+       lfd     f25,88(r3)
+       lfd     f26,96(r3)
+       lfd     f27,104(r3)
+       lfd     f28,112(r3)
+       lfd     f29,120(r3)
+       lfd     f30,128(r3)
+       lfd     f31,136(r3)
+       blr
+FUNC_END(load_fpu)
+
+FUNC_START(check_fpu)
+       mr r4,r3
+       li      r3,1 # assume a bad result
+       lfd     f0,0(r4)
+       fcmpu   cr1,f0,f14
+       bne     cr1,1f
+       lfd     f0,8(r4)
+       fcmpu   cr1,f0,f15
+       bne     cr1,1f
+       lfd     f0,16(r4)
+       fcmpu   cr1,f0,f16
+       bne     cr1,1f
+       lfd     f0,24(r4)
+       fcmpu   cr1,f0,f17
+       bne     cr1,1f
+       lfd     f0,32(r4)
+       fcmpu   cr1,f0,f18
+       bne     cr1,1f
+       lfd     f0,40(r4)
+       fcmpu   cr1,f0,f19
+       bne     cr1,1f
+       lfd     f0,48(r4)
+       fcmpu   cr1,f0,f20
+       bne     cr1,1f
+       lfd     f0,56(r4)
+       fcmpu   cr1,f0,f21
+       bne     cr1,1f
+       lfd     f0,64(r4)
+       fcmpu   cr1,f0,f22
+       bne     cr1,1f
+       lfd     f0,72(r4)
+       fcmpu   cr1,f0,f23
+       bne     cr1,1f
+       lfd     f0,80(r4)
+       fcmpu   cr1,f0,f24
+       bne     cr1,1f
+       lfd     f0,88(r4)
+       fcmpu   cr1,f0,f25
+       bne     cr1,1f
+       lfd     f0,96(r4)
+       fcmpu   cr1,f0,f26
+       bne     cr1,1f
+       lfd     f0,104(r4)
+       fcmpu   cr1,f0,f27
+       bne     cr1,1f
+       lfd     f0,112(r4)
+       fcmpu   cr1,f0,f28
+       bne     cr1,1f
+       lfd     f0,120(r4)
+       fcmpu   cr1,f0,f29
+       bne     cr1,1f
+       lfd     f0,128(r4)
+       fcmpu   cr1,f0,f30
+       bne     cr1,1f
+       lfd     f0,136(r4)
+       fcmpu   cr1,f0,f31
+       bne     cr1,1f
+       li      r3,0 # Success!!!
+1:     blr
+
+FUNC_START(test_fpu)
+       # r3 holds pointer to where to put the result of fork
+       # r4 holds pointer to the pid
+       # f14-f31 are non volatiles
+       PUSH_BASIC_STACK(256)
+       std     r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
+       std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
+       PUSH_FPU(STACK_FRAME_LOCAL(2,0))
+
+       bl load_fpu
+       nop
+       li      r0,__NR_fork
+       sc
+
+       # pass the result of the fork to the caller
+       ld      r9,STACK_FRAME_PARAM(1)(sp)
+       std     r3,0(r9)
+
+       ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_fpu
+       nop
+
+       POP_FPU(STACK_FRAME_LOCAL(2,0))
+       POP_BASIC_STACK(256)
+       blr
+FUNC_END(test_fpu)
+
+# int preempt_fpu(double *darray, int *threads_running, int *running)
+# On starting will (atomically) decrement not_ready as a signal that the FPU
+# has been loaded with darray. Will proceed to check the validity of the FPU
+# registers while running is not zero.
+FUNC_START(preempt_fpu)
+       PUSH_BASIC_STACK(256)
+       std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
+       std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
+       std r5,STACK_FRAME_PARAM(2)(sp) # int *running
+       PUSH_FPU(STACK_FRAME_LOCAL(3,0))
+
+       bl load_fpu
+       nop
+
+       sync
+       # Atomic DEC
+       ld r3,STACK_FRAME_PARAM(1)(sp)
+1:     lwarx r4,0,r3
+       addi r4,r4,-1
+       stwcx. r4,0,r3
+       bne- 1b
+
+2:     ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_fpu
+       nop
+       cmpdi r3,0
+       bne 3f
+       ld r4,STACK_FRAME_PARAM(2)(sp)
+       ld r5,0(r4)
+       cmpwi r5,0
+       bne 2b
+
+3:     POP_FPU(STACK_FRAME_LOCAL(3,0))
+       POP_BASIC_STACK(256)
+       blr
+FUNC_END(preempt_fpu)
diff --git a/tools/testing/selftests/powerpc/math/fpu_preempt.c b/tools/testing/selftests/powerpc/math/fpu_preempt.c
new file mode 100644 (file)
index 0000000..0f85b79
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the FPU registers change across preemption.
+ * Two things should be noted here a) The check_fpu function in asm only checks
+ * the non volatile registers as it is reused from the syscall test b) There is
+ * no way to be sure preemption happened so this test just uses many threads
+ * and a long wait. As such, a successful test doesn't mean much but a failure
+ * is bad.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "utils.h"
+
+/* Time to wait for workers to get preempted (seconds) */
+#define PREEMPT_TIME 20
+/*
+ * Factor by which to multiply number of online CPUs for total number of
+ * worker threads
+ */
+#define THREAD_FACTOR 8
+
+
+__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
+                    1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
+                    2.1};
+
+int threads_starting;
+int running;
+
+extern void preempt_fpu(double *darray, int *threads_starting, int *running);
+
+void *preempt_fpu_c(void *p)
+{
+       int i;
+       srand(pthread_self());
+       for (i = 0; i < 21; i++)
+               darray[i] = rand();
+
+       /* Test failed if it ever returns */
+       preempt_fpu(darray, &threads_starting, &running);
+
+       return p;
+}
+
+int test_preempt_fpu(void)
+{
+       int i, rc, threads;
+       pthread_t *tids;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
+       tids = malloc((threads) * sizeof(pthread_t));
+       FAIL_IF(!tids);
+
+       running = true;
+       threads_starting = threads;
+       for (i = 0; i < threads; i++) {
+               rc = pthread_create(&tids[i], NULL, preempt_fpu_c, NULL);
+               FAIL_IF(rc);
+       }
+
+       setbuf(stdout, NULL);
+       /* Not really necessary but nice to wait for every thread to start */
+       printf("\tWaiting for all workers to start...");
+       while(threads_starting)
+               asm volatile("": : :"memory");
+       printf("done\n");
+
+       printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
+       sleep(PREEMPT_TIME);
+       printf("done\n");
+
+       printf("\tStopping workers...");
+       /*
+        * Working are checking this value every loop. In preempt_fpu 'cmpwi r5,0; bne 2b'.
+        * r5 will have loaded the value of running.
+        */
+       running = 0;
+       for (i = 0; i < threads; i++) {
+               void *rc_p;
+               pthread_join(tids[i], &rc_p);
+
+               /*
+                * Harness will say the fail was here, look at why preempt_fpu
+                * returned
+                */
+               if ((long) rc_p)
+                       printf("oops\n");
+               FAIL_IF((long) rc_p);
+       }
+       printf("done\n");
+
+       free(tids);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_preempt_fpu, "fpu_preempt");
+}
diff --git a/tools/testing/selftests/powerpc/math/fpu_signal.c b/tools/testing/selftests/powerpc/math/fpu_signal.c
new file mode 100644 (file)
index 0000000..888aa51
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the FPU registers are correctly reported in a
+ * signal context. Each worker just spins checking its FPU registers, at some
+ * point a signal will interrupt it and C code will check the signal context
+ * ensuring it is also the same.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "utils.h"
+
+/* Number of times each thread should receive the signal */
+#define ITERATIONS 10
+/*
+ * Factor by which to multiply number of online CPUs for total number of
+ * worker threads
+ */
+#define THREAD_FACTOR 8
+
+__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
+                    1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
+                    2.1};
+
+bool bad_context;
+int threads_starting;
+int running;
+
+extern long preempt_fpu(double *darray, int *threads_starting, int *running);
+
+void signal_fpu_sig(int sig, siginfo_t *info, void *context)
+{
+       int i;
+       ucontext_t *uc = context;
+       mcontext_t *mc = &uc->uc_mcontext;
+
+       /* Only the non volatiles were loaded up */
+       for (i = 14; i < 32; i++) {
+               if (mc->fp_regs[i] != darray[i - 14]) {
+                       bad_context = true;
+                       break;
+               }
+       }
+}
+
+void *signal_fpu_c(void *p)
+{
+       int i;
+       long rc;
+       struct sigaction act;
+       act.sa_sigaction = signal_fpu_sig;
+       act.sa_flags = SA_SIGINFO;
+       rc = sigaction(SIGUSR1, &act, NULL);
+       if (rc)
+               return p;
+
+       srand(pthread_self());
+       for (i = 0; i < 21; i++)
+               darray[i] = rand();
+
+       rc = preempt_fpu(darray, &threads_starting, &running);
+
+       return (void *) rc;
+}
+
+int test_signal_fpu(void)
+{
+       int i, j, rc, threads;
+       void *rc_p;
+       pthread_t *tids;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
+       tids = malloc(threads * sizeof(pthread_t));
+       FAIL_IF(!tids);
+
+       running = true;
+       threads_starting = threads;
+       for (i = 0; i < threads; i++) {
+               rc = pthread_create(&tids[i], NULL, signal_fpu_c, NULL);
+               FAIL_IF(rc);
+       }
+
+       setbuf(stdout, NULL);
+       printf("\tWaiting for all workers to start...");
+       while (threads_starting)
+               asm volatile("": : :"memory");
+       printf("done\n");
+
+       printf("\tSending signals to all threads %d times...", ITERATIONS);
+       for (i = 0; i < ITERATIONS; i++) {
+               for (j = 0; j < threads; j++) {
+                       pthread_kill(tids[j], SIGUSR1);
+               }
+               sleep(1);
+       }
+       printf("done\n");
+
+       printf("\tStopping workers...");
+       running = 0;
+       for (i = 0; i < threads; i++) {
+               pthread_join(tids[i], &rc_p);
+
+               /*
+                * Harness will say the fail was here, look at why signal_fpu
+                * returned
+                */
+               if ((long) rc_p || bad_context)
+                       printf("oops\n");
+               if (bad_context)
+                       fprintf(stderr, "\t!! bad_context is true\n");
+               FAIL_IF((long) rc_p || bad_context);
+       }
+       printf("done\n");
+
+       free(tids);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_signal_fpu, "fpu_signal");
+}
diff --git a/tools/testing/selftests/powerpc/math/fpu_syscall.c b/tools/testing/selftests/powerpc/math/fpu_syscall.c
new file mode 100644 (file)
index 0000000..949e672
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the FPU registers change across a syscall (fork).
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+extern int test_fpu(double *darray, pid_t *pid);
+
+double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
+                    1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
+                    2.1};
+
+int syscall_fpu(void)
+{
+       pid_t fork_pid;
+       int i;
+       int ret;
+       int child_ret;
+       for (i = 0; i < 1000; i++) {
+               /* test_fpu will fork() */
+               ret = test_fpu(darray, &fork_pid);
+               if (fork_pid == -1)
+                       return -1;
+               if (fork_pid == 0)
+                       exit(ret);
+               waitpid(fork_pid, &child_ret, 0);
+               if (ret || child_ret)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int test_syscall_fpu(void)
+{
+       /*
+        * Setup an environment with much context switching
+        */
+       pid_t pid2;
+       pid_t pid = fork();
+       int ret;
+       int child_ret;
+       FAIL_IF(pid == -1);
+
+       pid2 = fork();
+       /* Can't FAIL_IF(pid2 == -1); because already forked once */
+       if (pid2 == -1) {
+               /*
+                * Couldn't fork, ensure test is a fail
+                */
+               child_ret = ret = 1;
+       } else {
+               ret = syscall_fpu();
+               if (pid2)
+                       waitpid(pid2, &child_ret, 0);
+               else
+                       exit(ret);
+       }
+
+       ret |= child_ret;
+
+       if (pid)
+               waitpid(pid, &child_ret, 0);
+       else
+               exit(ret);
+
+       FAIL_IF(ret || child_ret);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_syscall_fpu, "syscall_fpu");
+
+}
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
new file mode 100644 (file)
index 0000000..1b8c248
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "../basic_asm.h"
+
+# POS MUST BE 16 ALIGNED!
+#define PUSH_VMX(pos,reg) \
+       li      reg,pos; \
+       stvx    v20,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v21,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v22,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v23,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v24,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v25,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v26,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v27,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v28,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v29,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v30,reg,sp; \
+       addi    reg,reg,16; \
+       stvx    v31,reg,sp;
+
+# POS MUST BE 16 ALIGNED!
+#define POP_VMX(pos,reg) \
+       li      reg,pos; \
+       lvx     v20,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v21,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v22,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v23,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v24,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v25,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v26,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v27,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v28,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v29,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v30,reg,sp; \
+       addi    reg,reg,16; \
+       lvx     v31,reg,sp;
+
+# Carefull this will 'clobber' vmx (by design)
+# Don't call this from C
+FUNC_START(load_vmx)
+       li      r5,0
+       lvx     v20,r5,r3
+       addi    r5,r5,16
+       lvx     v21,r5,r3
+       addi    r5,r5,16
+       lvx     v22,r5,r3
+       addi    r5,r5,16
+       lvx     v23,r5,r3
+       addi    r5,r5,16
+       lvx     v24,r5,r3
+       addi    r5,r5,16
+       lvx     v25,r5,r3
+       addi    r5,r5,16
+       lvx     v26,r5,r3
+       addi    r5,r5,16
+       lvx     v27,r5,r3
+       addi    r5,r5,16
+       lvx     v28,r5,r3
+       addi    r5,r5,16
+       lvx     v29,r5,r3
+       addi    r5,r5,16
+       lvx     v30,r5,r3
+       addi    r5,r5,16
+       lvx     v31,r5,r3
+       blr
+FUNC_END(load_vmx)
+
+# Should be safe from C, only touches r4, r5 and v0,v1,v2
+FUNC_START(check_vmx)
+       PUSH_BASIC_STACK(32)
+       mr r4,r3
+       li      r3,1 # assume a bad result
+       li      r5,0
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v20
+       vmr     v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v21
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v22
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v23
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v24
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v25
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v26
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v27
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v28
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v29
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v30
+       vand    v2,v2,v1
+
+       addi    r5,r5,16
+       lvx     v0,r5,r4
+       vcmpequd.       v1,v0,v31
+       vand    v2,v2,v1
+
+       li      r5,STACK_FRAME_LOCAL(0,0)
+       stvx    v2,r5,sp
+       ldx     r0,r5,sp
+       cmpdi   r0,0xffffffffffffffff
+       bne     1f
+       li      r3,0
+1:     POP_BASIC_STACK(32)
+       blr
+FUNC_END(check_vmx)
+
+# Safe from C
+FUNC_START(test_vmx)
+       # r3 holds pointer to where to put the result of fork
+       # r4 holds pointer to the pid
+       # v20-v31 are non-volatile
+       PUSH_BASIC_STACK(512)
+       std     r3,STACK_FRAME_PARAM(0)(sp) # Address of varray
+       std r4,STACK_FRAME_PARAM(1)(sp) # address of pid
+       PUSH_VMX(STACK_FRAME_LOCAL(2,0),r4)
+
+       bl load_vmx
+       nop
+
+       li      r0,__NR_fork
+       sc
+       # Pass the result of fork back to the caller
+       ld      r9,STACK_FRAME_PARAM(1)(sp)
+       std     r3,0(r9)
+
+       ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_vmx
+       nop
+
+       POP_VMX(STACK_FRAME_LOCAL(2,0),r4)
+       POP_BASIC_STACK(512)
+       blr
+FUNC_END(test_vmx)
+
+# int preempt_vmx(vector int *varray, int *threads_starting, int *running)
+# On starting will (atomically) decrement threads_starting as a signal that
+# the VMX have been loaded with varray. Will proceed to check the validity of
+# the VMX registers while running is not zero.
+FUNC_START(preempt_vmx)
+       PUSH_BASIC_STACK(512)
+       std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
+       std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
+       std r5,STACK_FRAME_PARAM(2)(sp) # int *running
+       # VMX need to write to 16 byte aligned addresses, skip STACK_FRAME_LOCAL(3,0)
+       PUSH_VMX(STACK_FRAME_LOCAL(4,0),r4)
+
+       bl load_vmx
+       nop
+
+       sync
+       # Atomic DEC
+       ld r3,STACK_FRAME_PARAM(1)(sp)
+1:     lwarx r4,0,r3
+       addi r4,r4,-1
+       stwcx. r4,0,r3
+       bne- 1b
+
+2:     ld r3,STACK_FRAME_PARAM(0)(sp)
+       bl check_vmx
+       nop
+       cmpdi r3,0
+       bne 3f
+       ld r4,STACK_FRAME_PARAM(2)(sp)
+       ld r5,0(r4)
+       cmpwi r5,0
+       bne 2b
+
+3:     POP_VMX(STACK_FRAME_LOCAL(4,0),r4)
+       POP_BASIC_STACK(512)
+       blr
+FUNC_END(preempt_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vmx_preempt.c b/tools/testing/selftests/powerpc/math/vmx_preempt.c
new file mode 100644 (file)
index 0000000..9ef376c
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the VMX registers change across preemption.
+ * Two things should be noted here a) The check_vmx function in asm only checks
+ * the non volatile registers as it is reused from the syscall test b) There is
+ * no way to be sure preemption happened so this test just uses many threads
+ * and a long wait. As such, a successful test doesn't mean much but a failure
+ * is bad.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "utils.h"
+
+/* Time to wait for workers to get preempted (seconds) */
+#define PREEMPT_TIME 20
+/*
+ * Factor by which to multiply number of online CPUs for total number of
+ * worker threads
+ */
+#define THREAD_FACTOR 8
+
+__thread vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
+       {13,14,15,16},{17,18,19,20},{21,22,23,24},
+       {25,26,27,28},{29,30,31,32},{33,34,35,36},
+       {37,38,39,40},{41,42,43,44},{45,46,47,48}};
+
+int threads_starting;
+int running;
+
+extern void preempt_vmx(vector int *varray, int *threads_starting, int *running);
+
+void *preempt_vmx_c(void *p)
+{
+       int i, j;
+       srand(pthread_self());
+       for (i = 0; i < 12; i++)
+               for (j = 0; j < 4; j++)
+                       varray[i][j] = rand();
+
+       /* Test fails if it ever returns */
+       preempt_vmx(varray, &threads_starting, &running);
+       return p;
+}
+
+int test_preempt_vmx(void)
+{
+       int i, rc, threads;
+       pthread_t *tids;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
+       tids = malloc(threads * sizeof(pthread_t));
+       FAIL_IF(!tids);
+
+       running = true;
+       threads_starting = threads;
+       for (i = 0; i < threads; i++) {
+               rc = pthread_create(&tids[i], NULL, preempt_vmx_c, NULL);
+               FAIL_IF(rc);
+       }
+
+       setbuf(stdout, NULL);
+       /* Not really nessesary but nice to wait for every thread to start */
+       printf("\tWaiting for all workers to start...");
+       while(threads_starting)
+               asm volatile("": : :"memory");
+       printf("done\n");
+
+       printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
+       sleep(PREEMPT_TIME);
+       printf("done\n");
+
+       printf("\tStopping workers...");
+       /*
+        * Working are checking this value every loop. In preempt_vmx 'cmpwi r5,0; bne 2b'.
+        * r5 will have loaded the value of running.
+        */
+       running = 0;
+       for (i = 0; i < threads; i++) {
+               void *rc_p;
+               pthread_join(tids[i], &rc_p);
+
+               /*
+                * Harness will say the fail was here, look at why preempt_vmx
+                * returned
+                */
+               if ((long) rc_p)
+                       printf("oops\n");
+               FAIL_IF((long) rc_p);
+       }
+       printf("done\n");
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_preempt_vmx, "vmx_preempt");
+}
diff --git a/tools/testing/selftests/powerpc/math/vmx_signal.c b/tools/testing/selftests/powerpc/math/vmx_signal.c
new file mode 100644 (file)
index 0000000..671d753
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the VMX registers are correctly reported in a
+ * signal context. Each worker just spins checking its VMX registers, at some
+ * point a signal will interrupt it and C code will check the signal context
+ * ensuring it is also the same.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <altivec.h>
+
+#include "utils.h"
+
+/* Number of times each thread should receive the signal */
+#define ITERATIONS 10
+/*
+ * Factor by which to multiply number of online CPUs for total number of
+ * worker threads
+ */
+#define THREAD_FACTOR 8
+
+__thread vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
+       {13,14,15,16},{17,18,19,20},{21,22,23,24},
+       {25,26,27,28},{29,30,31,32},{33,34,35,36},
+       {37,38,39,40},{41,42,43,44},{45,46,47,48}};
+
+bool bad_context;
+int running;
+int threads_starting;
+
+extern int preempt_vmx(vector int *varray, int *threads_starting, int *sentinal);
+
+void signal_vmx_sig(int sig, siginfo_t *info, void *context)
+{
+       int i;
+       ucontext_t *uc = context;
+       mcontext_t *mc = &uc->uc_mcontext;
+
+       /* Only the non volatiles were loaded up */
+       for (i = 20; i < 32; i++) {
+               if (memcmp(mc->v_regs->vrregs[i], &varray[i - 20], 16)) {
+                       int j;
+                       /*
+                        * Shouldn't printf() in a signal handler, however, this is a
+                        * test and we've detected failure. Understanding what failed
+                        * is paramount. All that happens after this is tests exit with
+                        * failure.
+                        */
+                       printf("VMX mismatch at reg %d!\n", i);
+                       printf("Reg | Actual                  | Expected\n");
+                       for (j = 20; j < 32; j++) {
+                               printf("%d  | 0x%04x%04x%04x%04x      | 0x%04x%04x%04x%04x\n", j, mc->v_regs->vrregs[j][0],
+                                          mc->v_regs->vrregs[j][1], mc->v_regs->vrregs[j][2], mc->v_regs->vrregs[j][3],
+                                          varray[j - 20][0], varray[j - 20][1], varray[j - 20][2], varray[j - 20][3]);
+                       }
+                       bad_context = true;
+                       break;
+               }
+       }
+}
+
+void *signal_vmx_c(void *p)
+{
+       int i, j;
+       long rc;
+       struct sigaction act;
+       act.sa_sigaction = signal_vmx_sig;
+       act.sa_flags = SA_SIGINFO;
+       rc = sigaction(SIGUSR1, &act, NULL);
+       if (rc)
+               return p;
+
+       srand(pthread_self());
+       for (i = 0; i < 12; i++)
+               for (j = 0; j < 4; j++)
+                       varray[i][j] = rand();
+
+       rc = preempt_vmx(varray, &threads_starting, &running);
+
+       return (void *) rc;
+}
+
+int test_signal_vmx(void)
+{
+       int i, j, rc, threads;
+       void *rc_p;
+       pthread_t *tids;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
+       tids = malloc(threads * sizeof(pthread_t));
+       FAIL_IF(!tids);
+
+       running = true;
+       threads_starting = threads;
+       for (i = 0; i < threads; i++) {
+               rc = pthread_create(&tids[i], NULL, signal_vmx_c, NULL);
+               FAIL_IF(rc);
+       }
+
+       setbuf(stdout, NULL);
+       printf("\tWaiting for %d workers to start... %d", threads, threads_starting);
+       while (threads_starting) {
+               asm volatile("": : :"memory");
+               usleep(1000);
+               printf(", %d", threads_starting);
+       }
+       printf(" ...done\n");
+
+       printf("\tSending signals to all threads %d times...", ITERATIONS);
+       for (i = 0; i < ITERATIONS; i++) {
+               for (j = 0; j < threads; j++) {
+                       pthread_kill(tids[j], SIGUSR1);
+               }
+               sleep(1);
+       }
+       printf("done\n");
+
+       printf("\tKilling workers...");
+       running = 0;
+       for (i = 0; i < threads; i++) {
+               pthread_join(tids[i], &rc_p);
+
+               /*
+                * Harness will say the fail was here, look at why signal_vmx
+                * returned
+                */
+               if ((long) rc_p || bad_context)
+                       printf("oops\n");
+               if (bad_context)
+                       fprintf(stderr, "\t!! bad_context is true\n");
+               FAIL_IF((long) rc_p || bad_context);
+       }
+       printf("done\n");
+
+       free(tids);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_signal_vmx, "vmx_signal");
+}
diff --git a/tools/testing/selftests/powerpc/math/vmx_syscall.c b/tools/testing/selftests/powerpc/math/vmx_syscall.c
new file mode 100644 (file)
index 0000000..a017918
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test attempts to see if the VMX registers change across a syscall (fork).
+ */
+
+#include <altivec.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "utils.h"
+
+vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
+       {13,14,15,16},{17,18,19,20},{21,22,23,24},
+       {25,26,27,28},{29,30,31,32},{33,34,35,36},
+       {37,38,39,40},{41,42,43,44},{45,46,47,48}};
+
+extern int test_vmx(vector int *varray, pid_t *pid);
+
+int vmx_syscall(void)
+{
+       pid_t fork_pid;
+       int i;
+       int ret;
+       int child_ret;
+       for (i = 0; i < 1000; i++) {
+               /* test_vmx will fork() */
+               ret = test_vmx(varray, &fork_pid);
+               if (fork_pid == -1)
+                       return -1;
+               if (fork_pid == 0)
+                       exit(ret);
+               waitpid(fork_pid, &child_ret, 0);
+               if (ret || child_ret)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int test_vmx_syscall(void)
+{
+       /*
+        * Setup an environment with much context switching
+        */
+       pid_t pid2;
+       pid_t pid = fork();
+       int ret;
+       int child_ret;
+       FAIL_IF(pid == -1);
+
+       pid2 = fork();
+       ret = vmx_syscall();
+       /* Can't FAIL_IF(pid2 == -1); because we've already forked */
+       if (pid2 == -1) {
+               /*
+                * Couldn't fork, ensure child_ret is set and is a fail
+                */
+               ret = child_ret = 1;
+       } else {
+               if (pid2)
+                       waitpid(pid2, &child_ret, 0);
+               else
+                       exit(ret);
+       }
+
+       ret |= child_ret;
+
+       if (pid)
+               waitpid(pid, &child_ret, 0);
+       else
+               exit(ret);
+
+       FAIL_IF(ret || child_ret);
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       return test_harness(test_vmx_syscall, "vmx_syscall");
+
+}
index d86653f..8c54d18 100644 (file)
@@ -40,7 +40,7 @@ void signal_usr1(int signum, siginfo_t *info, void *uc)
 #ifdef __powerpc64__
        ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32);
 #else
-       ucp->uc_mcontext.regs->gpr[PT_MSR] |= (7ULL);
+       ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL);
 #endif
        /* Should segv on return becuase of invalid context */
        segv_expected = 1;