]> Pileus Git - ~andy/linux/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 02:08:37 +0000 (18:08 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 30 Jan 2014 02:08:37 +0000 (18:08 -0800)
Pull networking fixes from David Miller:
 "Several fixups, of note:

  1) Fix unlock of not held spinlock in RXRPC code, from Alexey
     Khoroshilov.

  2) Call pci_disable_device() from the correct shutdown path in bnx2x
     driver, from Yuval Mintz.

  3) Fix qeth build on s390 for some configurations, from Eugene
     Crosser.

  4) Cure locking bugs in bond_loadbalance_arp_mon(), from Ding
     Tianhong.

  5) Must do netif_napi_add() before registering netdevice in sky2
     driver, from Stanislaw Gruszka.

  6) Fix lost bug fix during merge due to code movement in ieee802154,
     noticed and fixed by the eagle eyed Stephen Rothwell.

  7) Get rid of resource leak in xen-netfront driver, from Annie Li.

  8) Bounds checks in qlcnic driver are off by one, from Manish Chopra.

  9) TPROXY can leak sockets when TCP early demux is enabled, fix from
     Holger Eitzenberger"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (32 commits)
  qeth: fix build of s390 allmodconfig
  bonding: fix locking in bond_loadbalance_arp_mon()
  tun: add device name(iff) field to proc fdinfo entry
  DT: net: davinci_emac: "ti, davinci-no-bd-ram" property is actually optional
  DT: net: davinci_emac: "ti, davinci-rmii-en" property is actually optional
  bnx2x: Fix generic option settings
  net: Fix warning on make htmldocs caused by skbuff.c
  llc: remove noisy WARN from llc_mac_hdr_init
  qlcnic: Fix loopback test failure
  qlcnic: Fix tx timeout.
  qlcnic: Fix initialization of vlan list.
  qlcnic: Correct off-by-one errors in bounds checks
  net: Document promote_secondaries
  net: gre: use icmp_hdr() to get inner ip header
  i40e: Add missing braces to i40e_dcb_need_reconfig()
  xen-netfront: fix resource leak in netfront
  net: 6lowpan: fixup for code movement
  hyperv: Add support for physically discontinuous receive buffer
  sky2: initialize napi before registering device
  net: Fix memory leak if TPROXY used with TCP early demux
  ...

816 files changed:
Documentation/ABI/testing/configfs-usb-gadget
Documentation/ABI/testing/configfs-usb-gadget-acm
Documentation/ABI/testing/configfs-usb-gadget-ecm
Documentation/ABI/testing/configfs-usb-gadget-eem
Documentation/ABI/testing/configfs-usb-gadget-ffs
Documentation/ABI/testing/configfs-usb-gadget-loopback
Documentation/ABI/testing/configfs-usb-gadget-mass-storage
Documentation/ABI/testing/configfs-usb-gadget-ncm
Documentation/ABI/testing/configfs-usb-gadget-obex
Documentation/ABI/testing/configfs-usb-gadget-phonet
Documentation/ABI/testing/configfs-usb-gadget-rndis
Documentation/ABI/testing/configfs-usb-gadget-serial
Documentation/ABI/testing/configfs-usb-gadget-sourcesink
Documentation/ABI/testing/configfs-usb-gadget-subset
Documentation/ABI/testing/sysfs-bus-rbd
Documentation/debugging-via-ohci1394.txt
Documentation/devicetree/bindings/arm/davinci/nand.txt [deleted file]
Documentation/devicetree/bindings/clock/ti/apll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/autoidle.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/clockdomain.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/composite.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/divider.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/dpll.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/gate.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/interface.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/mux.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/tca6507.txt
Documentation/devicetree/bindings/mtd/davinci-nand.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmi-nand.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
Documentation/devicetree/bindings/pwm/atmel-pwm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/pxa-pwm.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/ssd1289fb.txt [new file with mode: 0644]
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/kmsg/s390/zcrypt [deleted file]
Documentation/leds/leds-lp55xx.txt
Documentation/mtd/nand/pxa3xx-nand.txt [new file with mode: 0644]
Documentation/power/basic-pm-debugging.txt
Documentation/sysctl/vm.txt
MAINTAINERS
arch/arm/boot/dts/am33xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am35xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am43xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra7xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap3430es1-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap34xx.dtsi
arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx.dtsi
arch/arm/boot/dts/omap3xxx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap443x-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap443x.dtsi
arch/arm/boot/dts/omap4460.dtsi
arch/arm/boot/dts/omap446x-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap44xx-clocks.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/omap54xx-clocks.dtsi [new file with mode: 0644]
arch/arm/kernel/setup.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/cclock33xx_data.c [deleted file]
arch/arm/mach-omap2/cclock44xx_data.c [deleted file]
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clkt_iclk.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock36xx.c
arch/arm/mach-omap2/clock3xxx.h
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll44xx.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/timer.c
arch/arm/plat-samsung/include/plat/regs-nand.h [deleted file]
arch/blackfin/kernel/setup.c
arch/cris/Kconfig
arch/cris/arch-v10/drivers/gpio.c
arch/cris/arch-v10/drivers/sync_serial.c
arch/cris/arch-v10/kernel/Makefile
arch/cris/arch-v10/kernel/debugport.c
arch/cris/arch-v10/kernel/entry.S
arch/cris/arch-v10/kernel/head.S
arch/cris/arch-v10/kernel/irq.c
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v10/kernel/time.c
arch/cris/arch-v10/lib/dram_init.S
arch/cris/arch-v32/drivers/axisflashmap.c
arch/cris/arch-v32/drivers/mach-a3/gpio.c
arch/cris/arch-v32/drivers/mach-fs/gpio.c
arch/cris/arch-v32/drivers/sync_serial.c
arch/cris/arch-v32/kernel/entry.S
arch/cris/arch-v32/kernel/fasttimer.c
arch/cris/arch-v32/kernel/irq.c
arch/cris/arch-v32/kernel/smp.c
arch/cris/arch-v32/kernel/time.c
arch/cris/arch-v32/mach-a3/arbiter.c
arch/cris/arch-v32/mach-fs/arbiter.c
arch/cris/boot/rescue/kimagerescue.S
arch/cris/include/arch-v10/arch/io.h
arch/cris/include/arch-v10/arch/irq.h
arch/cris/include/arch-v32/arch/irq.h
arch/cris/include/asm/unistd.h
arch/cris/include/uapi/asm/unistd.h
arch/cris/kernel/irq.c
arch/microblaze/Kconfig
arch/microblaze/Makefile
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/sections.h
arch/microblaze/include/uapi/asm/Kbuild
arch/microblaze/include/uapi/asm/types.h [deleted file]
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/head.S
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/vmlinux.lds.S
arch/powerpc/Kconfig
arch/powerpc/boot/.gitignore
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/fsl/elo3-dma-2.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/p1020si-post.dtsi
arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
arch/powerpc/boot/dts/fsl/p1022si-post.dtsi
arch/powerpc/boot/dts/fsl/p1023si-post.dtsi
arch/powerpc/boot/dts/kilauea.dts
arch/powerpc/boot/dts/mvme5100.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb-pa.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb-pa.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb-pa_36b.dts [moved from arch/powerpc/boot/dts/p1010rdb_36b.dts with 64% similarity]
arch/powerpc/boot/dts/p1010rdb-pb.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb-pb_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb.dts [deleted file]
arch/powerpc/boot/dts/p1010rdb.dtsi
arch/powerpc/boot/dts/p1010rdb_32b.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1010rdb_36b.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1022ds.dtsi
arch/powerpc/boot/dts/p1025twr.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1025twr.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/virtex440-ml507.dts
arch/powerpc/boot/mvme5100.c [new file with mode: 0644]
arch/powerpc/boot/wrapper
arch/powerpc/configs/85xx/p1023_defconfig [deleted file]
arch/powerpc/configs/adder875_defconfig
arch/powerpc/configs/ep88xc_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/mpc866_ads_defconfig
arch/powerpc/configs/mpc885_ads_defconfig
arch/powerpc/configs/mvme5100_defconfig [new file with mode: 0644]
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/tqm8xx_defconfig
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/cmpxchg.h
arch/powerpc/include/asm/code-patching.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/fsl_lbc.h
arch/powerpc/include/asm/hardirq.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/kvm_asm.h
arch/powerpc/include/asm/lppaca.h
arch/powerpc/include/asm/mce.h [new file with mode: 0644]
arch/powerpc/include/asm/mmu-book3e.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/ps3.h
arch/powerpc/include/asm/pte-hash64.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/spinlock.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/tm.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/vio.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cacheinfo.c
arch/powerpc/kernel/cpu_setup_fsl_booke.S
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fpu.S
arch/powerpc/kernel/fsl_booke_entry_mapping.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/iomap.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/mce.c [new file with mode: 0644]
arch/powerpc/kernel/mce_power.c [new file with mode: 0644]
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/smp-tbsync.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/swsusp_booke.S
arch/powerpc/kernel/syscalls.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vdso32/vdso32_wrapper.S
arch/powerpc/kernel/vdso64/vdso64_wrapper.S
arch/powerpc/kernel/vector.S
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/book3s_hv_ras.c
arch/powerpc/kvm/bookehv_interrupts.S
arch/powerpc/lib/code-patching.c
arch/powerpc/lib/crtsavres.S
arch/powerpc/math-emu/math_efp.c
arch/powerpc/mm/fsl_booke_mmu.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugepage-hash64.c
arch/powerpc/mm/hugetlbpage-book3e.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/tlb_hash64.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_7450.c
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/oprofile/op_model_fsl_emb.c
arch/powerpc/oprofile/op_model_pa6t.c
arch/powerpc/oprofile/op_model_power4.c
arch/powerpc/oprofile/op_model_rs64.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
arch/powerpc/platforms/83xx/suspend.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/common.c
arch/powerpc/platforms/85xx/mpc85xx.h
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/sgy_cts1000.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/85xx/twr_p102x.c [new file with mode: 0644]
arch/powerpc/platforms/8xx/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/embedded6xx/Kconfig
arch/powerpc/platforms/embedded6xx/Makefile
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
arch/powerpc/platforms/embedded6xx/mvme5100.c [new file with mode: 0644]
arch/powerpc/platforms/pasemi/dma_lib.c
arch/powerpc/platforms/pasemi/iommu.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/powernv/Kconfig
arch/powerpc/platforms/powernv/Makefile
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal-flash.c
arch/powerpc/platforms/powernv/opal-memory-errors.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-rtc.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci-p5ioc2.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/ps3/spu.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/cmm.c
arch/powerpc/platforms/pseries/dtl.c
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/platforms/wsp/wsp_pci.c
arch/powerpc/sysdev/Kconfig
arch/powerpc/sysdev/cpm2_pic.c
arch/powerpc/sysdev/fsl_ifc.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/ge/ge_pic.h
arch/powerpc/sysdev/i8259.c
arch/powerpc/sysdev/indirect_pci.c
arch/powerpc/sysdev/mpc8xx_pic.c
arch/powerpc/sysdev/mpic_timer.c
arch/powerpc/sysdev/qe_lib/qe_io.c
arch/powerpc/sysdev/qe_lib/ucc.c
arch/powerpc/sysdev/qe_lib/ucc_fast.c
arch/powerpc/sysdev/qe_lib/ucc_slow.c
arch/powerpc/sysdev/udbg_memcons.c
arch/powerpc/sysdev/xics/icp-hv.c
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/hypfs/Makefile
arch/s390/hypfs/hypfs.h
arch/s390/hypfs/hypfs_dbfs.c
arch/s390/hypfs/hypfs_sprp.c [new file with mode: 0644]
arch/s390/hypfs/inode.c
arch/s390/include/asm/cmpxchg.h
arch/s390/include/asm/sclp.h
arch/s390/include/uapi/asm/hypfs.h [new file with mode: 0644]
arch/s390/include/uapi/asm/statfs.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/syscalls.S
arch/s390/lib/uaccess.h
arch/s390/lib/uaccess_pt.c
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/cpumap.c
arch/sparc/kernel/ebus.c
arch/sparc/kernel/hvtramp.S
arch/sparc/kernel/of_device_common.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/pci_common.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/sparc_ksyms_32.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/trampoline_32.S
arch/sparc/kernel/trampoline_64.S
arch/sparc/mm/hugetlbpage.c
arch/sparc/mm/tlb.c
arch/sparc/prom/p1275.c
arch/unicore32/kernel/early_printk.c
arch/x86/include/asm/page_types.h
arch/x86/kernel/setup.c
drivers/block/rbd.c
drivers/clk/Makefile
drivers/clk/clk-si5351.c
drivers/clk/clk-si5351.h
drivers/clk/clk.c
drivers/clk/qcom/Makefile
drivers/clk/samsung/clk-pll.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/ti/Makefile [new file with mode: 0644]
drivers/clk/ti/apll.c [new file with mode: 0644]
drivers/clk/ti/autoidle.c [new file with mode: 0644]
drivers/clk/ti/clk-33xx.c [new file with mode: 0644]
drivers/clk/ti/clk-3xxx.c [new file with mode: 0644]
drivers/clk/ti/clk-43xx.c [new file with mode: 0644]
drivers/clk/ti/clk-44xx.c [new file with mode: 0644]
drivers/clk/ti/clk-54xx.c [new file with mode: 0644]
drivers/clk/ti/clk-7xx.c [new file with mode: 0644]
drivers/clk/ti/clk.c [new file with mode: 0644]
drivers/clk/ti/clockdomain.c [new file with mode: 0644]
drivers/clk/ti/composite.c [new file with mode: 0644]
drivers/clk/ti/divider.c [new file with mode: 0644]
drivers/clk/ti/dpll.c [new file with mode: 0644]
drivers/clk/ti/fixed-factor.c [new file with mode: 0644]
drivers/clk/ti/gate.c [new file with mode: 0644]
drivers/clk/ti/interface.c [new file with mode: 0644]
drivers/clk/ti/mux.c [new file with mode: 0644]
drivers/firewire/core-transaction.c
drivers/firewire/core.h
drivers/firewire/ohci.c
drivers/firmware/google/Kconfig
drivers/ide/ide-cd_verbose.c
drivers/ide/ide-pio-blacklist.c
drivers/leds/led-triggers.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp55xx-common.c
drivers/leds/leds-mc13783.c
drivers/leds/leds-pwm.c
drivers/leds/leds-s3c24xx.c
drivers/leds/leds-tca6507.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/mtd/Kconfig
drivers/mtd/afs.c
drivers/mtd/ar7part.c
drivers/mtd/bcm47xxpart.c
drivers/mtd/bcm63xxpart.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/devices/mtdram.c
drivers/mtd/lpddr/lpddr_cmds.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/lantiq-flash.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/maps/sun_uflash.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/cafe_nand.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c
drivers/mtd/nand/denali_pci.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.h
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/lpc32xx_mlc.c
drivers/mtd/nand/lpc32xx_slc.c
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nuc900_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/pasemi_nand.c
drivers/mtd/nand/plat_nand.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/tmio_nand.c
drivers/mtd/nand/txx9ndfmc.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/generic.c
drivers/mtd/redboot.c
drivers/mtd/tests/mtd_nandecctest.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/core.c
drivers/pwm/pwm-atmel.c [new file with mode: 0644]
drivers/pwm/pwm-ep93xx.c
drivers/pwm/pwm-jz4740.c
drivers/pwm/pwm-pxa.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/sysfs.c
drivers/s390/block/xpram.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/vmur.c
drivers/sbus/char/bbc_i2c.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/envctrl.c
drivers/sbus/char/flash.c
drivers/sbus/char/uctrl.c
drivers/tty/Kconfig
drivers/tty/hvc/hvc_iucv.c
drivers/tty/serial/icom.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/samsung.c
drivers/vfio/vfio_iommu_spapr_tce.c
drivers/video/backlight/pwm_bl.c
fs/9p/acl.c
fs/Kconfig
fs/Makefile
fs/affs/super.c
fs/afs/internal.h
fs/afs/proc.c
fs/befs/linuxvfs.c
fs/btrfs/acl.c
fs/btrfs/ctree.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/xattr.c
fs/btrfs/xattr.h
fs/ceph/Kconfig
fs/ceph/Makefile
fs/ceph/acl.c [new file with mode: 0644]
fs/ceph/addr.c
fs/ceph/cache.h
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/ioctl.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/strings.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cramfs/inode.c
fs/cramfs/internal.h [moved from include/linux/cramfs_fs.h with 70% similarity]
fs/cramfs/uncompress.c
fs/dcache.c
fs/dcookies.c
fs/ecryptfs/inode.c
fs/efs/super.c
fs/eventfd.c
fs/exofs/inode.c
fs/exofs/ore.c
fs/ext2/acl.c
fs/ext2/acl.h
fs/ext2/file.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/ext2/xattr.c
fs/ext2/xattr.h
fs/ext3/acl.c
fs/ext3/acl.h
fs/ext3/file.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/xattr.c
fs/ext3/xattr.h
fs/ext4/acl.c
fs/ext4/acl.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/xattr.c
fs/ext4/xattr.h
fs/f2fs/acl.c
fs/f2fs/acl.h
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/namei.c
fs/f2fs/xattr.c
fs/f2fs/xattr.h
fs/file.c
fs/fuse/file.c
fs/generic_acl.c [deleted file]
fs/gfs2/acl.c
fs/gfs2/acl.h
fs/gfs2/inode.c
fs/gfs2/xattr.c
fs/hfsplus/acl.h
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/hfsplus/posix_acl.c
fs/hfsplus/xattr.c
fs/hfsplus/xattr.h
fs/jffs2/acl.c
fs/jffs2/acl.h
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/fs.c
fs/jffs2/malloc.c
fs/jffs2/symlink.c
fs/jffs2/xattr.c
fs/jfs/acl.c
fs/jfs/file.c
fs/jfs/jfs_acl.h
fs/jfs/jfs_xattr.h
fs/jfs/namei.c
fs/jfs/super.c
fs/jfs/xattr.c
fs/mount.h
fs/namei.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3super.c
fs/nfs/nfs4client.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4super.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/acl.h
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3acl.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4proc.c
fs/nfsd/vfs.c
fs/nfsd/vfs.h
fs/nls/mac-celtic.c
fs/nls/mac-centeuro.c
fs/nls/mac-croatian.c
fs/nls/mac-cyrillic.c
fs/nls/mac-gaelic.c
fs/nls/mac-greek.c
fs/nls/mac-iceland.c
fs/nls/mac-inuit.c
fs/nls/mac-roman.c
fs/nls/mac-romanian.c
fs/nls/mac-turkish.c
fs/nls/nls_ascii.c
fs/nls/nls_base.c
fs/nls/nls_cp1250.c
fs/nls/nls_cp1251.c
fs/nls/nls_cp1255.c
fs/nls/nls_cp437.c
fs/nls/nls_cp737.c
fs/nls/nls_cp775.c
fs/nls/nls_cp850.c
fs/nls/nls_cp852.c
fs/nls/nls_cp855.c
fs/nls/nls_cp857.c
fs/nls/nls_cp860.c
fs/nls/nls_cp861.c
fs/nls/nls_cp862.c
fs/nls/nls_cp863.c
fs/nls/nls_cp864.c
fs/nls/nls_cp865.c
fs/nls/nls_cp866.c
fs/nls/nls_cp869.c
fs/nls/nls_cp874.c
fs/nls/nls_cp932.c
fs/nls/nls_cp936.c
fs/nls/nls_cp949.c
fs/nls/nls_cp950.c
fs/nls/nls_euc-jp.c
fs/nls/nls_iso8859-1.c
fs/nls/nls_iso8859-13.c
fs/nls/nls_iso8859-14.c
fs/nls/nls_iso8859-15.c
fs/nls/nls_iso8859-2.c
fs/nls/nls_iso8859-3.c
fs/nls/nls_iso8859-4.c
fs/nls/nls_iso8859-5.c
fs/nls/nls_iso8859-6.c
fs/nls/nls_iso8859-7.c
fs/nls/nls_iso8859-9.c
fs/nls/nls_koi8-r.c
fs/nls/nls_koi8-ru.c
fs/nls/nls_koi8-u.c
fs/nls/nls_utf8.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify.h
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/notification.c
fs/ocfs2/acl.c
fs/ocfs2/acl.h
fs/ocfs2/file.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/xattr.c
fs/ocfs2/xattr.h
fs/posix_acl.c
fs/qnx4/inode.c
fs/qnx4/qnx4.h
fs/read_write.c
fs/reiserfs/acl.h
fs/reiserfs/file.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/reiserfs.h
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_acl.c
fs/xattr_acl.c [deleted file]
fs/xfs/xfs_acl.c
fs/xfs/xfs_acl.h
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_file.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_iops.h
fs/xfs/xfs_xattr.c
include/asm-generic/pgtable.h
include/dt-bindings/clock/qcom,mmcc-msm8974.h
include/linux/bootmem.h
include/linux/ceph/buffer.h
include/linux/ceph/ceph_features.h
include/linux/ceph/ceph_fs.h
include/linux/ceph/libceph.h
include/linux/ceph/messenger.h
include/linux/ceph/osd_client.h
include/linux/ceph/osdmap.h
include/linux/ceph/rados.h
include/linux/clk-provider.h
include/linux/clk/ti.h [new file with mode: 0644]
include/linux/compat.h
include/linux/cramfs_fs_sb.h [deleted file]
include/linux/crush/crush.h
include/linux/crush/mapper.h
include/linux/fdtable.h
include/linux/fs.h
include/linux/fsnotify_backend.h
include/linux/generic_acl.h [deleted file]
include/linux/interrupt.h
include/linux/ipc.h
include/linux/ipc_namespace.h
include/linux/mfd/mc13xxx.h
include/linux/mm.h
include/linux/msg.h
include/linux/mtd/mtdram.h
include/linux/mtd/nand.h
include/linux/mtd/partitions.h
include/linux/nfs_fs.h
include/linux/nls.h
include/linux/of_fdt.h
include/linux/of_mtd.h
include/linux/platform_data/leds-kirkwood-netxbig.h
include/linux/platform_data/leds-kirkwood-ns2.h
include/linux/platform_data/mtd-nand-omap2.h
include/linux/platform_data/mtd-nand-pxa3xx.h
include/linux/platform_data/mtd-onenand-omap2.h
include/linux/platform_data/mtd-orion_nand.h
include/linux/platform_data/si5351.h
include/linux/posix_acl.h
include/linux/posix_acl_xattr.h
include/linux/rcupdate.h
include/linux/shm.h
include/linux/splice.h
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/vmstat.h
include/math-emu/op-common.h
include/scsi/osd_ore.h
include/trace/events/sunrpc.h
init/do_mounts_rd.c
init/main.c
ipc/compat.c
ipc/compat_mq.c
ipc/ipc_sysctl.c
ipc/mqueue.c
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/kexec.c
kernel/rcu/update.c
kernel/softirq.c
kernel/trace/trace.c
lib/Kconfig.debug
lib/dma-debug.c
lib/dynamic_debug.c
lib/genalloc.c
lib/swiotlb.c
mm/filemap.c
mm/huge_memory.c
mm/internal.h
mm/memblock.c
mm/mempolicy.c
mm/migrate.c
mm/mm_init.c
mm/page-writeback.c
mm/readahead.c
mm/shmem.c
mm/slab_common.c
mm/slub.c
mm/vmalloc.c
mm/vmscan.c
net/ceph/buffer.c
net/ceph/ceph_common.c
net/ceph/crush/crush.c
net/ceph/crush/mapper.c
net/ceph/debugfs.c
net/ceph/messenger.c
net/ceph/mon_client.c
net/ceph/osd_client.c
net/ceph/osdmap.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/netns.h
net/sunrpc/rpc_pipe.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
scripts/checkpatch.pl
scripts/mod/modpost.c

index 01e769d6984d575bc431b3be14f014434633427b..37559a06393b56c743ee9b45c129f268bc16aa6c 100644 (file)
@@ -1,13 +1,13 @@
 What:          /config/usb-gadget
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                This group contains sub-groups corresponding to created
                USB gadgets.
 
 What:          /config/usb-gadget/gadget
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
 
                The attributes of a gadget:
@@ -27,7 +27,7 @@ Description:
 
 What:          /config/usb-gadget/gadget/configs
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                This group contains a USB gadget's configurations
 
@@ -58,20 +58,20 @@ Description:
 
 What:          /config/usb-gadget/gadget/functions
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                This group contains functions available to this USB gadget.
 
 What:          /config/usb-gadget/gadget/strings
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                This group contains subdirectories for language-specific
                strings for this gadget.
 
 What:          /config/usb-gadget/gadget/strings/language
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index 5708a568b5f6fb63fa7493e7ff33831ab5acbd90..d21092d75a0587ea8d7edbcd48a9af344388396d 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/acm.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
 
                This item contains just one readonly attribute: port_num.
index 6b9a582ce0b55afbca2f25688577cc4ea15cc675..0addf7704b4c0ee9639406abfd7f16184d7402fd 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/ecm.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index dbddf36b48b3c037f2822f06469c4e85d4e23928..a4c57158fcdef28a8805157b24015eb4edb38568 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/eem.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index 14343e237e83910e54255d14f7c85cf5837a7957..e39b27653c65c15f4911db846c7ca98859bf0463 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/ffs.name
 Date:          Nov 2013
-KenelVersion:  3.13
+KernelVersion: 3.13
 Description:   The purpose of this directory is to create and remove it.
 
                A corresponding USB function instance is created/removed.
index 852b2365a5b57a2e0c7f56030815b7397fddb695..9aae5bfb990887a6ad3faee29830d1603a7ecb19 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/Loopback.name
 Date:          Nov 2013
-KenelVersion:  3.13
+KernelVersion: 3.13
 Description:
                The attributes:
 
index ad72a37ee9ff24fab43631db8c8a0b01f02f4252..9931fb0d63ba44ce155d3e859a5bac2df451298a 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/mass_storage.name
 Date:          Oct 2013
-KenelVersion:  3.13
+KernelVersion: 3.13
 Description:
                The attributes:
 
@@ -13,7 +13,7 @@ Description:
 
 What:          /config/usb-gadget/gadget/functions/mass_storage.name/lun.name
 Date:          Oct 2013
-KenelVersion:  3.13
+KernelVersion: 3.13
 Description:
                The attributes:
 
index bc309f42357d60a3843eed7f71b4c0e9fd55d660..6fe723effc7894aeccfc297a34219cd0a5725565 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/ncm.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index aaa5c96fb7c609de47de1a716c1d233ce7f43368..a6a9327ed9ba51ea6bd0d2aa7d844ccb00cb32cb 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/obex.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
 
                This item contains just one readonly attribute: port_num.
index 3e3b742cdfd73aa4c3d04da9e061cb9a932d5257..7037a358e6c48f672b0aab94ec5159a29fe9fcdc 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/phonet.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
 
                This item contains just one readonly attribute: ifname.
index 822e6dad8fc08e5644a7e8297464f04d804e4d8f..e32879b84b4d092ffc3aa3c655c470ec5135c9fd 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/rndis.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index 16f130c1501f009f0d021138d48a8b27da58ee52..474d249f760be01f1311ba17842b4c4e827c8079 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/gser.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
 
                This item contains just one readonly attribute: port_num.
index a30f3093ef6caeb9b0891474884c40432e898000..29477c319f61bf16f1259962237f4b3f0a7e6287 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/SourceSink.name
 Date:          Nov 2013
-KenelVersion:  3.13
+KernelVersion: 3.13
 Description:
                The attributes:
 
index 154ae597cd99a84604decdd1a667f18707bda7e1..9373e2c51ea454e6de4031908ed5cdee4a04e9b6 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/geth.name
 Date:          Jun 2013
-KenelVersion:  3.11
+KernelVersion: 3.11
 Description:
                The attributes:
 
index 0a306476424ef06cf6222e6e13541804bc546333..501adc2a9ec723841c5246b19875a9bc14471ada 100644 (file)
@@ -18,6 +18,28 @@ Removal of a device:
 
   $ echo <dev-id> > /sys/bus/rbd/remove
 
+What:          /sys/bus/rbd/add_single_major
+Date:          December 2013
+KernelVersion: 3.14
+Contact:       Sage Weil <sage@inktank.com>
+Description:   Available only if rbd module is inserted with single_major
+               parameter set to true.
+               Usage is the same as for /sys/bus/rbd/add.  If present,
+               should be used instead of the latter: any attempts to use
+               /sys/bus/rbd/add if /sys/bus/rbd/add_single_major is
+               available will fail for backwards compatibility reasons.
+
+What:          /sys/bus/rbd/remove_single_major
+Date:          December 2013
+KernelVersion: 3.14
+Contact:       Sage Weil <sage@inktank.com>
+Description:   Available only if rbd module is inserted with single_major
+               parameter set to true.
+               Usage is the same as for /sys/bus/rbd/remove.  If present,
+               should be used instead of the latter: any attempts to use
+               /sys/bus/rbd/remove if /sys/bus/rbd/remove_single_major is
+               available will fail for backwards compatibility reasons.
+
 Entries under /sys/bus/rbd/devices/<dev-id>/
 --------------------------------------------
 
@@ -33,6 +55,10 @@ major
 
        The block device major number.
 
+minor
+
+       The block device minor number.  (December 2013, since 3.14.)
+
 name
 
        The name of the rbd image.
index 611f5a5499b153c9594ad37e7237f7a35489b3bd..fa0151a712f9c5a0d9fe43db6e0746ff4046a5e0 100644 (file)
@@ -22,10 +22,12 @@ locations such as buffers like the printk buffer or the process table.
 Retrieving a full system memory dump is also possible over the FireWire,
 using data transfer rates in the order of 10MB/s or more.
 
-Memory access is currently limited to the low 4G of physical address
-space which can be a problem on IA64 machines where memory is located
-mostly above that limit, but it is rarely a problem on more common
-hardware such as hardware based on x86, x86-64 and PowerPC.
+With most FireWire controllers, memory access is limited to the low 4 GB
+of physical address space.  This can be a problem on IA64 machines where
+memory is located mostly above that limit, but it is rarely a problem on
+more common hardware such as x86, x86-64 and PowerPC.  However, at least
+Agere/LSI FW643e and FW643e2 controllers are known to support access to
+physical addresses above 4 GB.
 
 Together with a early initialization of the OHCI-1394 controller for debugging,
 this facility proved most useful for examining long debugs logs in the printk
@@ -36,17 +38,11 @@ available (notebooks) or too slow for extensive debug information (like ACPI).
 Drivers
 -------
 
-The ohci1394 driver in drivers/ieee1394 initializes the OHCI-1394 controllers
-to a working state and enables physical DMA by default for all remote nodes.
-This can be turned off by ohci1394's module parameter phys_dma=0.
-
-The alternative firewire-ohci driver in drivers/firewire uses filtered physical
+The firewire-ohci driver in drivers/firewire uses filtered physical
 DMA by default, which is more secure but not suitable for remote debugging.
-Compile the driver with CONFIG_FIREWIRE_OHCI_REMOTE_DMA (Kernel hacking menu:
-Remote debugging over FireWire with firewire-ohci) to get unfiltered physical
-DMA.
+Pass the remote_dma=1 parameter to the driver to get unfiltered physical DMA.
 
-Because ohci1394 and firewire-ohci depend on the PCI enumeration to be
+Because the firewire-ohci driver depends on the PCI enumeration to be
 completed, an initialization routine which runs pretty early has been
 implemented for x86.  This routine runs long before console_init() can be
 called, i.e. before the printk buffer appears on the console.
@@ -64,7 +60,7 @@ be used to view the printk buffer of a remote machine, even with live update.
 
 Bernhard Kaindl enhanced firescope to support accessing 64-bit machines
 from 32-bit firescope and vice versa:
-- http://halobates.de/firewire/firescope-0.2.2.tar.bz2
+- http://v3.sk/~lkundrak/firescope/
 
 and he implemented fast system dump (alpha version - read README.txt):
 - http://halobates.de/firewire/firedump-0.1.tar.bz2
@@ -92,11 +88,11 @@ Step-by-step instructions for using firescope with early OHCI initialization:
 
 1) Verify that your hardware is supported:
 
-   Load the ohci1394 or the fw-ohci module and check your kernel logs.
+   Load the firewire-ohci module and check your kernel logs.
    You should see a line similar to
 
-   ohci1394: fw-host0: OHCI-1394 1.1 (PCI): IRQ=[18]  MMIO=[fe9ff800-fe9fffff]
-   ... Max Packet=[2048]  IR/IT contexts=[4/8]
+   firewire_ohci 0000:15:00.1: added OHCI v1.0 device as card 2, 4 IR + 4 IT
+   ... contexts, quirks 0x11
 
    when loading the driver. If you have no supported controller, many PCI,
    CardBus and even some Express cards which are fully compliant to OHCI-1394
@@ -105,6 +101,9 @@ Step-by-step instructions for using firescope with early OHCI initialization:
    compliant, they are based on TI PCILynx chips and require drivers for Win-
    dows operating systems.
 
+   The mentioned kernel log message contains ">4 GB phys DMA" in case of
+   OHCI-1394 controllers which support accesses above this limit.
+
 2) Establish a working FireWire cable connection:
 
    Any FireWire cable, as long at it provides electrically and mechanically
@@ -113,20 +112,18 @@ Step-by-step instructions for using firescope with early OHCI initialization:
 
    If an driver is running on both machines you should see a line like
 
-   ieee1394: Node added: ID:BUS[0-01:1023]  GUID[0090270001b84bba]
+   firewire_core 0000:15:00.1: created device fw1: GUID 00061b0020105917, S400
 
    on both machines in the kernel log when the cable is plugged in
    and connects the two machines.
 
 3) Test physical DMA using firescope:
 
-   On the debug host,
-       - load the raw1394 module,
-       - make sure that /dev/raw1394 is accessible,
+   On the debug host, make sure that /dev/fw* is accessible,
    then start firescope:
 
        $ firescope
-       Port 0 (ohci1394) opened, 2 nodes detected
+       Port 0 (/dev/fw1) opened, 2 nodes detected
 
        FireScope
        ---------
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
deleted file mode 100644 (file)
index 3545ea7..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-* Texas Instruments Davinci NAND
-
-This file provides information, what the device node for the
-davinci nand interface contain.
-
-Required properties:
-- compatible: "ti,davinci-nand";
-- reg : contain 2 offset/length values:
-        - offset and length for the access window
-        - offset and length for accessing the aemif control registers
-- ti,davinci-chipselect: Indicates on the davinci_nand driver which
-                         chipselect is used for accessing the nand.
-
-Recommended properties :
-- ti,davinci-mask-ale: mask for ale
-- ti,davinci-mask-cle: mask for cle
-- ti,davinci-mask-chipsel: mask for chipselect
-- ti,davinci-ecc-mode: ECC mode valid values for davinci driver:
-               - "none"
-               - "soft"
-               - "hw"
-- ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4.
-- ti,davinci-nand-buswidth: buswidth 8 or 16
-- ti,davinci-nand-use-bbt: use flash based bad block table support.
-
-nand device bindings may contain additional sub-nodes describing
-partitions of the address space. See partition.txt for more detail.
-
-Example(da850 EVM ):
-nand_cs3@62000000 {
-       compatible = "ti,davinci-nand";
-       reg = <0x62000000 0x807ff
-               0x68000000 0x8000>;
-       ti,davinci-chipselect = <1>;
-       ti,davinci-mask-ale = <0>;
-       ti,davinci-mask-cle = <0>;
-       ti,davinci-mask-chipsel = <0>;
-       ti,davinci-ecc-mode = "hw";
-       ti,davinci-ecc-bits = <4>;
-       ti,davinci-nand-use-bbt;
-
-       partition@180000 {
-               label = "ubifs";
-               reg = <0x180000 0x7e80000>;
-       };
-};
diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt
new file mode 100644 (file)
index 0000000..7faf5a6
--- /dev/null
@@ -0,0 +1,31 @@
+Binding for Texas Instruments APLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped APLL with usually two selectable input clocks
+(reference clock and bypass clock), with analog phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) APLL mostly behaves like
+a subtype of a DPLL [2], although a simplified one at that.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/dpll.txt
+
+Required properties:
+- compatible : shall be "ti,dra7-apll-clock"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks (clk-ref and clk-bypass)
+- reg : address and length of the register set for controlling the APLL.
+  It contains the information of registers in the following order:
+       "control" - contains the control register base address
+       "idlest" - contains the idlest register base address
+
+Examples:
+       apll_pcie_ck: apll_pcie_ck@4a008200 {
+               #clock-cells = <0>;
+               clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
+               reg = <0x4a00821c 0x4>, <0x4a008220 0x4>;
+               compatible = "ti,dra7-apll-clock";
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/autoidle.txt b/Documentation/devicetree/bindings/clock/ti/autoidle.txt
new file mode 100644 (file)
index 0000000..7c735dd
--- /dev/null
@@ -0,0 +1,39 @@
+Binding for Texas Instruments autoidle clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a register mapped
+clock which can be put to idle automatically by hardware based on the usage
+and a configuration bit setting. Autoidle clock is never an individual
+clock, it is always a derivative of some basic clock like a gate, divider,
+or fixed-factor.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- reg : offset for the register controlling the autoidle
+- ti,autoidle-shift : bit shift of the autoidle enable bit
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0
+
+Examples:
+       dpll_core_m4_ck: dpll_core_m4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2d38>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck {
+               #clock-cells = <0>;
+               compatible = "ti,fixed-factor-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,clock-div = <1>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b4>;
+               ti,clock-mult = <1>;
+               ti,invert-autoidle-bit;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt
new file mode 100644 (file)
index 0000000..cb76b3f
--- /dev/null
@@ -0,0 +1,24 @@
+Binding for Texas Instruments clockdomain.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1] in consumer role.
+Every clock on TI SoC belongs to one clockdomain, but software
+only needs this information for specific clocks which require
+their parent clockdomain to be controlled when the clock is
+enabled/disabled. This binding doesn't define a new clock
+binding type, it is used to group existing clock nodes under
+hardware hierarchy.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,clockdomain"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of clocks within this domain
+
+Examples:
+       dss_clkdm: dss_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/composite.txt b/Documentation/devicetree/bindings/clock/ti/composite.txt
new file mode 100644 (file)
index 0000000..5f43c47
--- /dev/null
@@ -0,0 +1,54 @@
+Binding for TI composite clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. It assumes a
+register-mapped composite clock with multiple different sub-types;
+
+a multiplexer clock with multiple input clock signals or parents, one
+of which can be selected as output, this behaves exactly as [2]
+
+an adjustable clock rate divider, this behaves exactly as [3]
+
+a gating function which can be used to enable and disable the output
+clock, this behaves exactly as [4]
+
+The binding must provide a list of the component clocks that shall be
+merged to this clock. The component clocks shall be of one of the
+"ti,*composite*-clock" types.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/mux.txt
+[3] Documentation/devicetree/bindings/clock/ti/divider.txt
+[4] Documentation/devicetree/bindings/clock/ti/gate.txt
+
+Required properties:
+- compatible : shall be: "ti,composite-clock"
+- clocks : link phandles of component clocks
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Examples:
+
+usb_l4_gate_ick: usb_l4_gate_ick {
+       #clock-cells = <0>;
+       compatible = "ti,composite-interface-clock";
+       clocks = <&l4_ick>;
+       ti,bit-shift = <5>;
+       reg = <0x0a10>;
+};
+
+usb_l4_div_ick: usb_l4_div_ick {
+       #clock-cells = <0>;
+       compatible = "ti,composite-divider-clock";
+       clocks = <&l4_ick>;
+       ti,bit-shift = <4>;
+       ti,max-div = <1>;
+       reg = <0x0a40>;
+       ti,index-starts-at-one;
+};
+
+usb_l4_ick: usb_l4_ick {
+       #clock-cells = <0>;
+       compatible = "ti,composite-clock";
+       clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+};
diff --git a/Documentation/devicetree/bindings/clock/ti/divider.txt b/Documentation/devicetree/bindings/clock/ti/divider.txt
new file mode 100644 (file)
index 0000000..35a6f5c
--- /dev/null
@@ -0,0 +1,114 @@
+Binding for TI divider clock
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped adjustable clock rate divider that does not gate and has
+only one input clock or parent.  By default the value programmed into
+the register is one less than the actual divisor value.  E.g:
+
+register value         actual divisor value
+0                      1
+1                      2
+2                      3
+
+This assumption may be modified by the following optional properties:
+
+ti,index-starts-at-one - valid divisor values start at 1, not the default
+of 0.  E.g:
+register value         actual divisor value
+1                      1
+2                      2
+3                      3
+
+ti,index-power-of-two - valid divisor values are powers of two.  E.g:
+register value         actual divisor value
+0                      1
+1                      2
+2                      4
+
+Additionally an array of valid dividers may be supplied like so:
+
+       ti,dividers = <4>, <8>, <0>, <16>;
+
+Which will map the resulting values to a divisor table by their index:
+register value         actual divisor value
+0                      4
+1                      8
+2                      <invalid divisor, skipped>
+3                      16
+
+Any zero value in this array means the corresponding bit-value is invalid
+and must not be used.
+
+The binding must also provide the register to control the divider and
+unless the divider array is provided, min and max dividers. Optionally
+the number of bits to shift that mask, if necessary. If the shift value
+is missing it is the same as supplying a zero shift.
+
+This binding can also optionally provide support to the hardware autoidle
+feature, see [2].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/autoidle.txt
+
+Required properties:
+- compatible : shall be "ti,divider-clock" or "ti,composite-divider-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable divider
+
+Optional properties:
+- clock-output-names : from common clock binding.
+- ti,dividers : array of integers defining divisors
+- ti,bit-shift : number of bits to shift the divider value, defaults to 0
+- ti,min-div : min divisor for dividing the input clock rate, only
+  needed if the first divisor is offset from the default value (1)
+- ti,max-div : max divisor for dividing the input clock rate, only needed
+  if ti,dividers is not defined.
+- ti,index-starts-at-one : valid divisor programming starts at 1, not zero,
+  only valid if ti,dividers is not defined.
+- ti,index-power-of-two : valid divisor programming must be a power of two,
+  only valid if ti,dividers is not defined.
+- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock,
+  see [2]
+- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0,
+  see [2]
+- ti,set-rate-parent : clk_set_rate is propagated to parent
+
+Examples:
+dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 {
+       #clock-cells = <0>;
+       compatible = "ti,divider-clock";
+       clocks = <&dpll_usb_ck>;
+       ti,max-div = <127>;
+       reg = <0x190>;
+       ti,index-starts-at-one;
+};
+
+aess_fclk: aess_fclk@4a004528 {
+       #clock-cells = <0>;
+       compatible = "ti,divider-clock";
+       clocks = <&abe_clk>;
+       ti,bit-shift = <24>;
+       reg = <0x528>;
+       ti,max-div = <2>;
+};
+
+dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck {
+       #clock-cells = <0>;
+       compatible = "ti,composite-divider-clock";
+       clocks = <&dpll_core_x2_ck>;
+       ti,max-div = <31>;
+       reg = <0x0134>;
+       ti,index-starts-at-one;
+};
+
+ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2 {
+       #clock-cells = <0>;
+       compatible = "ti,composite-divider-clock";
+       clocks = <&corex2_fck>;
+       ti,bit-shift = <8>;
+       reg = <0x0a40>;
+       ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
+};
diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt
new file mode 100644 (file)
index 0000000..30bfdb7
--- /dev/null
@@ -0,0 +1,75 @@
+Binding for Texas Instruments DPLL clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped DPLL with usually two selectable input clocks
+(reference clock and bypass clock), with digital phase locked
+loop logic for multiplying the input clock to a desired output
+clock. This clock also typically supports different operation
+modes (locked, low power stop etc.) This binding has several
+sub-types, which effectively result in slightly different setup
+for the actual DPLL clock.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of:
+               "ti,omap3-dpll-clock",
+               "ti,omap3-dpll-core-clock",
+               "ti,omap3-dpll-per-clock",
+               "ti,omap3-dpll-per-j-type-clock",
+               "ti,omap4-dpll-clock",
+               "ti,omap4-dpll-x2-clock",
+               "ti,omap4-dpll-core-clock",
+               "ti,omap4-dpll-m4xen-clock",
+               "ti,omap4-dpll-j-type-clock",
+               "ti,am3-dpll-no-gate-clock",
+               "ti,am3-dpll-j-type-clock",
+               "ti,am3-dpll-no-gate-j-type-clock",
+               "ti,am3-dpll-clock",
+               "ti,am3-dpll-core-clock",
+               "ti,am3-dpll-x2-clock",
+
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks, first entry lists reference clock
+  and second entry bypass clock
+- reg : offsets for the register set for controlling the DPLL.
+  Registers are listed in following order:
+       "control" - contains the control register base address
+       "idlest" - contains the idle status register base address
+       "mult-div1" - contains the multiplier / divider register base address
+       "autoidle" - contains the autoidle register base address (optional)
+  ti,am3-* dpll types do not have autoidle register
+
+Optional properties:
+- DPLL mode setting - defining any one or more of the following overrides
+  default setting.
+       - ti,low-power-stop : DPLL supports low power stop mode, gating output
+       - ti,low-power-bypass : DPLL output matches rate of parent bypass clock
+       - ti,lock : DPLL locks in programmed rate
+
+Examples:
+       dpll_core_ck: dpll_core_ck@44e00490 {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-core-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x490>, <0x45c>, <0x488>, <0x468>;
+       };
+
+       dpll2_ck: dpll2_ck@48004004 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-clock";
+               clocks = <&sys_ck>, <&dpll2_fck>;
+               ti,low-power-stop;
+               ti,low-power-bypass;
+               ti,lock;
+               reg = <0x4>, <0x24>, <0x34>, <0x40>;
+       };
+
+       dpll_core_ck: dpll_core_ck@44e00490 {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-core-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x90>, <0x5c>, <0x68>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt b/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt
new file mode 100644 (file)
index 0000000..662b36d
--- /dev/null
@@ -0,0 +1,43 @@
+Binding for TI fixed factor rate clock sources.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1], and also uses the autoidle
+support from TI autoidle clock [2].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/ti/autoidle.txt
+
+Required properties:
+- compatible : shall be "ti,fixed-factor-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- ti,clock-div: fixed divider.
+- ti,clock-mult: fixed multiplier.
+- clocks: parent clock.
+
+Optional properties:
+- ti,autoidle-shift: bit shift of the autoidle enable bit for the clock,
+  see [2]
+- reg: offset for the autoidle register of this clock, see [2]
+- ti,invert-autoidle-bit: autoidle is enabled by setting the bit to 0, see [2]
+- ti,set-rate-parent: clk_set_rate is propagated to parent
+
+Example:
+       clock {
+               compatible = "ti,fixed-factor-clock";
+               clocks = <&parentclk>;
+               #clock-cells = <0>;
+               ti,clock-div = <2>;
+               ti,clock-mult = <1>;
+       };
+
+       dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck {
+               #clock-cells = <0>;
+               compatible = "ti,fixed-factor-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,clock-div = <1>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b4>;
+               ti,clock-mult = <1>;
+               ti,invert-autoidle-bit;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt
new file mode 100644 (file)
index 0000000..125281a
--- /dev/null
@@ -0,0 +1,85 @@
+Binding for Texas Instruments gate clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features. If no register
+is provided for this clock, the code assumes that a clockdomain
+will be controlled instead and the corresponding hw-ops for
+that is used.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt
+
+Required properties:
+- compatible : shall be one of:
+  "ti,gate-clock" - basic gate clock
+  "ti,wait-gate-clock" - gate clock which waits until clock is active before
+                        returning from clk_enable()
+  "ti,dss-gate-clock" - gate clock with DSS specific hardware handling
+  "ti,am35xx-gate-clock" - gate clock with AM35xx specific hardware handling
+  "ti,clkdm-gate-clock" - clockdomain gate clock, which derives its functional
+                         clock directly from a clockdomain, see [3] how
+                         to map clockdomains properly
+  "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling,
+                         required for a hardware errata
+- #clock-cells : from common clock binding; shall be set to 0
+- clocks : link to phandle of parent clock
+- reg : offset for register controlling adjustable gate, not needed for
+       ti,clkdm-gate-clock type
+
+Optional properties:
+- ti,bit-shift : bit shift for programming the clock gate, invalid for
+                ti,clkdm-gate-clock type
+- ti,set-bit-to-disable : inverts default gate programming. Setting the bit
+  gates the clock and clearing the bit ungates the clock.
+
+Examples:
+       mmchs2_fck: mmchs2_fck@48004a00 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x48004a00 0x4>;
+               ti,bit-shift = <25>;
+       };
+
+       uart4_fck_am35xx: uart4_fck_am35xx {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <23>;
+       };
+
+       dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2@48004e00 {
+               #clock-cells = <0>;
+               compatible = "ti,dss-gate-clock";
+               clocks = <&dpll4_m4x2_ck>;
+               reg = <0x48004e00 0x4>;
+               ti,bit-shift = <0>;
+       };
+
+       emac_ick: emac_ick@4800259c {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x4800259c 0x4>;
+               ti,bit-shift = <1>;
+       };
+
+       emu_src_ck: emu_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,clkdm-gate-clock";
+               clocks = <&emu_src_mux_ck>;
+       };
+
+       dpll4_m2x2_ck: dpll4_m2x2_ck@48004d00 {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll4_m2x2_mul_ck>;
+               ti,bit-shift = <0x1b>;
+               reg = <0x48004d00 0x4>;
+               ti,set-bit-to-disable;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
new file mode 100644 (file)
index 0000000..064e8ca
--- /dev/null
@@ -0,0 +1,54 @@
+Binding for Texas Instruments interface clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1]. This clock is
+quite much similar to the basic gate-clock [2], however,
+it supports a number of additional features, including
+companion clock finding (match corresponding functional gate
+clock) and hardware autoidle enable / disable.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+
+Required properties:
+- compatible : shall be one of:
+  "ti,omap3-interface-clock" - basic OMAP3 interface clock
+  "ti,omap3-no-wait-interface-clock" - interface clock which has no hardware
+                                      capability for waiting clock to be ready
+  "ti,omap3-hsotgusb-interface-clock" - interface clock with USB specific HW
+                                       handling
+  "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
+  "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
+  "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
+- #clock-cells : from common clock binding; shall be set to 0
+- clocks : link to phandle of parent clock
+- reg : base address for the control register
+
+Optional properties:
+- ti,bit-shift : bit shift for the bit enabling/disabling the clock (default 0)
+
+Examples:
+       aes1_ick: aes1_ick@48004a14 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l4_ick2>;
+               reg = <0x48004a14 0x4>;
+               ti,bit-shift = <3>;
+       };
+
+       cam_ick: cam_ick@48004f10 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-no-wait-interface-clock";
+               clocks = <&l4_ick>;
+               reg = <0x48004f10 0x4>;
+               ti,bit-shift = <0>;
+       };
+
+       ssi_ick_3430es2: ssi_ick_3430es2@48004a10 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-ssi-interface-clock";
+               clocks = <&ssi_l4_ick>;
+               reg = <0x48004a10 0x4>;
+               ti,bit-shift = <0>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/mux.txt b/Documentation/devicetree/bindings/clock/ti/mux.txt
new file mode 100644 (file)
index 0000000..2d0d170
--- /dev/null
@@ -0,0 +1,76 @@
+Binding for TI mux clock.
+
+Binding status: Unstable - ABI compatibility may be broken in the future
+
+This binding uses the common clock binding[1].  It assumes a
+register-mapped multiplexer with multiple input clock signals or
+parents, one of which can be selected as output.  This clock does not
+gate or adjust the parent rate via a divider or multiplier.
+
+By default the "clocks" property lists the parents in the same order
+as they are programmed into the regster.  E.g:
+
+       clocks = <&foo_clock>, <&bar_clock>, <&baz_clock>;
+
+results in programming the register as follows:
+
+register value         selected parent clock
+0                      foo_clock
+1                      bar_clock
+2                      baz_clock
+
+Some clock controller IPs do not allow a value of zero to be programmed
+into the register, instead indexing begins at 1.  The optional property
+"index-starts-at-one" modified the scheme as follows:
+
+register value         selected clock parent
+1                      foo_clock
+2                      bar_clock
+3                      baz_clock
+
+The binding must provide the register to control the mux. Optionally
+the number of bits to shift the control field in the register can be
+supplied. If the shift value is missing it is the same as supplying
+a zero shift.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,mux-clock" or "ti,composite-mux-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles of parent clocks
+- reg : register offset for register controlling adjustable mux
+
+Optional properties:
+- ti,bit-shift : number of bits to shift the bit-mask, defaults to
+  0 if not present
+- ti,index-starts-at-one : valid input select programming starts at 1, not
+  zero
+- ti,set-rate-parent : clk_set_rate is propagated to parent clock,
+  not supported by the composite-mux-clock subtype
+
+Examples:
+
+sys_clkin_ck: sys_clkin_ck@4a306110 {
+       #clock-cells = <0>;
+       compatible = "ti,mux-clock";
+       clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+       reg = <0x0110>;
+       ti,index-starts-at-one;
+};
+
+abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@4a306108 {
+       #clock-cells = <0>;
+       compatible = "ti,mux-clock";
+       clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+       ti,bit-shift = <24>;
+       reg = <0x0108>;
+};
+
+mcbsp5_mux_fck: mcbsp5_mux_fck {
+       #clock-cells = <0>;
+       compatible = "ti,composite-mux-clock";
+       clocks = <&core_96m_fck>, <&mcbsp_clks>;
+       ti,bit-shift = <4>;
+       reg = <0x02d8>;
+};
index 80ff3dfb1f325e89993184324e8ed053fd15e867..d7221b84987cd684169bee2765a050cba3511c75 100644 (file)
@@ -2,6 +2,13 @@ LEDs connected to tca6507
 
 Required properties:
 - compatible : should be : "ti,tca6507".
+- #address-cells: must be 1
+- #size-cells: must be 0
+- reg: typically 0x45.
+
+Optional properties:
+- gpio-controller: allows lines to be used as output-only GPIOs.
+- #gpio-cells: if present, must be 0.
 
 Each led is represented as a sub-node of the ti,tca6507 device.
 
@@ -10,6 +17,7 @@ LED sub-node properties:
 - reg : number of LED line (could be from 0 to 6)
 - linux,default-trigger : (optional)
    see Documentation/devicetree/bindings/leds/common.txt
+- compatible: either "led" (the default) or "gpio".
 
 Examples:
 
@@ -19,6 +27,9 @@ tca6507@45 {
        #size-cells = <0>;
        reg = <0x45>;
 
+       gpio-controller;
+       #gpio-cells = <2>;
+
        led0: red-aux@0 {
                label = "red:aux";
                reg = <0x0>;
@@ -29,5 +40,10 @@ tca6507@45 {
                reg = <0x5>;
                linux,default-trigger = "default-on";
        };
+
+       wifi-reset@6 {
+               reg = <0x6>;
+               compatible = "gpio";
+       };
 };
 
diff --git a/Documentation/devicetree/bindings/mtd/davinci-nand.txt b/Documentation/devicetree/bindings/mtd/davinci-nand.txt
new file mode 100644 (file)
index 0000000..cfb18ab
--- /dev/null
@@ -0,0 +1,94 @@
+Device tree bindings for Texas instruments Davinci/Keystone NAND controller
+
+This file provides information, what the device node for the davinci/keystone
+NAND interface contains.
+
+Documentation:
+Davinci DM646x - http://www.ti.com/lit/ug/sprueq7c/sprueq7c.pdf
+Kestone - http://www.ti.com/lit/ug/sprugz3a/sprugz3a.pdf
+
+Required properties:
+
+- compatible:                  "ti,davinci-nand"
+                               "ti,keystone-nand"
+
+- reg:                         Contains 2 offset/length values:
+                               - offset and length for the access window.
+                               - offset and length for accessing the AEMIF
+                               control registers.
+
+- ti,davinci-chipselect:       number of chipselect. Indicates on the
+                               davinci_nand driver which chipselect is used
+                               for accessing the nand.
+                               Can be in the range [0-3].
+
+Recommended properties :
+
+- ti,davinci-mask-ale:         mask for ALE. Needed for executing address
+                               phase. These offset will be added to the base
+                               address for the chip select space the NAND Flash
+                               device is connected to.
+                               If not set equal to 0x08.
+
+- ti,davinci-mask-cle:         mask for CLE. Needed for executing command
+                               phase. These offset will be added to the base
+                               address for the chip select space the NAND Flash
+                               device is connected to.
+                               If not set equal to 0x10.
+
+- ti,davinci-mask-chipsel:     mask for chipselect address. Needed to mask
+                               addresses for given chipselect.
+
+- nand-ecc-mode:               operation mode of the NAND ecc mode. ECC mode
+                               valid values for davinci driver:
+                               - "none"
+                               - "soft"
+                               - "hw"
+
+- ti,davinci-ecc-bits:         used ECC bits, currently supported 1 or 4.
+
+- nand-bus-width:              buswidth 8 or 16. If not present 8.
+
+- nand-on-flash-bbt:           use flash based bad block table support. OOB
+                               identifier is saved in OOB area. If not present
+                               false.
+
+Deprecated properties:
+
+- ti,davinci-ecc-mode:         operation mode of the NAND ecc mode. ECC mode
+                               valid values for davinci driver:
+                               - "none"
+                               - "soft"
+                               - "hw"
+
+- ti,davinci-nand-buswidth:    buswidth 8 or 16. If not present 8.
+
+- ti,davinci-nand-use-bbt:     use flash based bad block table support. OOB
+                               identifier is saved in OOB area. If not present
+                               false.
+
+Nand device bindings may contain additional sub-nodes describing partitions of
+the address space. See partition.txt for more detail. The NAND Flash timing
+values must be programmed in the chip select’s node of AEMIF
+memory-controller (see Documentation/devicetree/bindings/memory-controllers/
+davinci-aemif.txt).
+
+Example(da850 EVM ):
+
+nand_cs3@62000000 {
+       compatible = "ti,davinci-nand";
+       reg = <0x62000000 0x807ff
+              0x68000000 0x8000>;
+       ti,davinci-chipselect = <1>;
+       ti,davinci-mask-ale = <0>;
+       ti,davinci-mask-cle = <0>;
+       ti,davinci-mask-chipsel = <0>;
+       nand-ecc-mode = "hw";
+       ti,davinci-ecc-bits = <4>;
+       nand-on-flash-bbt;
+
+       partition@180000 {
+               label = "ubifs";
+               reg = <0x180000 0x7e80000>;
+       };
+};
index 551b2a179d016df4bd9bb8e611f38633d57d6640..458d5963468826647d2469c23f542bde3ffe047c 100644 (file)
@@ -17,6 +17,14 @@ Required properties:
 Optional properties:
   - nand-on-flash-bbt: boolean to enable on flash bbt option if not
                        present false
+  - fsl,use-minimum-ecc: Protect this NAND flash with the minimum ECC
+                       strength required. The required ECC strength is
+                       automatically discoverable for some flash
+                       (e.g., according to the ONFI standard).
+                       However, note that if this strength is not
+                       discoverable or this property is not enabled,
+                       the software may chooses an implementation-defined
+                       ECC scheme.
 
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
index f1421e2bbab7387a87e1885794b9688780d6de73..86e0a5601ff5dfb05d9eeed35eb3e638ea58cc7b 100644 (file)
@@ -2,7 +2,9 @@ PXA3xx NAND DT bindings
 
 Required properties:
 
- - compatible:         Should be "marvell,pxa3xx-nand"
+ - compatible:         Should be set to one of the following:
+                       marvell,pxa3xx-nand
+                       marvell,armada370-nand
  - reg:                The register base for the controller
  - interrupts:         The interrupt to map
  - #address-cells:     Set to <1> if the node includes partitions
@@ -13,6 +15,8 @@ Optional properties:
  - marvell,nand-keep-config:   Set to keep the NAND controller config as set
                                by the bootloader
  - num-cs:                     Number of chipselect lines to usw
+ - nand-on-flash-bbt:          boolean to enable on flash bbt option if
+                               not present false
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/pwm/atmel-pwm.txt b/Documentation/devicetree/bindings/pwm/atmel-pwm.txt
new file mode 100644 (file)
index 0000000..02331b9
--- /dev/null
@@ -0,0 +1,33 @@
+Atmel PWM controller
+
+Required properties:
+  - compatible: should be one of:
+    - "atmel,at91sam9rl-pwm"
+    - "atmel,sama5d3-pwm"
+  - reg: physical base address and length of the controller's registers
+  - #pwm-cells: Should be 3. See pwm.txt in this directory for a
+    description of the cells format.
+
+Example:
+
+       pwm0: pwm@f8034000 {
+               compatible = "atmel,at91sam9rl-pwm";
+               reg = <0xf8034000 0x400>;
+               #pwm-cells = <3>;
+       };
+
+       pwmleds {
+               compatible = "pwm-leds";
+
+               d1 {
+                       label = "d1";
+                       pwms = <&pwm0 3 5000 0>
+                       max-brightness = <255>;
+               };
+
+               d2 {
+                       label = "d2";
+                       pwms = <&pwm0 1 5000 1>
+                       max-brightness = <255>;
+               };
+       };
diff --git a/Documentation/devicetree/bindings/pwm/pxa-pwm.txt b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt
new file mode 100644 (file)
index 0000000..5ae9f1e
--- /dev/null
@@ -0,0 +1,30 @@
+Marvell PWM controller
+
+Required properties:
+- compatible: should be one or more of:
+  - "marvell,pxa250-pwm"
+  - "marvell,pxa270-pwm"
+  - "marvell,pxa168-pwm"
+  - "marvell,pxa910-pwm"
+- reg: Physical base address and length of the registers used by the PWM channel
+  Note that one device instance must be created for each PWM that is used, so the
+  length covers only the register window for one PWM output, not that of the
+  entire PWM controller.  Currently length is 0x10 for all supported devices.
+- #pwm-cells: Should be 1.  This cell is used to specify the period in
+  nanoseconds.
+
+Example PWM device node:
+
+pwm0: pwm@40b00000 {
+       compatible = "marvell,pxa250-pwm";
+       reg = <0x40b00000 0x10>;
+       #pwm-cells = <1>;
+};
+
+Example PWM client node:
+
+backlight {
+       compatible = "pwm-backlight";
+       pwms = <&pwm0 5000000>;
+       ...
+}
diff --git a/Documentation/devicetree/bindings/video/ssd1289fb.txt b/Documentation/devicetree/bindings/video/ssd1289fb.txt
new file mode 100644 (file)
index 0000000..4fcd5e6
--- /dev/null
@@ -0,0 +1,13 @@
+* Solomon SSD1289 Framebuffer Driver
+
+Required properties:
+  - compatible: Should be "solomon,ssd1289fb". The only supported bus for
+    now is lbc.
+  - reg: Should contain address of the controller on the LBC bus. The detail
+    was described in Documentation/devicetree/bindings/powerpc/fsl/lbc.txt
+
+Examples:
+display@2,0 {
+       compatible = "solomon,ssd1289fb";
+       reg = <0x2 0x0000 0x0004>;
+};
index 7cbfa3c4fc3d327c8b1d9c3ef8a4c1228998a69b..d7e43fa88575b1845a38b9471eba70910d67d344 100644 (file)
@@ -73,6 +73,7 @@ Code  Seq#(hex)       Include File            Comments
 0x09   all     linux/raid/md_u.h
 0x10   00-0F   drivers/char/s390/vmcp.h
 0x10   10-1F   arch/s390/include/uapi/sclp_ctl.h
+0x10   20-2F   arch/s390/include/uapi/asm/hypfs.h
 0x12   all     linux/fs.h
                linux/blkpg.h
 0x1b   all     InfiniBand Subsystem    <http://infiniband.sourceforge.net/>
index be6ba33d4ff1ae85bc6bad162e5f9d6a210bbc32..8f441dab03963624c0f32eb8f030c2b3c9a38f9d 100644 (file)
@@ -3124,7 +3124,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        controller if no parameter or 1 is given or disable
                        it if 0 is given (See Documentation/cgroups/memory.txt)
 
-       swiotlb=        [IA-64] Number of I/O TLB slabs
+       swiotlb=        [ARM,IA-64,PPC,MIPS,X86]
+                       Format: { <int> | force }
+                       <int> -- Number of I/O TLB slabs
+                       force -- force using of bounce buffers even if they
+                                wouldn't be automatically used by the kernel
 
        switches=       [HW,M68k]
 
diff --git a/Documentation/kmsg/s390/zcrypt b/Documentation/kmsg/s390/zcrypt
deleted file mode 100644 (file)
index 7fb2087..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*?
- * Text: "Cryptographic device %x failed and was set offline\n"
- * Severity: Error
- * Parameter:
- *   @1: device index
- * Description:
- * A cryptographic device failed to process a cryptographic request.
- * The cryptographic device driver could not correct the error and
- * set the device offline. The application that issued the
- * request received an indication that the request has failed.
- * User action:
- * Use the lszcrypt command to confirm that the cryptographic
- * hardware is still configured to your LPAR or z/VM guest virtual
- * machine. If the device is available to your Linux instance the
- * command output contains a line that begins with 'card<device index>',
- * where <device index> is the two-digit decimal number in the message text.
- * After ensuring that the device is available, use the chzcrypt command to
- * set it online again.
- * If the error persists, contact your support organization.
- */
index 82713ff92eb3e5c72a82ff6f1dc9d637e7f04376..bcea12a0c5847e12211a14d43f356d0f1a1e77f0 100644 (file)
@@ -73,6 +73,10 @@ select_engine : Select which engine is used for running program
 run_engine    : Start program which is loaded via the firmware interface
 firmware      : Load program data
 
+In case of LP5523, one more command is required, 'enginex_leds'.
+It is used for selecting LED output(s) at each engine number.
+In more details, please refer to 'leds-lp5523.txt'.
+
 For example, run blinking pattern in engine #1 of LP5521
 echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp5521/loading
@@ -81,10 +85,12 @@ echo 0 > /sys/class/firmware/lp5521/loading
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 For example, run blinking pattern in engine #3 of LP55231
+Two LEDs are configured as pattern output channels.
 echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp55231/loading
 echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data
 echo 0 > /sys/class/firmware/lp55231/loading
+echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 To start blinking patterns in engine #2 and #3 simultaneously,
@@ -99,17 +105,19 @@ done
 echo 1 > /sys/class/leds/red/device/run_engine
 
 Here is another example for LP5523.
+Full LED strings are selected by 'engine2_leds'.
 echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
 echo 1 > /sys/class/firmware/lp5523/loading
 echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data
 echo 0 > /sys/class/firmware/lp5523/loading
+echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds
 echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
 
 As soon as 'loading' is set to 0, registered callback is called.
 Inside the callback, the selected engine is loaded and memory is updated.
 To run programmed pattern, 'run_engine' attribute should be enabled.
 
-The pattern sqeuence of LP8501 is same as LP5523.
+The pattern sqeuence of LP8501 is similar to LP5523.
 However pattern data is specific.
 Ex 1) Engine 1 is used
 echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
diff --git a/Documentation/mtd/nand/pxa3xx-nand.txt b/Documentation/mtd/nand/pxa3xx-nand.txt
new file mode 100644 (file)
index 0000000..840fd41
--- /dev/null
@@ -0,0 +1,113 @@
+
+About this document
+===================
+
+Some notes about Marvell's NAND controller available in PXA and Armada 370/XP
+SoC (aka NFCv1 and NFCv2), with an emphasis on the latter.
+
+NFCv2 controller background
+===========================
+
+The controller has a 2176 bytes FIFO buffer. Therefore, in order to support
+larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of
+chunked transfers.
+
+For instance, if we choose a 2048 data chunk and set "BCH" ECC (see below)
+we'll have this layout in the pages:
+
+  ------------------------------------------------------------------------------
+  | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... |
+  ------------------------------------------------------------------------------
+
+The driver reads the data and spare portions independently and builds an internal
+buffer with this layout (in the 4 KiB page case):
+
+  ------------------------------------------
+  |     4096B data     |     64B spare     |
+  ------------------------------------------
+
+Also, for the READOOB command the driver disables the ECC and reads a 'spare + ECC'
+OOB, one per chunk read.
+
+  -------------------------------------------------------------------
+  |     4096B data     |  32B spare | 30B ECC | 32B spare | 30B ECC |
+  -------------------------------------------------------------------
+
+So, in order to achieve reading (for instance), we issue several READ0 commands
+(with some additional controller-specific magic) and read two chunks of 2080B
+(2048 data + 32 spare) each.
+The driver accommodates this data to expose the NAND core a contiguous buffer
+(4096 data + spare) or (4096 + spare + ECC + spare + ECC).
+
+ECC
+===
+
+The controller has built-in hardware ECC capabilities. In addition it is
+configurable between two modes: 1) Hamming, 2) BCH.
+
+Note that the actual BCH mode: BCH-4 or BCH-8 will depend on the way
+the controller is configured to transfer the data.
+
+In the BCH mode the ECC code will be calculated for each transfered chunk
+and expected to be located (when reading/programming) right after the spare
+bytes as the figure above shows.
+
+So, repeating the above scheme, a 2048B data chunk will be followed by 32B
+spare, and then the ECC controller will read/write the ECC code (30B in
+this case):
+
+  ------------------------------------
+  | 2048B data | 32B spare | 30B ECC |
+  ------------------------------------
+
+If the ECC mode is 'BCH' then the ECC is *always* 30 bytes long.
+If the ECC mode is 'Hamming' the ECC is 6 bytes long, for each 512B block.
+So in Hamming mode, a 2048B page will have a 24B ECC.
+
+Despite all of the above, the controller requires the driver to only read or
+write in multiples of 8-bytes, because the data buffer is 64-bits.
+
+OOB
+===
+
+Because of the above scheme, and because the "spare" OOB is really located in
+the middle of a page, spare OOB cannot be read or write independently of the
+data area. In other words, in order to read the OOB (aka READOOB), the entire
+page (aka READ0) has to be read.
+
+In the same sense, in order to write to the spare OOB the driver has to write
+an *entire* page.
+
+Factory bad blocks handling
+===========================
+
+Given the ECC BCH requires to layout the device's pages in a split
+data/OOB/data/OOB way, the controller has a view of the flash page that's
+different from the specified (aka the manufacturer's) view. In other words,
+
+Factory view:
+
+  -----------------------------------------------
+  |                    Data           |x  OOB   |
+  -----------------------------------------------
+
+Driver's view:
+
+  -----------------------------------------------
+  |      Data      | OOB |      Data   x  | OOB |
+  -----------------------------------------------
+
+It can be seen from the above, that the factory bad block marker must be
+searched within the 'data' region, and not in the usual OOB region.
+
+In addition, this means under regular usage the driver will write such
+position (since it belongs to the data region) and every used block is
+likely to be marked as bad.
+
+For this reason, marking the block as bad in the OOB is explicitly
+disabled by using the NAND_BBT_NO_OOB_BBM option in the driver. The rationale
+for this is that there's no point in marking a block as bad, because good
+blocks are also 'marked as bad' (in the OOB BBM sense) under normal usage.
+
+Instead, the driver relies on the bad block table alone, and should only perform
+the bad block scan on the very first time (when the device hasn't been used).
index e9b54de8fdf7509e7d2cf2d3ec73deca5cf6f2e3..edeecd447d23dc8ff26e66debe0d874b9482f087 100644 (file)
@@ -172,7 +172,7 @@ you can boot the kernel with the 'no_console_suspend' parameter and try to log
 kernel messages using the serial console.  This may provide you with some
 information about the reasons of the suspend (resume) failure.  Alternatively,
 it may be possible to use a FireWire port for debugging with firescope
-(ftp://ftp.firstfloor.org/pub/ak/firescope/).  On x86 it is also possible to
+(http://v3.sk/~lkundrak/firescope/).  On x86 it is also possible to
 use the PM_TRACE mechanism documented in Documentation/power/s2ram.txt .
 
 2. Testing suspend to RAM (STR)
index 9f5481bdc5a43f942fb833f3131901249d2d5c50..d614a9b6a28048ecf879e96b3aada686ecadb6cb 100644 (file)
@@ -696,7 +696,9 @@ swappiness
 
 This control is used to define how aggressive the kernel will swap
 memory pages.  Higher values will increase agressiveness, lower values
-decrease the amount of swap.
+decrease the amount of swap.  A value of 0 instructs the kernel not to
+initiate swap until the amount of free and file-backed pages is less
+than the high water mark in a zone.
 
 The default value is 60.
 
index 2507f38b208f7a6773d31a8f0921c9cc8c4210a8..38b81df6701c1d744ce14efbe301f6d16c2257ee 100644 (file)
@@ -309,36 +309,36 @@ F:        sound/pci/ad1889.*
 
 AD525X ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/AD5254
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/misc/ad525x_dpot.c
 
 AD5398 CURRENT REGULATOR DRIVER (AD5398/AD5821)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/AD5398
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/regulator/ad5398.c
 
 AD714X CAPACITANCE TOUCH SENSOR DRIVER (AD7142/3/7/8/7A)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/AD7142
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/input/misc/ad714x.c
 
 AD7877 TOUCHSCREEN DRIVER
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/AD7877
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/input/touchscreen/ad7877.c
 
 AD7879 TOUCHSCREEN DRIVER (AD7879/AD7889)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/AD7879
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/input/touchscreen/ad7879.c
 
@@ -374,8 +374,8 @@ F:  include/media/adp1653.h
 
 ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/ADP5520
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/mfd/adp5520.c
 F:     drivers/video/backlight/adp5520_bl.c
@@ -385,16 +385,16 @@ F:        drivers/input/keyboard/adp5520-keys.c
 
 ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/ADP5588
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/input/keyboard/adp5588-keys.c
 F:     drivers/gpio/gpio-adp5588.c
 
 ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/ADP8860
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/video/backlight/adp8860_bl.c
 
@@ -420,8 +420,8 @@ F:  drivers/hwmon/adt7475.c
 
 ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
 M:     Michael Hennerich <michael.hennerich@analog.com>
-L:     device-drivers-devel@blackfin.uclinux.org
 W:     http://wiki.analog.com/ADXL345
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     drivers/input/misc/adxl34x.c
 
@@ -627,9 +627,9 @@ F:  drivers/media/i2c/adv7842*
 
 ANALOG DEVICES INC ASOC CODEC DRIVERS
 M:     Lars-Peter Clausen <lars@metafoo.de>
-L:     device-drivers-devel@blackfin.uclinux.org
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://wiki.analog.com/
+W:     http://ez.analog.com/community/linux-device-drivers
 S:     Supported
 F:     sound/soc/codecs/adau*
 F:     sound/soc/codecs/adav*
@@ -639,7 +639,7 @@ F:  sound/soc/codecs/ssm*
 F:     sound/soc/codecs/sigmadsp.*
 
 ANALOG DEVICES INC ASOC DRIVERS
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://blackfin.uclinux.org/
 S:     Supported
@@ -1742,56 +1742,54 @@ F:      fs/bfs/
 F:     include/uapi/linux/bfs_fs.h
 
 BLACKFIN ARCHITECTURE
-M:     Mike Frysinger <vapier@gentoo.org>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+M:     Steven Miao <realmz6@gmail.com>
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     arch/blackfin/
 
 BLACKFIN EMAC DRIVER
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/net/ethernet/adi/
 
 BLACKFIN RTC DRIVER
-M:     Mike Frysinger <vapier.adi@gmail.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/rtc/rtc-bfin.c
 
 BLACKFIN SDH DRIVER
 M:     Sonic Zhang <sonic.zhang@analog.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/mmc/host/bfin_sdh.c
 
 BLACKFIN SERIAL DRIVER
 M:     Sonic Zhang <sonic.zhang@analog.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/tty/serial/bfin_uart.c
 
 BLACKFIN WATCHDOG DRIVER
-M:     Mike Frysinger <vapier.adi@gmail.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/watchdog/bfin_wdt.c
 
 BLACKFIN I2C TWI DRIVER
 M:     Sonic Zhang <sonic.zhang@analog.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org/
 S:     Supported
 F:     drivers/i2c/busses/i2c-bfin-twi.c
 
 BLACKFIN MEDIA DRIVER
 M:     Scott Jiang <scott.jiang.linux@gmail.com>
-L:     uclinux-dist-devel@blackfin.uclinux.org
+L:     adi-buildroot-devel@lists.sourceforge.net
 W:     http://blackfin.uclinux.org/
 S:     Supported
 F:     drivers/media/platform/blackfin/
@@ -5622,10 +5620,11 @@ F:      mm/page_cgroup.c
 
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:     David Woodhouse <dwmw2@infradead.org>
+M:     Brian Norris <computersforpeace@gmail.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
-T:     git git://git.infradead.org/mtd-2.6.git
+T:     git git://git.infradead.org/linux-mtd.git
 S:     Maintained
 F:     drivers/mtd/
 F:     include/linux/mtd/
@@ -6942,6 +6941,12 @@ F:       include/sound/pxa2xx-lib.h
 F:     sound/arm/pxa*
 F:     sound/soc/pxa/
 
+PXA3xx NAND FLASH DRIVER
+M:     Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+F:     drivers/mtd/nand/pxa3xx-nand.c
+
 MMP SUPPORT
 M:     Eric Miao <eric.y.miao@gmail.com>
 M:     Haojian Zhuang <haojian.zhuang@gmail.com>
@@ -7075,7 +7080,7 @@ F:        drivers/media/parport/*-qcam*
 RADOS BLOCK DEVICE (RBD)
 M:     Yehuda Sadeh <yehuda@inktank.com>
 M:     Sage Weil <sage@inktank.com>
-M:     Alex Elder <elder@inktank.com>
+M:     Alex Elder <elder@kernel.org>
 M:     ceph-devel@vger.kernel.org
 W:     http://ceph.com/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
diff --git a/arch/arm/boot/dts/am33xx-clocks.dtsi b/arch/arm/boot/dts/am33xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..9ccfe50
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * Device Tree Source for AM33xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&scrm_clocks {
+       sys_clkin_ck: sys_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+               ti,bit-shift = <22>;
+               reg = <0x0040>;
+       };
+
+       adc_tsc_fck: adc_tsc_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dcan0_fck: dcan0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dcan1_fck: dcan1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       smartreflex0_fck: smartreflex0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       smartreflex1_fck: smartreflex1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sha0_fck: sha0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       aes0_fck: aes0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       rng_fck: rng_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       ehrpwm0_gate_tbclk: ehrpwm0_gate_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_per_m2_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x0664>;
+       };
+
+       ehrpwm0_tbclk: ehrpwm0_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&ehrpwm0_gate_tbclk>;
+       };
+
+       ehrpwm1_gate_tbclk: ehrpwm1_gate_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_per_m2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0664>;
+       };
+
+       ehrpwm1_tbclk: ehrpwm1_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&ehrpwm1_gate_tbclk>;
+       };
+
+       ehrpwm2_gate_tbclk: ehrpwm2_gate_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_per_m2_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0664>;
+       };
+
+       ehrpwm2_tbclk: ehrpwm2_tbclk {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&ehrpwm2_gate_tbclk>;
+       };
+};
+&prcm_clocks {
+       clk_32768_ck: clk_32768_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       clk_rc32k_ck: clk_rc32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32000>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_24000000_ck: virt_24000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+       };
+
+       virt_25000000_ck: virt_25000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <25000000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       tclkin_ck: tclkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       dpll_core_ck: dpll_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-core-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x0490>, <0x045c>, <0x0468>;
+       };
+
+       dpll_core_x2_ck: dpll_core_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-x2-clock";
+               clocks = <&dpll_core_ck>;
+       };
+
+       dpll_core_m4_ck: dpll_core_m4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0480>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_core_m5_ck: dpll_core_m5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0484>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_core_m6_ck: dpll_core_m6_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x04d8>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_mpu_ck: dpll_mpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x0488>, <0x0420>, <0x042c>;
+       };
+
+       dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_mpu_ck>;
+               ti,max-div = <31>;
+               reg = <0x04a8>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_ddr_ck: dpll_ddr_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-no-gate-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x0494>, <0x0434>, <0x0440>;
+       };
+
+       dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_ck>;
+               ti,max-div = <31>;
+               reg = <0x04a0>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_ddr_m2_div2_ck: dpll_ddr_m2_div2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_ddr_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       dpll_disp_ck: dpll_disp_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-no-gate-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x0498>, <0x0448>, <0x0454>;
+       };
+
+       dpll_disp_m2_ck: dpll_disp_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_disp_ck>;
+               ti,max-div = <31>;
+               reg = <0x04a4>;
+               ti,index-starts-at-one;
+               ti,set-rate-parent;
+       };
+
+       dpll_per_ck: dpll_per_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-no-gate-j-type-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x048c>, <0x0470>, <0x049c>;
+       };
+
+       dpll_per_m2_ck: dpll_per_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_ck>;
+               ti,max-div = <31>;
+               reg = <0x04ac>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       dpll_per_m2_div4_ck: dpll_per_m2_div4_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       cefuse_fck: cefuse_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_clkin_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0a20>;
+       };
+
+       clk_24mhz: clk_24mhz {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       clkdiv32k_ck: clkdiv32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&clk_24mhz>;
+               clock-mult = <1>;
+               clock-div = <732>;
+       };
+
+       clkdiv32k_ick: clkdiv32k_ick {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x014c>;
+       };
+
+       l3_gclk: l3_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       pruss_ocp_gclk: pruss_ocp_gclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3_gclk>, <&dpll_disp_m2_ck>;
+               reg = <0x0530>;
+       };
+
+       mmu_fck: mmu_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_core_m4_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0914>;
+       };
+
+       timer1_fck: timer1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>;
+               reg = <0x0528>;
+       };
+
+       timer2_fck: timer2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x0508>;
+       };
+
+       timer3_fck: timer3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x050c>;
+       };
+
+       timer4_fck: timer4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x0510>;
+       };
+
+       timer5_fck: timer5_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x0518>;
+       };
+
+       timer6_fck: timer6_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x051c>;
+       };
+
+       timer7_fck: timer7_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x0504>;
+       };
+
+       usbotg_fck: usbotg_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_per_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x047c>;
+       };
+
+       dpll_core_m4_div2_ck: dpll_core_m4_div2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       ieee5000_fck: ieee5000_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x00e4>;
+       };
+
+       wdt1_fck: wdt1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
+               reg = <0x0538>;
+       };
+
+       l4_rtc_gclk: l4_rtc_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       l4hs_gclk: l4hs_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l3s_gclk: l3s_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4fw_gclk: l4fw_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4ls_gclk: l4ls_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sysclk_div_ck: sysclk_div_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       cpsw_125mhz_gclk: cpsw_125mhz_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m5_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>;
+               reg = <0x0520>;
+       };
+
+       gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>;
+               reg = <0x053c>;
+       };
+
+       gpio0_dbclk: gpio0_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&gpio0_dbclk_mux_ck>;
+               ti,bit-shift = <18>;
+               reg = <0x0408>;
+       };
+
+       gpio1_dbclk: gpio1_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <18>;
+               reg = <0x00ac>;
+       };
+
+       gpio2_dbclk: gpio2_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <18>;
+               reg = <0x00b0>;
+       };
+
+       gpio3_dbclk: gpio3_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <18>;
+               reg = <0x00b4>;
+       };
+
+       lcd_gclk: lcd_gclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
+               reg = <0x0534>;
+               ti,set-rate-parent;
+       };
+
+       mmc_clk: mmc_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x052c>;
+       };
+
+       gfx_fck_div_ck: gfx_fck_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&gfx_fclk_clksel_ck>;
+               reg = <0x052c>;
+               ti,max-div = <2>;
+       };
+
+       sysclkout_pre_ck: sysclkout_pre_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>;
+               reg = <0x0700>;
+       };
+
+       clkout2_div_ck: clkout2_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sysclkout_pre_ck>;
+               ti,bit-shift = <3>;
+               ti,max-div = <8>;
+               reg = <0x0700>;
+       };
+
+       dbg_sysclk_ck: dbg_sysclk_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_clkin_ck>;
+               ti,bit-shift = <19>;
+               reg = <0x0414>;
+       };
+
+       dbg_clka_ck: dbg_clka_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_core_m4_ck>;
+               ti,bit-shift = <30>;
+               reg = <0x0414>;
+       };
+
+       stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
+               ti,bit-shift = <22>;
+               reg = <0x0414>;
+       };
+
+       trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
+               ti,bit-shift = <20>;
+               reg = <0x0414>;
+       };
+
+       stm_clk_div_ck: stm_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&stm_pmd_clock_mux_ck>;
+               ti,bit-shift = <27>;
+               ti,max-div = <64>;
+               reg = <0x0414>;
+               ti,index-power-of-two;
+       };
+
+       trace_clk_div_ck: trace_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&trace_pmd_clk_mux_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <64>;
+               reg = <0x0414>;
+               ti,index-power-of-two;
+       };
+
+       clkout2_ck: clkout2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkout2_div_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x0700>;
+       };
+};
+
+&prcm_clockdomains {
+       clk_24mhz_clkdm: clk_24mhz_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&clkdiv32k_ick>;
+       };
+};
index f6d8ffe98d0bfa15bc516b8fde2847f3568fcdd2..6d95d3df33c7913dc0feb76598f6e94ea15cf0fa 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               prcm: prcm@44e00000 {
+                       compatible = "ti,am3-prcm";
+                       reg = <0x44e00000 0x4000>;
+
+                       prcm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prcm_clockdomains: clockdomains {
+                       };
+               };
+
+               scrm: scrm@44e10000 {
+                       compatible = "ti,am3-scrm";
+                       reg = <0x44e10000 0x2000>;
+
+                       scrm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       scrm_clockdomains: clockdomains {
+                       };
+               };
+
                intc: interrupt-controller@48200000 {
                        compatible = "ti,omap2-intc";
                        interrupt-controller;
                };
        };
 };
+
+/include/ "am33xx-clocks.dtsi"
index 2fbe02faa8b18f2b18dd0e8bedff0256db4ff501..788391f916844130d8d6cdb2722479163863a707 100644 (file)
@@ -61,3 +61,6 @@
                };
        };
 };
+
+/include/ "am35xx-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/boot/dts/am35xx-clocks.dtsi b/arch/arm/boot/dts/am35xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..df489d3
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&scrm_clocks {
+       emac_ick: emac_ick {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x059c>;
+               ti,bit-shift = <1>;
+       };
+
+       emac_fck: emac_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&rmii_ck>;
+               reg = <0x059c>;
+               ti,bit-shift = <9>;
+       };
+
+       vpfe_ick: vpfe_ick {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x059c>;
+               ti,bit-shift = <2>;
+       };
+
+       vpfe_fck: vpfe_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pclk_ck>;
+               reg = <0x059c>;
+               ti,bit-shift = <10>;
+       };
+
+       hsotgusb_ick_am35xx: hsotgusb_ick_am35xx {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&ipss_ick>;
+               reg = <0x059c>;
+               ti,bit-shift = <0>;
+       };
+
+       hsotgusb_fck_am35xx: hsotgusb_fck_am35xx {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x059c>;
+               ti,bit-shift = <8>;
+       };
+
+       hecc_ck: hecc_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x059c>;
+               ti,bit-shift = <3>;
+       };
+};
+&cm_clocks {
+       ipss_ick: ipss_ick {
+               #clock-cells = <0>;
+               compatible = "ti,am35xx-interface-clock";
+               clocks = <&core_l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <4>;
+       };
+
+       rmii_ck: rmii_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <50000000>;
+       };
+
+       pclk_ck: pclk_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <27000000>;
+       };
+
+       uart4_ick_am35xx: uart4_ick_am35xx {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <23>;
+       };
+
+       uart4_fck_am35xx: uart4_fck_am35xx {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <23>;
+       };
+};
+
+&cm_clockdomains {
+       core_l3_clkdm: core_l3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>,
+                        <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>,
+                        <&hecc_ck>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+                        <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+                        <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+                        <&uart4_ick_am35xx>, <&uart4_fck_am35xx>;
+       };
+};
index 974d103ab3b1e673fe255e28e5c13d8544ad2565..c6bd4d986c290aaeb7bd4e0f78e2d48489c2bee4 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               prcm: prcm@44df0000 {
+                       compatible = "ti,am4-prcm";
+                       reg = <0x44df0000 0x11000>;
+
+                       prcm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prcm_clockdomains: clockdomains {
+                       };
+               };
+
+               scrm: scrm@44e10000 {
+                       compatible = "ti,am4-scrm";
+                       reg = <0x44e10000 0x2000>;
+
+                       scrm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       scrm_clockdomains: clockdomains {
+                       };
+               };
+
                edma: edma@49000000 {
                        compatible = "ti,edma3";
                        ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
                };
        };
 };
+
+/include/ "am43xx-clocks.dtsi"
diff --git a/arch/arm/boot/dts/am43xx-clocks.dtsi b/arch/arm/boot/dts/am43xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..142009c
--- /dev/null
@@ -0,0 +1,656 @@
+/*
+ * Device Tree Source for AM43xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&scrm_clocks {
+       sys_clkin_ck: sys_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
+               ti,bit-shift = <22>;
+               reg = <0x0040>;
+       };
+
+       adc_tsc_fck: adc_tsc_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dcan0_fck: dcan0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dcan1_fck: dcan1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mcasp0_fck: mcasp0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mcasp1_fck: mcasp1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       smartreflex0_fck: smartreflex0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       smartreflex1_fck: smartreflex1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sha0_fck: sha0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       aes0_fck: aes0_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+};
+&prcm_clocks {
+       clk_32768_ck: clk_32768_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       clk_rc32k_ck: clk_rc32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_24000000_ck: virt_24000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+       };
+
+       virt_25000000_ck: virt_25000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <25000000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       tclkin_ck: tclkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       dpll_core_ck: dpll_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-core-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2d20>, <0x2d24>, <0x2d2c>;
+       };
+
+       dpll_core_x2_ck: dpll_core_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-x2-clock";
+               clocks = <&dpll_core_ck>;
+       };
+
+       dpll_core_m4_ck: dpll_core_m4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2d38>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m5_ck: dpll_core_m5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2d3c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m6_ck: dpll_core_m6_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2d40>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_mpu_ck: dpll_mpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2d60>, <0x2d64>, <0x2d6c>;
+       };
+
+       dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_mpu_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2d70>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_ddr_ck: dpll_ddr_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2da0>, <0x2da4>, <0x2dac>;
+       };
+
+       dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2db0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_disp_ck: dpll_disp_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2e20>, <0x2e24>, <0x2e2c>;
+       };
+
+       dpll_disp_m2_ck: dpll_disp_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_disp_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2e30>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_ck: dpll_per_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-j-type-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2de0>, <0x2de4>, <0x2dec>;
+       };
+
+       dpll_per_m2_ck: dpll_per_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2df0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       dpll_per_m2_div4_ck: dpll_per_m2_div4_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       clk_24mhz: clk_24mhz {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       clkdiv32k_ck: clkdiv32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&clk_24mhz>;
+               clock-mult = <1>;
+               clock-div = <732>;
+       };
+
+       clkdiv32k_ick: clkdiv32k_ick {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x2a38>;
+       };
+
+       sysclk_div: sysclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       pruss_ocp_gclk: pruss_ocp_gclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sysclk_div>, <&dpll_disp_m2_ck>;
+               reg = <0x4248>;
+       };
+
+       clk_32k_tpm_ck: clk_32k_tpm_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       timer1_fck: timer1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>;
+               reg = <0x4200>;
+       };
+
+       timer2_fck: timer2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x4204>;
+       };
+
+       timer3_fck: timer3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x4208>;
+       };
+
+       timer4_fck: timer4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x420c>;
+       };
+
+       timer5_fck: timer5_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x4210>;
+       };
+
+       timer6_fck: timer6_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x4214>;
+       };
+
+       timer7_fck: timer7_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
+               reg = <0x4218>;
+       };
+
+       wdt1_fck: wdt1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
+               reg = <0x422c>;
+       };
+
+       l3_gclk: l3_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_core_m4_div2_ck: dpll_core_m4_div2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sysclk_div>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       l4hs_gclk: l4hs_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l3s_gclk: l3s_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4ls_gclk: l4ls_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4_div2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       cpsw_125mhz_gclk: cpsw_125mhz_gclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m5_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>;
+               reg = <0x4238>;
+       };
+
+       clk_32k_mosc_ck: clk_32k_mosc_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>;
+               reg = <0x4240>;
+       };
+
+       gpio0_dbclk: gpio0_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&gpio0_dbclk_mux_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x2b68>;
+       };
+
+       gpio1_dbclk: gpio1_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <8>;
+               reg = <0x8c78>;
+       };
+
+       gpio2_dbclk: gpio2_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <8>;
+               reg = <0x8c80>;
+       };
+
+       gpio3_dbclk: gpio3_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <8>;
+               reg = <0x8c88>;
+       };
+
+       gpio4_dbclk: gpio4_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <8>;
+               reg = <0x8c90>;
+       };
+
+       gpio5_dbclk: gpio5_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkdiv32k_ick>;
+               ti,bit-shift = <8>;
+               reg = <0x8c98>;
+       };
+
+       mmc_clk: mmc_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sysclk_div>, <&dpll_per_m2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x423c>;
+       };
+
+       gfx_fck_div_ck: gfx_fck_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&gfx_fclk_clksel_ck>;
+               reg = <0x423c>;
+               ti,max-div = <2>;
+       };
+
+       disp_clk: disp_clk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
+               reg = <0x4244>;
+       };
+
+       dpll_extdev_ck: dpll_extdev_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
+               reg = <0x2e60>, <0x2e64>, <0x2e6c>;
+       };
+
+       dpll_extdev_m2_ck: dpll_extdev_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_extdev_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2e70>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       mux_synctimer32k_ck: mux_synctimer32k_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>;
+               reg = <0x4230>;
+       };
+
+       synctimer_32kclk: synctimer_32kclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&mux_synctimer32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x2a30>;
+       };
+
+       timer8_fck: timer8_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+               reg = <0x421c>;
+       };
+
+       timer9_fck: timer9_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+               reg = <0x4220>;
+       };
+
+       timer10_fck: timer10_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+               reg = <0x4224>;
+       };
+
+       timer11_fck: timer11_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
+               reg = <0x4228>;
+       };
+
+       cpsw_50m_clkdiv: cpsw_50m_clkdiv {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m5_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       cpsw_5m_clkdiv: cpsw_5m_clkdiv {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&cpsw_50m_clkdiv>;
+               clock-mult = <1>;
+               clock-div = <10>;
+       };
+
+       dpll_ddr_x2_ck: dpll_ddr_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,am3-dpll-x2-clock";
+               clocks = <&dpll_ddr_ck>;
+       };
+
+       dpll_ddr_m4_ck: dpll_ddr_m4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x2db8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_clkdcoldo: dpll_per_clkdcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dll_aging_clk_div: dll_aging_clk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin_ck>;
+               reg = <0x4250>;
+               ti,dividers = <8>, <16>, <32>;
+       };
+
+       div_core_25m_ck: div_core_25m_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sysclk_div>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       func_12m_clk: func_12m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       vtp_clk_div: vtp_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       usbphy_32khz_clkmux: usbphy_32khz_clkmux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>;
+               reg = <0x4260>;
+       };
+};
index d0df4c4e8b0a1bd422f33015a51656d8c063b5d9..1fd75aa4639da23c8e1b05bd1c5e28730f01c791 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+               prm: prm@4ae06000 {
+                       compatible = "ti,dra7-prm";
+                       reg = <0x4ae06000 0x3000>;
+
+                       prm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prm_clockdomains: clockdomains {
+                       };
+               };
+
+               cm_core_aon: cm_core_aon@4a005000 {
+                       compatible = "ti,dra7-cm-core-aon";
+                       reg = <0x4a005000 0x2000>;
+
+                       cm_core_aon_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm_core_aon_clockdomains: clockdomains {
+                       };
+               };
+
+               cm_core: cm_core@4a008000 {
+                       compatible = "ti,dra7-cm-core";
+                       reg = <0x4a008000 0x3000>;
+
+                       cm_core_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm_core_clockdomains: clockdomains {
+                       };
+               };
+
                counter32k: counter@4ae04000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x4ae04000 0x40>;
                };
        };
 };
+
+/include/ "dra7xx-clocks.dtsi"
diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..e96da9a
--- /dev/null
@@ -0,0 +1,2015 @@
+/*
+ * Device Tree Source for DRA7xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_core_aon_clocks {
+       atl_clkin0_ck: atl_clkin0_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       atl_clkin1_ck: atl_clkin1_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       atl_clkin2_ck: atl_clkin2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       atlclkin3_ck: atlclkin3_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       hdmi_clkin_ck: hdmi_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       mlb_clkin_ck: mlb_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       mlbp_clkin_ck: mlbp_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       pciesref_acs_clk_ck: pciesref_acs_clk_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <100000000>;
+       };
+
+       ref_clkin0_ck: ref_clkin0_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       ref_clkin1_ck: ref_clkin1_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       ref_clkin2_ck: ref_clkin2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       ref_clkin3_ck: ref_clkin3_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       rmii_clk_ck: rmii_clk_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       sdvenc_clkin_ck: sdvenc_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       secure_32k_clk_src_ck: secure_32k_clk_src_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       sys_32k_ck: sys_32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       virt_12000000_ck: virt_12000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       virt_13000000_ck: virt_13000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <13000000>;
+       };
+
+       virt_16800000_ck: virt_16800000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16800000>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_20000000_ck: virt_20000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <20000000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       virt_27000000_ck: virt_27000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <27000000>;
+       };
+
+       virt_38400000_ck: virt_38400000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <38400000>;
+       };
+
+       sys_clkin2: sys_clkin2 {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <22579200>;
+       };
+
+       usb_otg_clkin_ck: usb_otg_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       video1_clkin_ck: video1_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       video1_m2_clkin_ck: video1_m2_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       video2_clkin_ck: video2_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       video2_m2_clkin_ck: video2_m2_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       dpll_abe_ck: dpll_abe_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-m4xen-clock";
+               clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
+               reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
+       };
+
+       dpll_abe_x2_ck: dpll_abe_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_abe_ck>;
+       };
+
+       dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       abe_clk: abe_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               ti,max-div = <4>;
+               reg = <0x0108>;
+               ti,index-power-of-two;
+       };
+
+       dpll_abe_m2_ck: dpll_abe_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f4>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_ck: dpll_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-core-clock";
+               clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+               reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>;
+       };
+
+       dpll_core_x2_ck: dpll_core_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_core_ck>;
+       };
+
+       dpll_core_h12x2_ck: dpll_core_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x013c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       mpu_dpll_hs_clk_div: mpu_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_mpu_ck: dpll_mpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>;
+               reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
+       };
+
+       dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_mpu_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0170>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       mpu_dclk_div: mpu_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_mpu_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dsp_dpll_hs_clk_div: dsp_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_dsp_ck: dpll_dsp_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>;
+               reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>;
+       };
+
+       dpll_dsp_m2_ck: dpll_dsp_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_dsp_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0244>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       iva_dpll_hs_clk_div: iva_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_iva_ck: dpll_iva_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>;
+               reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>;
+       };
+
+       dpll_iva_m2_ck: dpll_iva_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_iva_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       iva_dclk: iva_dclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_iva_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_gpu_ck: dpll_gpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+               reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>;
+       };
+
+       dpll_gpu_m2_ck: dpll_gpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gpu_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02e8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m2_ck: dpll_core_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0130>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       core_dpll_out_dclk_div: core_dpll_out_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_ddr_ck: dpll_ddr_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+               reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>;
+       };
+
+       dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0220>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_gmac_ck: dpll_gmac_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
+               reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>;
+       };
+
+       dpll_gmac_m2_ck: dpll_gmac_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02b8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       video2_dclk_div: video2_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video2_m2_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       video1_dclk_div: video1_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video1_m2_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       hdmi_dclk_div: hdmi_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&hdmi_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       per_dpll_hs_clk_div: per_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       usb_dpll_hs_clk_div: usb_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <3>;
+       };
+
+       eve_dpll_hs_clk_div: eve_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_eve_ck: dpll_eve_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>;
+               reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>;
+       };
+
+       dpll_eve_m2_ck: dpll_eve_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_eve_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0294>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       eve_dclk_div: eve_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_eve_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_core_h13x2_ck: dpll_core_h13x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0140>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h14x2_ck: dpll_core_h14x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0144>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h22x2_ck: dpll_core_h22x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0154>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h23x2_ck: dpll_core_h23x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0158>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h24x2_ck: dpll_core_h24x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x015c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_ddr_x2_ck: dpll_ddr_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_ddr_ck>;
+       };
+
+       dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0228>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_dsp_x2_ck: dpll_dsp_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_dsp_ck>;
+       };
+
+       dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_dsp_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0248>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_gmac_x2_ck: dpll_gmac_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_gmac_ck>;
+       };
+
+       dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02c0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02c4>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02c8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x02bc>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       gmii_m_clk_div: gmii_m_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_gmac_h11x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       hdmi_clk2_div: hdmi_clk2_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&hdmi_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       hdmi_div_clk: hdmi_div_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&hdmi_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l3_iclk_div: l3_iclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4_root_clk_div: l4_root_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l3_iclk_div>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       video1_clk2_div: video1_clk2_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video1_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       video1_div_clk: video1_div_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video1_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       video2_clk2_div: video2_clk2_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video2_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       video2_div_clk: video2_div_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&video2_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       ipu1_gfclk_mux: ipu1_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0520>;
+       };
+
+       mcasp1_ahclkr_mux: mcasp1_ahclkr_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <28>;
+               reg = <0x0550>;
+       };
+
+       mcasp1_ahclkx_mux: mcasp1_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0550>;
+       };
+
+       mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x0550>;
+       };
+
+       timer5_gfclk_mux: timer5_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+               ti,bit-shift = <24>;
+               reg = <0x0558>;
+       };
+
+       timer6_gfclk_mux: timer6_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+               ti,bit-shift = <24>;
+               reg = <0x0560>;
+       };
+
+       timer7_gfclk_mux: timer7_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+               ti,bit-shift = <24>;
+               reg = <0x0568>;
+       };
+
+       timer8_gfclk_mux: timer8_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
+               ti,bit-shift = <24>;
+               reg = <0x0570>;
+       };
+
+       uart6_gfclk_mux: uart6_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0580>;
+       };
+
+       dummy_ck: dummy_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+};
+&prm_clocks {
+       sys_clkin1: sys_clkin1 {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_12000000_ck>, <&virt_20000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+               reg = <0x0110>;
+               ti,index-starts-at-one;
+       };
+
+       abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>;
+               reg = <0x0118>;
+       };
+
+       abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
+               reg = <0x0114>;
+       };
+
+       abe_dpll_clk_mux: abe_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
+               reg = <0x010c>;
+       };
+
+       abe_24m_fclk: abe_24m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               reg = <0x011c>;
+               ti,dividers = <8>, <16>;
+       };
+
+       aess_fclk: aess_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&abe_clk>;
+               reg = <0x0178>;
+               ti,max-div = <2>;
+       };
+
+       abe_giclk_div: abe_giclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&aess_fclk>;
+               reg = <0x0174>;
+               ti,max-div = <2>;
+       };
+
+       abe_lp_clk_div: abe_lp_clk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               reg = <0x01d8>;
+               ti,dividers = <16>, <32>;
+       };
+
+       abe_sys_clk_div: abe_sys_clk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin1>;
+               reg = <0x0120>;
+               ti,max-div = <2>;
+       };
+
+       adc_gfclk_mux: adc_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>, <&sys_32k_ck>;
+               reg = <0x01dc>;
+       };
+
+       sys_clk1_dclk_div: sys_clk1_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin1>;
+               ti,max-div = <64>;
+               reg = <0x01c8>;
+               ti,index-power-of-two;
+       };
+
+       sys_clk2_dclk_div: sys_clk2_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin2>;
+               ti,max-div = <64>;
+               reg = <0x01cc>;
+               ti,index-power-of-two;
+       };
+
+       per_abe_x1_dclk_div: per_abe_x1_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x01bc>;
+               ti,index-power-of-two;
+       };
+
+       dsp_gclk_div: dsp_gclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_dsp_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x018c>;
+               ti,index-power-of-two;
+       };
+
+       gpu_dclk: gpu_dclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gpu_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x01a0>;
+               ti,index-power-of-two;
+       };
+
+       emif_phy_dclk_div: emif_phy_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_ddr_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x0190>;
+               ti,index-power-of-two;
+       };
+
+       gmac_250m_dclk_div: gmac_250m_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x019c>;
+               ti,index-power-of-two;
+       };
+
+       l3init_480m_dclk_div: l3init_480m_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x01ac>;
+               ti,index-power-of-two;
+       };
+
+       usb_otg_dclk_div: usb_otg_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&usb_otg_clkin_ck>;
+               ti,max-div = <64>;
+               reg = <0x0184>;
+               ti,index-power-of-two;
+       };
+
+       sata_dclk_div: sata_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin1>;
+               ti,max-div = <64>;
+               reg = <0x01c0>;
+               ti,index-power-of-two;
+       };
+
+       pcie2_dclk_div: pcie2_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_pcie_ref_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x01b8>;
+               ti,index-power-of-two;
+       };
+
+       pcie_dclk_div: pcie_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&apll_pcie_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x01b4>;
+               ti,index-power-of-two;
+       };
+
+       emu_dclk_div: emu_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin1>;
+               ti,max-div = <64>;
+               reg = <0x0194>;
+               ti,index-power-of-two;
+       };
+
+       secure_32k_dclk_div: secure_32k_dclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&secure_32k_clk_src_ck>;
+               ti,max-div = <64>;
+               reg = <0x01c4>;
+               ti,index-power-of-two;
+       };
+
+       clkoutmux0_clk_mux: clkoutmux0_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+               reg = <0x0158>;
+       };
+
+       clkoutmux1_clk_mux: clkoutmux1_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+               reg = <0x015c>;
+       };
+
+       clkoutmux2_clk_mux: clkoutmux2_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
+               reg = <0x0160>;
+       };
+
+       custefuse_sys_gfclk_div: custefuse_sys_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin1>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       eve_clk: eve_clk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_eve_m2_ck>, <&dpll_dsp_m3x2_ck>;
+               reg = <0x0180>;
+       };
+
+       hdmi_dpll_clk_mux: hdmi_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>;
+               reg = <0x01a4>;
+       };
+
+       mlb_clk: mlb_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mlb_clkin_ck>;
+               ti,max-div = <64>;
+               reg = <0x0134>;
+               ti,index-power-of-two;
+       };
+
+       mlbp_clk: mlbp_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mlbp_clkin_ck>;
+               ti,max-div = <64>;
+               reg = <0x0130>;
+               ti,index-power-of-two;
+       };
+
+       per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2_ck>;
+               ti,max-div = <64>;
+               reg = <0x0138>;
+               ti,index-power-of-two;
+       };
+
+       timer_sys_clk_div: timer_sys_clk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin1>;
+               reg = <0x0144>;
+               ti,max-div = <2>;
+       };
+
+       video1_dpll_clk_mux: video1_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>;
+               reg = <0x01d0>;
+       };
+
+       video2_dpll_clk_mux: video2_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>;
+               reg = <0x01d4>;
+       };
+
+       wkupaon_iclk_mux: wkupaon_iclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&abe_lp_clk_div>;
+               reg = <0x0108>;
+       };
+
+       gpio1_dbclk: gpio1_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1838>;
+       };
+
+       dcan1_sys_clk_mux: dcan1_sys_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin2>;
+               ti,bit-shift = <24>;
+               reg = <0x1888>;
+       };
+
+       timer1_gfclk_mux: timer1_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1840>;
+       };
+
+       uart10_gfclk_mux: uart10_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1880>;
+       };
+};
+&cm_core_clocks {
+       dpll_pcie_ref_ck: dpll_pcie_ref_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&sys_clkin1>;
+               reg = <0x0200>, <0x0204>, <0x020c>, <0x0208>;
+       };
+
+       dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_pcie_ref_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0210>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       apll_pcie_in_clk_mux: apll_pcie_in_clk_mux@4ae06118 {
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_pcie_ref_ck>, <&pciesref_acs_clk_ck>;
+               #clock-cells = <0>;
+               reg = <0x021c 0x4>;
+               ti,bit-shift = <7>;
+       };
+
+       apll_pcie_ck: apll_pcie_ck {
+               #clock-cells = <0>;
+               compatible = "ti,dra7-apll-clock";
+               clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
+               reg = <0x021c>, <0x0220>;
+       };
+
+       optfclk_pciephy_div: optfclk_pciephy_div@4a00821c {
+               compatible = "ti,divider-clock";
+               clocks = <&apll_pcie_ck>;
+               #clock-cells = <0>;
+               reg = <0x021c>;
+               ti,bit-shift = <8>;
+               ti,max-div = <2>;
+       };
+
+       optfclk_pciephy_clk: optfclk_pciephy_clk@4a0093b0 {
+               compatible = "ti,gate-clock";
+               clocks = <&apll_pcie_ck>;
+               #clock-cells = <0>;
+               reg = <0x13b0>;
+               ti,bit-shift = <9>;
+       };
+
+       optfclk_pciephy_div_clk: optfclk_pciephy_div_clk@4a0093b0 {
+               compatible = "ti,gate-clock";
+               clocks = <&optfclk_pciephy_div>;
+               #clock-cells = <0>;
+               reg = <0x13b0>;
+               ti,bit-shift = <10>;
+       };
+
+       apll_pcie_clkvcoldo: apll_pcie_clkvcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&apll_pcie_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       apll_pcie_clkvcoldo_div: apll_pcie_clkvcoldo_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&apll_pcie_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       apll_pcie_m2_ck: apll_pcie_m2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&apll_pcie_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_per_ck: dpll_per_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>;
+               reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>;
+       };
+
+       dpll_per_m2_ck: dpll_per_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       func_96m_aon_dclk_div: func_96m_aon_dclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_usb_ck: dpll_usb_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-j-type-clock";
+               clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>;
+               reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
+       };
+
+       dpll_usb_m2_ck: dpll_usb_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0190>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_pcie_ref_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0210>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_x2_ck: dpll_per_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_per_ck>;
+       };
+
+       dpll_per_h11x2_ck: dpll_per_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0158>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_h12x2_ck: dpll_per_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x015c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_h13x2_ck: dpll_per_h13x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0160>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_h14x2_ck: dpll_per_h14x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0164>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_usb_clkdcoldo: dpll_usb_clkdcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_usb_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       func_128m_clk: func_128m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_h11x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       func_12m_fclk: func_12m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       func_24m_clk: func_24m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_48m_fclk: func_48m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_96m_fclk: func_96m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       l3init_60m_fclk: l3init_60m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               reg = <0x0104>;
+               ti,dividers = <1>, <8>;
+       };
+
+       dss_32khz_clk: dss_32khz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <11>;
+               reg = <0x1120>;
+       };
+
+       dss_48mhz_clk: dss_48mhz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48m_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1120>;
+       };
+
+       dss_dss_clk: dss_dss_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_per_h12x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1120>;
+       };
+
+       dss_hdmi_clk: dss_hdmi_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&hdmi_dpll_clk_mux>;
+               ti,bit-shift = <10>;
+               reg = <0x1120>;
+       };
+
+       dss_video1_clk: dss_video1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&video1_dpll_clk_mux>;
+               ti,bit-shift = <12>;
+               reg = <0x1120>;
+       };
+
+       dss_video2_clk: dss_video2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&video2_dpll_clk_mux>;
+               ti,bit-shift = <13>;
+               reg = <0x1120>;
+       };
+
+       gpio2_dbclk: gpio2_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1760>;
+       };
+
+       gpio3_dbclk: gpio3_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1768>;
+       };
+
+       gpio4_dbclk: gpio4_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1770>;
+       };
+
+       gpio5_dbclk: gpio5_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1778>;
+       };
+
+       gpio6_dbclk: gpio6_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1780>;
+       };
+
+       gpio7_dbclk: gpio7_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1810>;
+       };
+
+       gpio8_dbclk: gpio8_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1818>;
+       };
+
+       mmc1_clk32k: mmc1_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1328>;
+       };
+
+       mmc2_clk32k: mmc2_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1330>;
+       };
+
+       mmc3_clk32k: mmc3_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1820>;
+       };
+
+       mmc4_clk32k: mmc4_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1828>;
+       };
+
+       sata_ref_clk: sata_ref_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_clkin1>;
+               ti,bit-shift = <8>;
+               reg = <0x1388>;
+       };
+
+       usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_clkdcoldo>;
+               ti,bit-shift = <8>;
+               reg = <0x13f0>;
+       };
+
+       usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_clkdcoldo>;
+               ti,bit-shift = <8>;
+               reg = <0x1340>;
+       };
+
+       usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0640>;
+       };
+
+       usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0688>;
+       };
+
+       usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0698>;
+       };
+
+       atl_dpll_clk_mux: atl_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_32k_ck>, <&video1_clkin_ck>, <&video2_clkin_ck>, <&hdmi_clkin_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0c00>;
+       };
+
+       atl_gfclk_mux: atl_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3_iclk_div>, <&dpll_abe_m2_ck>, <&atl_dpll_clk_mux>;
+               ti,bit-shift = <26>;
+               reg = <0x0c00>;
+       };
+
+       gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_m2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x13d0>;
+               ti,dividers = <2>;
+       };
+
+       gmac_rft_clk_mux: gmac_rft_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&video1_clkin_ck>, <&video2_clkin_ck>, <&dpll_abe_m2_ck>, <&hdmi_clkin_ck>, <&l3_iclk_div>;
+               ti,bit-shift = <25>;
+               reg = <0x13d0>;
+       };
+
+       gpu_core_gclk_mux: gpu_core_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1220>;
+       };
+
+       gpu_hyd_gclk_mux: gpu_hyd_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
+               ti,bit-shift = <26>;
+               reg = <0x1220>;
+       };
+
+       l3instr_ts_gclk_div: l3instr_ts_gclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&wkupaon_iclk_mux>;
+               ti,bit-shift = <24>;
+               reg = <0x0e50>;
+               ti,dividers = <8>, <16>, <32>;
+       };
+
+       mcasp2_ahclkr_mux: mcasp2_ahclkr_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <28>;
+               reg = <0x1860>;
+       };
+
+       mcasp2_ahclkx_mux: mcasp2_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <28>;
+               reg = <0x1860>;
+       };
+
+       mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1860>;
+       };
+
+       mcasp3_ahclkx_mux: mcasp3_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1868>;
+       };
+
+       mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1868>;
+       };
+
+       mcasp4_ahclkx_mux: mcasp4_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1898>;
+       };
+
+       mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1898>;
+       };
+
+       mcasp5_ahclkx_mux: mcasp5_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1878>;
+       };
+
+       mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1878>;
+       };
+
+       mcasp6_ahclkx_mux: mcasp6_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1904>;
+       };
+
+       mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1904>;
+       };
+
+       mcasp7_ahclkx_mux: mcasp7_ahclkx_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1908>;
+       };
+
+       mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <22>;
+               reg = <0x1908>;
+       };
+
+       mcasp8_ahclk_mux: mcasp8_ahclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               ti,bit-shift = <22>;
+               reg = <0x1890>;
+       };
+
+       mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
+               ti,bit-shift = <24>;
+               reg = <0x1890>;
+       };
+
+       mmc1_fclk_mux: mmc1_fclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1328>;
+       };
+
+       mmc1_fclk_div: mmc1_fclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc1_fclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <4>;
+               reg = <0x1328>;
+               ti,index-power-of-two;
+       };
+
+       mmc2_fclk_mux: mmc2_fclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1330>;
+       };
+
+       mmc2_fclk_div: mmc2_fclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc2_fclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <4>;
+               reg = <0x1330>;
+               ti,index-power-of-two;
+       };
+
+       mmc3_gfclk_mux: mmc3_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1820>;
+       };
+
+       mmc3_gfclk_div: mmc3_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc3_gfclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <4>;
+               reg = <0x1820>;
+               ti,index-power-of-two;
+       };
+
+       mmc4_gfclk_mux: mmc4_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1828>;
+       };
+
+       mmc4_gfclk_div: mmc4_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc4_gfclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <4>;
+               reg = <0x1828>;
+               ti,index-power-of-two;
+       };
+
+       qspi_gfclk_mux: qspi_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_128m_clk>, <&dpll_per_h13x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1838>;
+       };
+
+       qspi_gfclk_div: qspi_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&qspi_gfclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <4>;
+               reg = <0x1838>;
+               ti,index-power-of-two;
+       };
+
+       timer10_gfclk_mux: timer10_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1728>;
+       };
+
+       timer11_gfclk_mux: timer11_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1730>;
+       };
+
+       timer13_gfclk_mux: timer13_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x17c8>;
+       };
+
+       timer14_gfclk_mux: timer14_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x17d0>;
+       };
+
+       timer15_gfclk_mux: timer15_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x17d8>;
+       };
+
+       timer16_gfclk_mux: timer16_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1830>;
+       };
+
+       timer2_gfclk_mux: timer2_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1738>;
+       };
+
+       timer3_gfclk_mux: timer3_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1740>;
+       };
+
+       timer4_gfclk_mux: timer4_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1748>;
+       };
+
+       timer9_gfclk_mux: timer9_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x1750>;
+       };
+
+       uart1_gfclk_mux: uart1_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1840>;
+       };
+
+       uart2_gfclk_mux: uart2_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1848>;
+       };
+
+       uart3_gfclk_mux: uart3_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1850>;
+       };
+
+       uart4_gfclk_mux: uart4_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1858>;
+       };
+
+       uart5_gfclk_mux: uart5_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1870>;
+       };
+
+       uart7_gfclk_mux: uart7_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x18d0>;
+       };
+
+       uart8_gfclk_mux: uart8_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x18e0>;
+       };
+
+       uart9_gfclk_mux: uart9_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x18e8>;
+       };
+
+       vip1_gclk_mux: vip1_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1020>;
+       };
+
+       vip2_gclk_mux: vip2_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1028>;
+       };
+
+       vip3_gclk_mux: vip3_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1030>;
+       };
+};
+
+&cm_core_clockdomains {
+       coreaon_clkdm: coreaon_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll_usb_ck>;
+       };
+};
index 427395c083f59e63c3b41bfeeefaa0fab1b66ee0..a5fc83b9c83545ce61738abf4695ceaa47453980 100644 (file)
                        interrupts = <0>;
                };
 
+               prm: prm@48306000 {
+                       compatible = "ti,omap3-prm";
+                       reg = <0x48306000 0x4000>;
+
+                       prm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prm_clockdomains: clockdomains {
+                       };
+               };
+
+               cm: cm@48004000 {
+                       compatible = "ti,omap3-cm";
+                       reg = <0x48004000 0x4000>;
+
+                       cm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm_clockdomains: clockdomains {
+                       };
+               };
+
+               scrm: scrm@48002000 {
+                       compatible = "ti,omap3-scrm";
+                       reg = <0x48002000 0x2000>;
+
+                       scrm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       scrm_clockdomains: clockdomains {
+                       };
+               };
+
                counter32k: counter@48320000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x48320000 0x20>;
                };
        };
 };
+
+/include/ "omap3xxx-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap3430es1-clocks.dtsi b/arch/arm/boot/dts/omap3430es1-clocks.dtsi
new file mode 100644 (file)
index 0000000..02f6c7f
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Device Tree Source for OMAP3430 ES1 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_clocks {
+       gfx_l3_ck: gfx_l3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&l3_ick>;
+               reg = <0x0b10>;
+               ti,bit-shift = <0>;
+       };
+
+       gfx_l3_fck: gfx_l3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&l3_ick>;
+               ti,max-div = <7>;
+               reg = <0x0b40>;
+               ti,index-starts-at-one;
+       };
+
+       gfx_l3_ick: gfx_l3_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&gfx_l3_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gfx_cg1_ck: gfx_cg1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&gfx_l3_fck>;
+               reg = <0x0b00>;
+               ti,bit-shift = <1>;
+       };
+
+       gfx_cg2_ck: gfx_cg2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&gfx_l3_fck>;
+               reg = <0x0b00>;
+               ti,bit-shift = <2>;
+       };
+
+       d2d_26m_fck: d2d_26m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <3>;
+       };
+
+       fshostusb_fck: fshostusb_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <5>;
+       };
+
+       ssi_ssr_gate_fck_3430es1: ssi_ssr_gate_fck_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&corex2_fck>;
+               ti,bit-shift = <0>;
+               reg = <0x0a00>;
+       };
+
+       ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-divider-clock";
+               clocks = <&corex2_fck>;
+               ti,bit-shift = <8>;
+               reg = <0x0a40>;
+               ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
+       };
+
+       ssi_ssr_fck_3430es1: ssi_ssr_fck_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&ssi_ssr_gate_fck_3430es1>, <&ssi_ssr_div_fck_3430es1>;
+       };
+
+       ssi_sst_fck_3430es1: ssi_sst_fck_3430es1 {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&ssi_ssr_fck_3430es1>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       hsotgusb_ick_3430es1: hsotgusb_ick_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-no-wait-interface-clock";
+               clocks = <&core_l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <4>;
+       };
+
+       fac_ick: fac_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <8>;
+       };
+
+       ssi_l4_ick: ssi_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       ssi_ick_3430es1: ssi_ick_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-no-wait-interface-clock";
+               clocks = <&ssi_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <0>;
+       };
+
+       usb_l4_gate_ick: usb_l4_gate_ick {
+               #clock-cells = <0>;
+               compatible = "ti,composite-interface-clock";
+               clocks = <&l4_ick>;
+               ti,bit-shift = <5>;
+               reg = <0x0a10>;
+       };
+
+       usb_l4_div_ick: usb_l4_div_ick {
+               #clock-cells = <0>;
+               compatible = "ti,composite-divider-clock";
+               clocks = <&l4_ick>;
+               ti,bit-shift = <4>;
+               ti,max-div = <1>;
+               reg = <0x0a40>;
+               ti,index-starts-at-one;
+       };
+
+       usb_l4_ick: usb_l4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
+       };
+
+       dss1_alwon_fck_3430es1: dss1_alwon_fck_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m4x2_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x0e00>;
+               ti,set-rate-parent;
+       };
+
+       dss_ick_3430es1: dss_ick_3430es1 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-no-wait-interface-clock";
+               clocks = <&l4_ick>;
+               reg = <0x0e10>;
+               ti,bit-shift = <0>;
+       };
+};
+
+&cm_clockdomains {
+       core_l3_clkdm: core_l3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sdrc_ick>, <&hsotgusb_ick_3430es1>;
+       };
+
+       gfx_3430es1_clkdm: gfx_3430es1_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&gfx_l3_ck>, <&gfx_cg1_ck>, <&gfx_cg2_ck>;
+       };
+
+       dss_clkdm: dss_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dss_tv_fck>, <&dss_96m_fck>, <&dss2_alwon_fck>,
+                        <&dss1_alwon_fck_3430es1>, <&dss_ick_3430es1>;
+       };
+
+       d2d_clkdm: d2d_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&d2d_26m_fck>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+                        <&fshostusb_fck>, <&fac_ick>, <&ssi_ick_3430es1>;
+       };
+};
diff --git a/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..b02017b
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Device Tree Source for OMAP34XX/OMAP36XX clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_clocks {
+       security_l4_ick2: security_l4_ick2 {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       aes1_ick: aes1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l4_ick2>;
+               ti,bit-shift = <3>;
+               reg = <0x0a14>;
+       };
+
+       rng_ick: rng_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l4_ick2>;
+               reg = <0x0a14>;
+               ti,bit-shift = <2>;
+       };
+
+       sha11_ick: sha11_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l4_ick2>;
+               reg = <0x0a14>;
+               ti,bit-shift = <1>;
+       };
+
+       des1_ick: des1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l4_ick2>;
+               reg = <0x0a14>;
+               ti,bit-shift = <0>;
+       };
+
+       cam_mclk: cam_mclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m5x2_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x0f00>;
+               ti,set-rate-parent;
+       };
+
+       cam_ick: cam_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-no-wait-interface-clock";
+               clocks = <&l4_ick>;
+               reg = <0x0f10>;
+               ti,bit-shift = <0>;
+       };
+
+       csi2_96m_fck: csi2_96m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0f00>;
+               ti,bit-shift = <1>;
+       };
+
+       security_l3_ick: security_l3_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l3_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       pka_ick: pka_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&security_l3_ick>;
+               reg = <0x0a14>;
+               ti,bit-shift = <4>;
+       };
+
+       icr_ick: icr_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <29>;
+       };
+
+       des2_ick: des2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <26>;
+       };
+
+       mspro_ick: mspro_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <23>;
+       };
+
+       mailboxes_ick: mailboxes_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <7>;
+       };
+
+       ssi_l4_ick: ssi_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sr1_fck: sr1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0c00>;
+               ti,bit-shift = <6>;
+       };
+
+       sr2_fck: sr2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0c00>;
+               ti,bit-shift = <7>;
+       };
+
+       sr_l4_ick: sr_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll2_fck: dpll2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <19>;
+               ti,max-div = <7>;
+               reg = <0x0040>;
+               ti,index-starts-at-one;
+       };
+
+       dpll2_ck: dpll2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-clock";
+               clocks = <&sys_ck>, <&dpll2_fck>;
+               reg = <0x0004>, <0x0024>, <0x0040>, <0x0034>;
+               ti,low-power-stop;
+               ti,lock;
+               ti,low-power-bypass;
+       };
+
+       dpll2_m2_ck: dpll2_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0044>;
+               ti,index-starts-at-one;
+       };
+
+       iva2_ck: iva2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&dpll2_m2_ck>;
+               reg = <0x0000>;
+               ti,bit-shift = <0>;
+       };
+
+       modem_fck: modem_fck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <31>;
+       };
+
+       sad2d_ick: sad2d_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <3>;
+       };
+
+       mad2d_ick: mad2d_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&l3_ick>;
+               reg = <0x0a18>;
+               ti,bit-shift = <3>;
+       };
+
+       mspro_fck: mspro_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <23>;
+       };
+};
+
+&cm_clockdomains {
+       cam_clkdm: cam_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&cam_ick>, <&csi2_96m_fck>;
+       };
+
+       iva2_clkdm: iva2_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&iva2_ck>;
+       };
+
+       dpll2_clkdm: dpll2_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll2_ck>;
+       };
+
+       wkup_clkdm: wkup_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&gpio1_dbck>, <&wdt2_fck>, <&wdt2_ick>, <&wdt1_ick>,
+                        <&gpio1_ick>, <&omap_32ksync_ick>, <&gpt12_ick>,
+                        <&gpt1_ick>, <&sr1_fck>, <&sr2_fck>;
+       };
+
+       d2d_clkdm: d2d_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&modem_fck>, <&sad2d_ick>, <&mad2d_ick>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>, <&icr_ick>,
+                        <&des2_ick>, <&mspro_ick>, <&mailboxes_ick>,
+                        <&mspro_fck>;
+       };
+};
index 77d124678c9587905b4da1fb9ee18b9759883efe..2e92360da1f36d29d094ef67c8183a8824c0f047 100644 (file)
@@ -39,3 +39,7 @@
                };
        };
 };
+
+/include/ "omap34xx-omap36xx-clocks.dtsi"
+/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
new file mode 100644 (file)
index 0000000..af9ae53
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Device Tree Source for OMAP36xx/AM35xx/OMAP34xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm_clocks {
+       corex2_d3_fck: corex2_d3_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&corex2_fck>;
+               clock-mult = <1>;
+               clock-div = <3>;
+       };
+
+       corex2_d5_fck: corex2_d5_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&corex2_fck>;
+               clock-mult = <1>;
+               clock-div = <5>;
+       };
+};
+&cm_clocks {
+       dpll5_ck: dpll5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0d04>, <0x0d24>, <0x0d4c>, <0x0d34>;
+               ti,low-power-stop;
+               ti,lock;
+       };
+
+       dpll5_m2_ck: dpll5_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll5_ck>;
+               ti,max-div = <31>;
+               reg = <0x0d50>;
+               ti,index-starts-at-one;
+       };
+
+       sgx_gate_fck: sgx_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0b00>;
+       };
+
+       core_d3_ck: core_d3_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&core_ck>;
+               clock-mult = <1>;
+               clock-div = <3>;
+       };
+
+       core_d4_ck: core_d4_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&core_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       core_d6_ck: core_d6_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&core_ck>;
+               clock-mult = <1>;
+               clock-div = <6>;
+       };
+
+       omap_192m_alwon_fck: omap_192m_alwon_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       core_d2_ck: core_d2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&core_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       sgx_mux_fck: sgx_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&core_d3_ck>, <&core_d4_ck>, <&core_d6_ck>, <&cm_96m_fck>, <&omap_192m_alwon_fck>, <&core_d2_ck>, <&corex2_d3_fck>, <&corex2_d5_fck>;
+               reg = <0x0b40>;
+       };
+
+       sgx_fck: sgx_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&sgx_gate_fck>, <&sgx_mux_fck>;
+       };
+
+       sgx_ick: sgx_ick {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&l3_ick>;
+               reg = <0x0b10>;
+               ti,bit-shift = <0>;
+       };
+
+       cpefuse_fck: cpefuse_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0a08>;
+               ti,bit-shift = <0>;
+       };
+
+       ts_fck: ts_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&omap_32k_fck>;
+               reg = <0x0a08>;
+               ti,bit-shift = <1>;
+       };
+
+       usbtll_fck: usbtll_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&dpll5_m2_ck>;
+               reg = <0x0a08>;
+               ti,bit-shift = <2>;
+       };
+
+       usbtll_ick: usbtll_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a18>;
+               ti,bit-shift = <2>;
+       };
+
+       mmchs3_ick: mmchs3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <30>;
+       };
+
+       mmchs3_fck: mmchs3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <30>;
+       };
+
+       dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,dss-gate-clock";
+               clocks = <&dpll4_m4x2_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x0e00>;
+               ti,set-rate-parent;
+       };
+
+       dss_ick_3430es2: dss_ick_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dss-interface-clock";
+               clocks = <&l4_ick>;
+               reg = <0x0e10>;
+               ti,bit-shift = <0>;
+       };
+
+       usbhost_120m_fck: usbhost_120m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll5_m2_ck>;
+               reg = <0x1400>;
+               ti,bit-shift = <1>;
+       };
+
+       usbhost_48m_fck: usbhost_48m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,dss-gate-clock";
+               clocks = <&omap_48m_fck>;
+               reg = <0x1400>;
+               ti,bit-shift = <0>;
+       };
+
+       usbhost_ick: usbhost_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dss-interface-clock";
+               clocks = <&l4_ick>;
+               reg = <0x1410>;
+               ti,bit-shift = <0>;
+       };
+};
+
+&cm_clockdomains {
+       dpll5_clkdm: dpll5_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll5_ck>;
+       };
+
+       sgx_clkdm: sgx_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sgx_ick>;
+       };
+
+       dss_clkdm: dss_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dss_tv_fck>, <&dss_96m_fck>, <&dss2_alwon_fck>,
+                        <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+                        <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+                        <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>;
+       };
+
+       usbhost_clkdm: usbhost_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&usbhost_120m_fck>, <&usbhost_48m_fck>,
+                        <&usbhost_ick>;
+       };
+};
diff --git a/arch/arm/boot/dts/omap36xx-clocks.dtsi b/arch/arm/boot/dts/omap36xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..2fcf253
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Device Tree Source for OMAP36xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_clocks {
+       dpll4_ck: dpll4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-per-j-type-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>;
+       };
+
+       dpll4_m5x2_ck: dpll4_m5x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll4_m5x2_mul_ck>;
+               ti,bit-shift = <0x1e>;
+               reg = <0x0d00>;
+               ti,set-rate-parent;
+               ti,set-bit-to-disable;
+       };
+
+       dpll4_m2x2_ck: dpll4_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll4_m2x2_mul_ck>;
+               ti,bit-shift = <0x1b>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       dpll3_m3x2_ck: dpll3_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll3_m3x2_mul_ck>;
+               ti,bit-shift = <0xc>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       dpll4_m3x2_ck: dpll4_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll4_m3x2_mul_ck>;
+               ti,bit-shift = <0x1c>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       dpll4_m6x2_ck: dpll4_m6x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,hsdiv-gate-clock";
+               clocks = <&dpll4_m6x2_mul_ck>;
+               ti,bit-shift = <0x1f>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       uart4_fck: uart4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&per_48m_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <18>;
+       };
+};
+
+&cm_clockdomains {
+       dpll4_clkdm: dpll4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll4_ck>;
+       };
+
+       per_clkdm: per_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&uart3_fck>, <&gpio6_dbck>, <&gpio5_dbck>,
+                        <&gpio4_dbck>, <&gpio3_dbck>, <&gpio2_dbck>,
+                        <&wdt3_fck>, <&gpio6_ick>, <&gpio5_ick>, <&gpio4_ick>,
+                        <&gpio3_ick>, <&gpio2_ick>, <&wdt3_ick>, <&uart3_ick>,
+                        <&uart4_ick>, <&gpt9_ick>, <&gpt8_ick>, <&gpt7_ick>,
+                        <&gpt6_ick>, <&gpt5_ick>, <&gpt4_ick>, <&gpt3_ick>,
+                        <&gpt2_ick>, <&mcbsp2_ick>, <&mcbsp3_ick>,
+                        <&mcbsp4_ick>, <&uart4_fck>;
+       };
+};
diff --git a/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi b/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi
new file mode 100644 (file)
index 0000000..8ed475d
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Device Tree Source for OMAP34xx/OMAP36xx clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_clocks {
+       ssi_ssr_gate_fck_3430es2: ssi_ssr_gate_fck_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&corex2_fck>;
+               ti,bit-shift = <0>;
+               reg = <0x0a00>;
+       };
+
+       ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-divider-clock";
+               clocks = <&corex2_fck>;
+               ti,bit-shift = <8>;
+               reg = <0x0a40>;
+               ti,dividers = <0>, <1>, <2>, <3>, <4>, <0>, <6>, <0>, <8>;
+       };
+
+       ssi_ssr_fck_3430es2: ssi_ssr_fck_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&ssi_ssr_gate_fck_3430es2>, <&ssi_ssr_div_fck_3430es2>;
+       };
+
+       ssi_sst_fck_3430es2: ssi_sst_fck_3430es2 {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&ssi_ssr_fck_3430es2>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       hsotgusb_ick_3430es2: hsotgusb_ick_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-hsotgusb-interface-clock";
+               clocks = <&core_l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <4>;
+       };
+
+       ssi_l4_ick: ssi_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       ssi_ick_3430es2: ssi_ick_3430es2 {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-ssi-interface-clock";
+               clocks = <&ssi_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <0>;
+       };
+
+       usim_gate_fck: usim_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&omap_96m_fck>;
+               ti,bit-shift = <9>;
+               reg = <0x0c00>;
+       };
+
+       sys_d2_ck: sys_d2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       omap_96m_d2_fck: omap_96m_d2_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       omap_96m_d4_fck: omap_96m_d4_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       omap_96m_d8_fck: omap_96m_d8_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       omap_96m_d10_fck: omap_96m_d10_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <10>;
+       };
+
+       dpll5_m2_d4_ck: dpll5_m2_d4_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll5_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       dpll5_m2_d8_ck: dpll5_m2_d8_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll5_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       dpll5_m2_d16_ck: dpll5_m2_d16_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll5_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       dpll5_m2_d20_ck: dpll5_m2_d20_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll5_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <20>;
+       };
+
+       usim_mux_fck: usim_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_ck>, <&sys_d2_ck>, <&omap_96m_d2_fck>, <&omap_96m_d4_fck>, <&omap_96m_d8_fck>, <&omap_96m_d10_fck>, <&dpll5_m2_d4_ck>, <&dpll5_m2_d8_ck>, <&dpll5_m2_d16_ck>, <&dpll5_m2_d20_ck>;
+               ti,bit-shift = <3>;
+               reg = <0x0c40>;
+               ti,index-starts-at-one;
+       };
+
+       usim_fck: usim_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&usim_gate_fck>, <&usim_mux_fck>;
+       };
+
+       usim_ick: usim_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <9>;
+       };
+};
+
+&cm_clockdomains {
+       core_l3_clkdm: core_l3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sdrc_ick>, <&hsotgusb_ick_3430es2>;
+       };
+
+       wkup_clkdm: wkup_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&gpio1_dbck>, <&wdt2_fck>, <&wdt2_ick>, <&wdt1_ick>,
+                        <&gpio1_ick>, <&omap_32ksync_ick>, <&gpt12_ick>,
+                        <&gpt1_ick>, <&usim_ick>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>,
+                        <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>,
+                        <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>,
+                        <&ssi_ick_3430es2>;
+       };
+};
index b7c7bd96c4041e70752e64c7f70c16c4d7ff4456..7e8dee9175d6a4d1d796a5a9389b4a9c3300125d 100644 (file)
@@ -51,3 +51,8 @@
                };
        };
 };
+
+/include/ "omap36xx-clocks.dtsi"
+/include/ "omap34xx-omap36xx-clocks.dtsi"
+/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
+/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap3xxx-clocks.dtsi b/arch/arm/boot/dts/omap3xxx-clocks.dtsi
new file mode 100644 (file)
index 0000000..cb04d4b
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+ * Device Tree Source for OMAP3 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm_clocks {
+       virt_16_8m_ck: virt_16_8m_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16800000>;
+       };
+
+       osc_sys_ck: osc_sys_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_12m_ck>, <&virt_13m_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_38_4m_ck>, <&virt_16_8m_ck>;
+               reg = <0x0d40>;
+       };
+
+       sys_ck: sys_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&osc_sys_ck>;
+               ti,bit-shift = <6>;
+               ti,max-div = <3>;
+               reg = <0x1270>;
+               ti,index-starts-at-one;
+       };
+
+       sys_clkout1: sys_clkout1 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&osc_sys_ck>;
+               reg = <0x0d70>;
+               ti,bit-shift = <7>;
+       };
+
+       dpll3_x2_ck: dpll3_x2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll3_m2x2_ck: dpll3_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_m2_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_x2_ck: dpll4_x2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       corex2_fck: corex2_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       wkup_l4_ick: wkup_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+};
+&scrm_clocks {
+       mcbsp5_mux_fck: mcbsp5_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&core_96m_fck>, <&mcbsp_clks>;
+               ti,bit-shift = <4>;
+               reg = <0x02d8>;
+       };
+
+       mcbsp5_fck: mcbsp5_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&mcbsp5_gate_fck>, <&mcbsp5_mux_fck>;
+       };
+
+       mcbsp1_mux_fck: mcbsp1_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&core_96m_fck>, <&mcbsp_clks>;
+               ti,bit-shift = <2>;
+               reg = <0x0274>;
+       };
+
+       mcbsp1_fck: mcbsp1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&mcbsp1_gate_fck>, <&mcbsp1_mux_fck>;
+       };
+
+       mcbsp2_mux_fck: mcbsp2_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&per_96m_fck>, <&mcbsp_clks>;
+               ti,bit-shift = <6>;
+               reg = <0x0274>;
+       };
+
+       mcbsp2_fck: mcbsp2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&mcbsp2_gate_fck>, <&mcbsp2_mux_fck>;
+       };
+
+       mcbsp3_mux_fck: mcbsp3_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&per_96m_fck>, <&mcbsp_clks>;
+               reg = <0x02d8>;
+       };
+
+       mcbsp3_fck: mcbsp3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&mcbsp3_gate_fck>, <&mcbsp3_mux_fck>;
+       };
+
+       mcbsp4_mux_fck: mcbsp4_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&per_96m_fck>, <&mcbsp_clks>;
+               ti,bit-shift = <2>;
+               reg = <0x02d8>;
+       };
+
+       mcbsp4_fck: mcbsp4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&mcbsp4_gate_fck>, <&mcbsp4_mux_fck>;
+       };
+};
+&cm_clocks {
+       dummy_apb_pclk: dummy_apb_pclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0x0>;
+       };
+
+       omap_32k_fck: omap_32k_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       virt_12m_ck: virt_12m_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       virt_13m_ck: virt_13m_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <13000000>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       virt_38_4m_ck: virt_38_4m_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <38400000>;
+       };
+
+       dpll4_ck: dpll4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-per-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>;
+       };
+
+       dpll4_m2_ck: dpll4_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll4_ck>;
+               ti,max-div = <63>;
+               reg = <0x0d48>;
+               ti,index-starts-at-one;
+       };
+
+       dpll4_m2x2_mul_ck: dpll4_m2x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m2_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_m2x2_ck: dpll4_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m2x2_mul_ck>;
+               ti,bit-shift = <0x1b>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       omap_96m_alwon_fck: omap_96m_alwon_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll3_ck: dpll3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-core-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0d00>, <0x0d20>, <0x0d40>, <0x0d30>;
+       };
+
+       dpll3_m3_ck: dpll3_m3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll3_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <31>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       dpll3_m3x2_mul_ck: dpll3_m3x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_m3_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll3_m3x2_ck: dpll3_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll3_m3x2_mul_ck>;
+               ti,bit-shift = <0xc>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       emu_core_alwon_ck: emu_core_alwon_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sys_altclk: sys_altclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0x0>;
+       };
+
+       mcbsp_clks: mcbsp_clks {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0x0>;
+       };
+
+       dpll3_m2_ck: dpll3_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll3_ck>;
+               ti,bit-shift = <27>;
+               ti,max-div = <31>;
+               reg = <0x0d40>;
+               ti,index-starts-at-one;
+       };
+
+       core_ck: core_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll3_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll1_fck: dpll1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <19>;
+               ti,max-div = <7>;
+               reg = <0x0940>;
+               ti,index-starts-at-one;
+       };
+
+       dpll1_ck: dpll1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-dpll-clock";
+               clocks = <&sys_ck>, <&dpll1_fck>;
+               reg = <0x0904>, <0x0924>, <0x0940>, <0x0934>;
+       };
+
+       dpll1_x2_ck: dpll1_x2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll1_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll1_x2m2_ck: dpll1_x2m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll1_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0944>;
+               ti,index-starts-at-one;
+       };
+
+       cm_96m_fck: cm_96m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_alwon_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       omap_96m_fck: omap_96m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&cm_96m_fck>, <&sys_ck>;
+               ti,bit-shift = <6>;
+               reg = <0x0d40>;
+       };
+
+       dpll4_m3_ck: dpll4_m3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll4_ck>;
+               ti,bit-shift = <8>;
+               ti,max-div = <32>;
+               reg = <0x0e40>;
+               ti,index-starts-at-one;
+       };
+
+       dpll4_m3x2_mul_ck: dpll4_m3x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m3_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_m3x2_ck: dpll4_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m3x2_mul_ck>;
+               ti,bit-shift = <0x1c>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       omap_54m_fck: omap_54m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll4_m3x2_ck>, <&sys_altclk>;
+               ti,bit-shift = <5>;
+               reg = <0x0d40>;
+       };
+
+       cm_96m_d2_fck: cm_96m_d2_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&cm_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       omap_48m_fck: omap_48m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&cm_96m_d2_fck>, <&sys_altclk>;
+               ti,bit-shift = <3>;
+               reg = <0x0d40>;
+       };
+
+       omap_12m_fck: omap_12m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_48m_fck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       dpll4_m4_ck: dpll4_m4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll4_ck>;
+               ti,max-div = <32>;
+               reg = <0x0e40>;
+               ti,index-starts-at-one;
+       };
+
+       dpll4_m4x2_mul_ck: dpll4_m4x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m4_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_m4x2_ck: dpll4_m4x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m4x2_mul_ck>;
+               ti,bit-shift = <0x1d>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       dpll4_m5_ck: dpll4_m5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll4_ck>;
+               ti,max-div = <63>;
+               reg = <0x0f40>;
+               ti,index-starts-at-one;
+       };
+
+       dpll4_m5x2_mul_ck: dpll4_m5x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m5_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_m5x2_ck: dpll4_m5x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m5x2_mul_ck>;
+               ti,bit-shift = <0x1e>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       dpll4_m6_ck: dpll4_m6_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll4_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <63>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       dpll4_m6x2_mul_ck: dpll4_m6x2_mul_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m6_ck>;
+               clock-mult = <2>;
+               clock-div = <1>;
+       };
+
+       dpll4_m6x2_ck: dpll4_m6x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll4_m6x2_mul_ck>;
+               ti,bit-shift = <0x1f>;
+               reg = <0x0d00>;
+               ti,set-bit-to-disable;
+       };
+
+       emu_per_alwon_ck: emu_per_alwon_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll4_m6x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       clkout2_src_gate_ck: clkout2_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x0d70>;
+       };
+
+       clkout2_src_mux_ck: clkout2_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&core_ck>, <&sys_ck>, <&cm_96m_fck>, <&omap_54m_fck>;
+               reg = <0x0d70>;
+       };
+
+       clkout2_src_ck: clkout2_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&clkout2_src_gate_ck>, <&clkout2_src_mux_ck>;
+       };
+
+       sys_clkout2: sys_clkout2 {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&clkout2_src_ck>;
+               ti,bit-shift = <3>;
+               ti,max-div = <64>;
+               reg = <0x0d70>;
+               ti,index-power-of-two;
+       };
+
+       mpu_ck: mpu_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll1_x2m2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       arm_fck: arm_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mpu_ck>;
+               reg = <0x0924>;
+               ti,max-div = <2>;
+       };
+
+       emu_mpu_alwon_ck: emu_mpu_alwon_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&mpu_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l3_ick: l3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&core_ck>;
+               ti,max-div = <3>;
+               reg = <0x0a40>;
+               ti,index-starts-at-one;
+       };
+
+       l4_ick: l4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&l3_ick>;
+               ti,bit-shift = <2>;
+               ti,max-div = <3>;
+               reg = <0x0a40>;
+               ti,index-starts-at-one;
+       };
+
+       rm_ick: rm_ick {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&l4_ick>;
+               ti,bit-shift = <1>;
+               ti,max-div = <3>;
+               reg = <0x0c40>;
+               ti,index-starts-at-one;
+       };
+
+       gpt10_gate_fck: gpt10_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <11>;
+               reg = <0x0a00>;
+       };
+
+       gpt10_mux_fck: gpt10_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <6>;
+               reg = <0x0a40>;
+       };
+
+       gpt10_fck: gpt10_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt10_gate_fck>, <&gpt10_mux_fck>;
+       };
+
+       gpt11_gate_fck: gpt11_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <12>;
+               reg = <0x0a00>;
+       };
+
+       gpt11_mux_fck: gpt11_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x0a40>;
+       };
+
+       gpt11_fck: gpt11_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt11_gate_fck>, <&gpt11_mux_fck>;
+       };
+
+       core_96m_fck: core_96m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mmchs2_fck: mmchs2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <25>;
+       };
+
+       mmchs1_fck: mmchs1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <24>;
+       };
+
+       i2c3_fck: i2c3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <17>;
+       };
+
+       i2c2_fck: i2c2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <16>;
+       };
+
+       i2c1_fck: i2c1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_96m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <15>;
+       };
+
+       mcbsp5_gate_fck: mcbsp5_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&mcbsp_clks>;
+               ti,bit-shift = <10>;
+               reg = <0x0a00>;
+       };
+
+       mcbsp1_gate_fck: mcbsp1_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&mcbsp_clks>;
+               ti,bit-shift = <9>;
+               reg = <0x0a00>;
+       };
+
+       core_48m_fck: core_48m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_48m_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mcspi4_fck: mcspi4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <21>;
+       };
+
+       mcspi3_fck: mcspi3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <20>;
+       };
+
+       mcspi2_fck: mcspi2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <19>;
+       };
+
+       mcspi1_fck: mcspi1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <18>;
+       };
+
+       uart2_fck: uart2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <14>;
+       };
+
+       uart1_fck: uart1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_48m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <13>;
+       };
+
+       core_12m_fck: core_12m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_12m_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       hdq_fck: hdq_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_12m_fck>;
+               reg = <0x0a00>;
+               ti,bit-shift = <22>;
+       };
+
+       core_l3_ick: core_l3_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l3_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       sdrc_ick: sdrc_ick {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&core_l3_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <1>;
+       };
+
+       gpmc_fck: gpmc_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&core_l3_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       core_l4_ick: core_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       mmchs2_ick: mmchs2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <25>;
+       };
+
+       mmchs1_ick: mmchs1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <24>;
+       };
+
+       hdq_ick: hdq_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <22>;
+       };
+
+       mcspi4_ick: mcspi4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <21>;
+       };
+
+       mcspi3_ick: mcspi3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <20>;
+       };
+
+       mcspi2_ick: mcspi2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <19>;
+       };
+
+       mcspi1_ick: mcspi1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <18>;
+       };
+
+       i2c3_ick: i2c3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <17>;
+       };
+
+       i2c2_ick: i2c2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <16>;
+       };
+
+       i2c1_ick: i2c1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <15>;
+       };
+
+       uart2_ick: uart2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <14>;
+       };
+
+       uart1_ick: uart1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <13>;
+       };
+
+       gpt11_ick: gpt11_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <12>;
+       };
+
+       gpt10_ick: gpt10_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <11>;
+       };
+
+       mcbsp5_ick: mcbsp5_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <10>;
+       };
+
+       mcbsp1_ick: mcbsp1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <9>;
+       };
+
+       omapctrl_ick: omapctrl_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <6>;
+       };
+
+       dss_tv_fck: dss_tv_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&omap_54m_fck>;
+               reg = <0x0e00>;
+               ti,bit-shift = <2>;
+       };
+
+       dss_96m_fck: dss_96m_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&omap_96m_fck>;
+               reg = <0x0e00>;
+               ti,bit-shift = <2>;
+       };
+
+       dss2_alwon_fck: dss2_alwon_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_ck>;
+               reg = <0x0e00>;
+               ti,bit-shift = <1>;
+       };
+
+       dummy_ck: dummy_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       gpt1_gate_fck: gpt1_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x0c00>;
+       };
+
+       gpt1_mux_fck: gpt1_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               reg = <0x0c40>;
+       };
+
+       gpt1_fck: gpt1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt1_gate_fck>, <&gpt1_mux_fck>;
+       };
+
+       aes2_ick: aes2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               ti,bit-shift = <28>;
+               reg = <0x0a10>;
+       };
+
+       wkup_32k_fck: wkup_32k_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_32k_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gpio1_dbck: gpio1_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&wkup_32k_fck>;
+               reg = <0x0c00>;
+               ti,bit-shift = <3>;
+       };
+
+       sha12_ick: sha12_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&core_l4_ick>;
+               reg = <0x0a10>;
+               ti,bit-shift = <27>;
+       };
+
+       wdt2_fck: wdt2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&wkup_32k_fck>;
+               reg = <0x0c00>;
+               ti,bit-shift = <5>;
+       };
+
+       wdt2_ick: wdt2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <5>;
+       };
+
+       wdt1_ick: wdt1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <4>;
+       };
+
+       gpio1_ick: gpio1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <3>;
+       };
+
+       omap_32ksync_ick: omap_32ksync_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <2>;
+       };
+
+       gpt12_ick: gpt12_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <1>;
+       };
+
+       gpt1_ick: gpt1_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&wkup_l4_ick>;
+               reg = <0x0c10>;
+               ti,bit-shift = <0>;
+       };
+
+       per_96m_fck: per_96m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_96m_alwon_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       per_48m_fck: per_48m_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_48m_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       uart3_fck: uart3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&per_48m_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <11>;
+       };
+
+       gpt2_gate_fck: gpt2_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <3>;
+               reg = <0x1000>;
+       };
+
+       gpt2_mux_fck: gpt2_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               reg = <0x1040>;
+       };
+
+       gpt2_fck: gpt2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt2_gate_fck>, <&gpt2_mux_fck>;
+       };
+
+       gpt3_gate_fck: gpt3_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <4>;
+               reg = <0x1000>;
+       };
+
+       gpt3_mux_fck: gpt3_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x1040>;
+       };
+
+       gpt3_fck: gpt3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt3_gate_fck>, <&gpt3_mux_fck>;
+       };
+
+       gpt4_gate_fck: gpt4_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <5>;
+               reg = <0x1000>;
+       };
+
+       gpt4_mux_fck: gpt4_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x1040>;
+       };
+
+       gpt4_fck: gpt4_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt4_gate_fck>, <&gpt4_mux_fck>;
+       };
+
+       gpt5_gate_fck: gpt5_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <6>;
+               reg = <0x1000>;
+       };
+
+       gpt5_mux_fck: gpt5_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <3>;
+               reg = <0x1040>;
+       };
+
+       gpt5_fck: gpt5_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt5_gate_fck>, <&gpt5_mux_fck>;
+       };
+
+       gpt6_gate_fck: gpt6_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x1000>;
+       };
+
+       gpt6_mux_fck: gpt6_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <4>;
+               reg = <0x1040>;
+       };
+
+       gpt6_fck: gpt6_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt6_gate_fck>, <&gpt6_mux_fck>;
+       };
+
+       gpt7_gate_fck: gpt7_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1000>;
+       };
+
+       gpt7_mux_fck: gpt7_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <5>;
+               reg = <0x1040>;
+       };
+
+       gpt7_fck: gpt7_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt7_gate_fck>, <&gpt7_mux_fck>;
+       };
+
+       gpt8_gate_fck: gpt8_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <9>;
+               reg = <0x1000>;
+       };
+
+       gpt8_mux_fck: gpt8_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <6>;
+               reg = <0x1040>;
+       };
+
+       gpt8_fck: gpt8_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt8_gate_fck>, <&gpt8_mux_fck>;
+       };
+
+       gpt9_gate_fck: gpt9_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <10>;
+               reg = <0x1000>;
+       };
+
+       gpt9_mux_fck: gpt9_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&omap_32k_fck>, <&sys_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x1040>;
+       };
+
+       gpt9_fck: gpt9_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&gpt9_gate_fck>, <&gpt9_mux_fck>;
+       };
+
+       per_32k_alwon_fck: per_32k_alwon_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&omap_32k_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gpio6_dbck: gpio6_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <17>;
+       };
+
+       gpio5_dbck: gpio5_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <16>;
+       };
+
+       gpio4_dbck: gpio4_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <15>;
+       };
+
+       gpio3_dbck: gpio3_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <14>;
+       };
+
+       gpio2_dbck: gpio2_dbck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <13>;
+       };
+
+       wdt3_fck: wdt3_fck {
+               #clock-cells = <0>;
+               compatible = "ti,wait-gate-clock";
+               clocks = <&per_32k_alwon_fck>;
+               reg = <0x1000>;
+               ti,bit-shift = <12>;
+       };
+
+       per_l4_ick: per_l4_ick {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l4_ick>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gpio6_ick: gpio6_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <17>;
+       };
+
+       gpio5_ick: gpio5_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <16>;
+       };
+
+       gpio4_ick: gpio4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <15>;
+       };
+
+       gpio3_ick: gpio3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <14>;
+       };
+
+       gpio2_ick: gpio2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <13>;
+       };
+
+       wdt3_ick: wdt3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <12>;
+       };
+
+       uart3_ick: uart3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <11>;
+       };
+
+       uart4_ick: uart4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <18>;
+       };
+
+       gpt9_ick: gpt9_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <10>;
+       };
+
+       gpt8_ick: gpt8_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <9>;
+       };
+
+       gpt7_ick: gpt7_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <8>;
+       };
+
+       gpt6_ick: gpt6_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <7>;
+       };
+
+       gpt5_ick: gpt5_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <6>;
+       };
+
+       gpt4_ick: gpt4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <5>;
+       };
+
+       gpt3_ick: gpt3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <4>;
+       };
+
+       gpt2_ick: gpt2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <3>;
+       };
+
+       mcbsp2_ick: mcbsp2_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <0>;
+       };
+
+       mcbsp3_ick: mcbsp3_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <1>;
+       };
+
+       mcbsp4_ick: mcbsp4_ick {
+               #clock-cells = <0>;
+               compatible = "ti,omap3-interface-clock";
+               clocks = <&per_l4_ick>;
+               reg = <0x1010>;
+               ti,bit-shift = <2>;
+       };
+
+       mcbsp2_gate_fck: mcbsp2_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&mcbsp_clks>;
+               ti,bit-shift = <0>;
+               reg = <0x1000>;
+       };
+
+       mcbsp3_gate_fck: mcbsp3_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&mcbsp_clks>;
+               ti,bit-shift = <1>;
+               reg = <0x1000>;
+       };
+
+       mcbsp4_gate_fck: mcbsp4_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&mcbsp_clks>;
+               ti,bit-shift = <2>;
+               reg = <0x1000>;
+       };
+
+       emu_src_mux_ck: emu_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>;
+               reg = <0x1140>;
+       };
+
+       emu_src_ck: emu_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,clkdm-gate-clock";
+               clocks = <&emu_src_mux_ck>;
+       };
+
+       pclk_fck: pclk_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&emu_src_ck>;
+               ti,bit-shift = <8>;
+               ti,max-div = <7>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       pclkx2_fck: pclkx2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&emu_src_ck>;
+               ti,bit-shift = <6>;
+               ti,max-div = <3>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       atclk_fck: atclk_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&emu_src_ck>;
+               ti,bit-shift = <4>;
+               ti,max-div = <3>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       traceclk_src_fck: traceclk_src_fck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x1140>;
+       };
+
+       traceclk_fck: traceclk_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&traceclk_src_fck>;
+               ti,bit-shift = <11>;
+               ti,max-div = <7>;
+               reg = <0x1140>;
+               ti,index-starts-at-one;
+       };
+
+       secure_32k_fck: secure_32k_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       gpt12_fck: gpt12_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&secure_32k_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       wdt1_fck: wdt1_fck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&secure_32k_fck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+};
+
+&cm_clockdomains {
+       core_l3_clkdm: core_l3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&sdrc_ick>;
+       };
+
+       dpll3_clkdm: dpll3_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll3_ck>;
+       };
+
+       dpll1_clkdm: dpll1_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll1_ck>;
+       };
+
+       per_clkdm: per_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&uart3_fck>, <&gpio6_dbck>, <&gpio5_dbck>,
+                        <&gpio4_dbck>, <&gpio3_dbck>, <&gpio2_dbck>,
+                        <&wdt3_fck>, <&gpio6_ick>, <&gpio5_ick>, <&gpio4_ick>,
+                        <&gpio3_ick>, <&gpio2_ick>, <&wdt3_ick>, <&uart3_ick>,
+                        <&uart4_ick>, <&gpt9_ick>, <&gpt8_ick>, <&gpt7_ick>,
+                        <&gpt6_ick>, <&gpt5_ick>, <&gpt4_ick>, <&gpt3_ick>,
+                        <&gpt2_ick>, <&mcbsp2_ick>, <&mcbsp3_ick>,
+                        <&mcbsp4_ick>;
+       };
+
+       emu_clkdm: emu_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&emu_src_ck>;
+       };
+
+       dpll4_clkdm: dpll4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll4_ck>;
+       };
+
+       wkup_clkdm: wkup_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&gpio1_dbck>, <&wdt2_fck>, <&wdt2_ick>, <&wdt1_ick>,
+                        <&gpio1_ick>, <&omap_32ksync_ick>, <&gpt12_ick>,
+                        <&gpt1_ick>;
+       };
+
+       dss_clkdm: dss_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dss_tv_fck>, <&dss_96m_fck>, <&dss2_alwon_fck>;
+       };
+
+       core_l4_clkdm: core_l4_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>,
+                        <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>,
+                        <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>,
+                        <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>,
+                        <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>,
+                        <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>,
+                        <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>,
+                        <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>,
+                        <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>;
+       };
+};
index a1e05853afcd583c15da3ad259c8f715992b2d7f..d3f8a6e8ca205ef1585c279c1ce50dc8703fa6b5 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+               cm1: cm1@4a004000 {
+                       compatible = "ti,omap4-cm1";
+                       reg = <0x4a004000 0x2000>;
+
+                       cm1_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm1_clockdomains: clockdomains {
+                       };
+               };
+
+               prm: prm@4a306000 {
+                       compatible = "ti,omap4-prm";
+                       reg = <0x4a306000 0x3000>;
+
+                       prm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prm_clockdomains: clockdomains {
+                       };
+               };
+
+               cm2: cm2@4a008000 {
+                       compatible = "ti,omap4-cm2";
+                       reg = <0x4a008000 0x3000>;
+
+                       cm2_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm2_clockdomains: clockdomains {
+                       };
+               };
+
+               scrm: scrm@4a30a000 {
+                       compatible = "ti,omap4-scrm";
+                       reg = <0x4a30a000 0x2000>;
+
+                       scrm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       scrm_clockdomains: clockdomains {
+                       };
+               };
+
                counter32k: counter@4a304000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x4a304000 0x20>;
                };
        };
 };
+
+/include/ "omap44xx-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap443x-clocks.dtsi b/arch/arm/boot/dts/omap443x-clocks.dtsi
new file mode 100644 (file)
index 0000000..2bd2166
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Device Tree Source for OMAP4 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm_clocks {
+       bandgap_fclk: bandgap_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1888>;
+       };
+};
index ab607a19a6137fe0c9f3fa779f6934131cc623f3..8c1cfad30d603714ce267820186dd8c6635ff923 100644 (file)
@@ -44,3 +44,5 @@
                };
        };
 };
+
+/include/ "omap443x-clocks.dtsi"
index 11566bed00358485634f1def11ffb980a2a48981..6b32f520741a9cb1398bf586a614a9358f04d3e5 100644 (file)
@@ -52,3 +52,5 @@
                };
        };
 };
+
+/include/ "omap446x-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap446x-clocks.dtsi b/arch/arm/boot/dts/omap446x-clocks.dtsi
new file mode 100644 (file)
index 0000000..be033e9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Device Tree Source for OMAP4 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&prm_clocks {
+       div_ts_ck: div_ts_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&l4_wkup_clk_mux_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1888>;
+               ti,dividers = <8>, <16>, <32>;
+       };
+
+       bandgap_ts_fclk: bandgap_ts_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&div_ts_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1888>;
+       };
+};
diff --git a/arch/arm/boot/dts/omap44xx-clocks.dtsi b/arch/arm/boot/dts/omap44xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..c821ff5
--- /dev/null
@@ -0,0 +1,1651 @@
+/*
+ * Device Tree Source for OMAP4 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm1_clocks {
+       extalt_clkin_ck: extalt_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <59000000>;
+       };
+
+       pad_clks_src_ck: pad_clks_src_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       pad_clks_ck: pad_clks_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pad_clks_src_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0108>;
+       };
+
+       pad_slimbus_core_clks_ck: pad_slimbus_core_clks_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       secure_32k_clk_src_ck: secure_32k_clk_src_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       slimbus_src_clk: slimbus_src_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       slimbus_clk: slimbus_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&slimbus_src_clk>;
+               ti,bit-shift = <10>;
+               reg = <0x0108>;
+       };
+
+       sys_32k_ck: sys_32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       virt_12000000_ck: virt_12000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       virt_13000000_ck: virt_13000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <13000000>;
+       };
+
+       virt_16800000_ck: virt_16800000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16800000>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       virt_27000000_ck: virt_27000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <27000000>;
+       };
+
+       virt_38400000_ck: virt_38400000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <38400000>;
+       };
+
+       tie_low_clock_ck: tie_low_clock_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       utmi_phy_clkout_ck: utmi_phy_clkout_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       xclk60mhsp1_ck: xclk60mhsp1_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       xclk60mhsp2_ck: xclk60mhsp2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       xclk60motg_ck: xclk60motg_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       dpll_abe_ck: dpll_abe_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-m4xen-clock";
+               clocks = <&abe_dpll_refclk_mux_ck>, <&abe_dpll_bypass_clk_mux_ck>;
+               reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
+       };
+
+       dpll_abe_x2_ck: dpll_abe_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_abe_ck>;
+               reg = <0x01f0>;
+       };
+
+       dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       abe_24m_fclk: abe_24m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       abe_clk: abe_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               ti,max-div = <4>;
+               reg = <0x0108>;
+               ti,index-power-of-two;
+       };
+
+       aess_fclk: aess_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&abe_clk>;
+               ti,bit-shift = <24>;
+               ti,max-div = <2>;
+               reg = <0x0528>;
+       };
+
+       dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f4>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_abe_m3x2_ck>;
+               ti,bit-shift = <23>;
+               reg = <0x012c>;
+       };
+
+       dpll_core_ck: dpll_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-core-clock";
+               clocks = <&sys_clkin_ck>, <&core_hsd_byp_clk_mux_ck>;
+               reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>;
+       };
+
+       dpll_core_x2_ck: dpll_core_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_core_ck>;
+       };
+
+       dpll_core_m6x2_ck: dpll_core_m6x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0140>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m2_ck: dpll_core_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0130>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       ddrphy_ck: ddrphy_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       dpll_core_m5x2_ck: dpll_core_m5x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x013c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       div_core_ck: div_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_m5x2_ck>;
+               reg = <0x0100>;
+               ti,max-div = <2>;
+       };
+
+       div_iva_hs_clk: div_iva_hs_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_m5x2_ck>;
+               ti,max-div = <4>;
+               reg = <0x01dc>;
+               ti,index-power-of-two;
+       };
+
+       div_mpu_hs_clk: div_mpu_hs_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_m5x2_ck>;
+               ti,max-div = <4>;
+               reg = <0x019c>;
+               ti,index-power-of-two;
+       };
+
+       dpll_core_m4x2_ck: dpll_core_m4x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0138>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dll_clk_div_ck: dll_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_m4x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       dpll_abe_m2_ck: dpll_abe_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_ck>;
+               ti,max-div = <31>;
+               reg = <0x01f0>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_core_m3x2_gate_ck: dpll_core_m3x2_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0134>;
+       };
+
+       dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0134>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_core_m3x2_ck: dpll_core_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&dpll_core_m3x2_gate_ck>, <&dpll_core_m3x2_div_ck>;
+       };
+
+       dpll_core_m7x2_ck: dpll_core_m7x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0144>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&div_iva_hs_clk>;
+               ti,bit-shift = <23>;
+               reg = <0x01ac>;
+       };
+
+       dpll_iva_ck: dpll_iva_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&iva_hsd_byp_clk_mux_ck>;
+               reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>;
+       };
+
+       dpll_iva_x2_ck: dpll_iva_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_iva_ck>;
+       };
+
+       dpll_iva_m4x2_ck: dpll_iva_m4x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_iva_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_iva_m5x2_ck: dpll_iva_m5x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_iva_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01bc>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_mpu_ck: dpll_mpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&div_mpu_hs_clk>;
+               reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
+       };
+
+       dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_mpu_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0170>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       per_hs_clk_div_ck: per_hs_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       usb_hs_clk_div_ck: usb_hs_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <3>;
+       };
+
+       l3_div_ck: l3_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&div_core_ck>;
+               ti,bit-shift = <4>;
+               ti,max-div = <2>;
+               reg = <0x0100>;
+       };
+
+       l4_div_ck: l4_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <8>;
+               ti,max-div = <2>;
+               reg = <0x0100>;
+       };
+
+       lp_clk_div_ck: lp_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       mpu_periphclk: mpu_periphclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_mpu_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       ocp_abe_iclk: ocp_abe_iclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&aess_fclk>;
+               ti,bit-shift = <24>;
+               reg = <0x0528>;
+               ti,dividers = <2>, <1>;
+       };
+
+       per_abe_24m_fclk: per_abe_24m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       dmic_sync_mux_ck: dmic_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
+               ti,bit-shift = <25>;
+               reg = <0x0538>;
+       };
+
+       func_dmic_abe_gfclk: func_dmic_abe_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0538>;
+       };
+
+       mcasp_sync_mux_ck: mcasp_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
+               ti,bit-shift = <25>;
+               reg = <0x0540>;
+       };
+
+       func_mcasp_abe_gfclk: func_mcasp_abe_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0540>;
+       };
+
+       mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
+               ti,bit-shift = <25>;
+               reg = <0x0548>;
+       };
+
+       func_mcbsp1_gfclk: func_mcbsp1_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0548>;
+       };
+
+       mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
+               ti,bit-shift = <25>;
+               reg = <0x0550>;
+       };
+
+       func_mcbsp2_gfclk: func_mcbsp2_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0550>;
+       };
+
+       mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
+               ti,bit-shift = <25>;
+               reg = <0x0558>;
+       };
+
+       func_mcbsp3_gfclk: func_mcbsp3_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0558>;
+       };
+
+       slimbus1_fclk_1: slimbus1_fclk_1 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_24m_clk>;
+               ti,bit-shift = <9>;
+               reg = <0x0560>;
+       };
+
+       slimbus1_fclk_0: slimbus1_fclk_0 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&abe_24m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x0560>;
+       };
+
+       slimbus1_fclk_2: slimbus1_fclk_2 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pad_clks_ck>;
+               ti,bit-shift = <10>;
+               reg = <0x0560>;
+       };
+
+       slimbus1_slimbus_clk: slimbus1_slimbus_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&slimbus_clk>;
+               ti,bit-shift = <11>;
+               reg = <0x0560>;
+       };
+
+       timer5_sync_mux: timer5_sync_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0568>;
+       };
+
+       timer6_sync_mux: timer6_sync_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0570>;
+       };
+
+       timer7_sync_mux: timer7_sync_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0578>;
+       };
+
+       timer8_sync_mux: timer8_sync_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0580>;
+       };
+
+       dummy_ck: dummy_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+};
+&prm_clocks {
+       sys_clkin_ck: sys_clkin_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+               reg = <0x0110>;
+               ti,index-starts-at-one;
+       };
+
+       abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0108>;
+       };
+
+       abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               reg = <0x010c>;
+       };
+
+       dbgclk_mux_ck: dbgclk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&lp_clk_div_ck>;
+               reg = <0x0108>;
+       };
+
+       syc_clk_div_ck: syc_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&sys_clkin_ck>;
+               reg = <0x0100>;
+               ti,max-div = <2>;
+       };
+
+       gpio1_dbclk: gpio1_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1838>;
+       };
+
+       dmt1_clk_mux: dmt1_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1840>;
+       };
+
+       usim_ck: usim_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m4x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1858>;
+               ti,dividers = <14>, <18>;
+       };
+
+       usim_fclk: usim_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&usim_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1858>;
+       };
+
+       pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>;
+               ti,bit-shift = <20>;
+               reg = <0x1a20>;
+       };
+
+       pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>;
+               ti,bit-shift = <22>;
+               reg = <0x1a20>;
+       };
+
+       stm_clk_div_ck: stm_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&pmd_stm_clock_mux_ck>;
+               ti,bit-shift = <27>;
+               ti,max-div = <64>;
+               reg = <0x1a20>;
+               ti,index-power-of-two;
+       };
+
+       trace_clk_div_div_ck: trace_clk_div_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&pmd_trace_clk_mux_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1a20>;
+               ti,dividers = <0>, <1>, <2>, <0>, <4>;
+       };
+
+       trace_clk_div_ck: trace_clk_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,clkdm-gate-clock";
+               clocks = <&trace_clk_div_div_ck>;
+       };
+};
+
+&prm_clockdomains {
+       emu_sys_clkdm: emu_sys_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&trace_clk_div_ck>;
+       };
+};
+
+&cm2_clocks {
+       per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&per_hs_clk_div_ck>;
+               ti,bit-shift = <23>;
+               reg = <0x014c>;
+       };
+
+       dpll_per_ck: dpll_per_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin_ck>, <&per_hsd_byp_clk_mux_ck>;
+               reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>;
+       };
+
+       dpll_per_m2_ck: dpll_per_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_ck>;
+               ti,max-div = <31>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_per_x2_ck: dpll_per_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_per_ck>;
+               reg = <0x0150>;
+       };
+
+       dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m3x2_gate_ck: dpll_per_m3x2_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0154>;
+       };
+
+       dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               reg = <0x0154>;
+               ti,index-starts-at-one;
+       };
+
+       dpll_per_m3x2_ck: dpll_per_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&dpll_per_m3x2_gate_ck>, <&dpll_per_m3x2_div_ck>;
+       };
+
+       dpll_per_m4x2_ck: dpll_per_m4x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0158>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m5x2_ck: dpll_per_m5x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x015c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m6x2_ck: dpll_per_m6x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0160>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m7x2_ck: dpll_per_m7x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0164>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_usb_ck: dpll_usb_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-j-type-clock";
+               clocks = <&sys_clkin_ck>, <&usb_hs_clk_div_ck>;
+               reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
+       };
+
+       dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck {
+               #clock-cells = <0>;
+               compatible = "ti,fixed-factor-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,clock-div = <1>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b4>;
+               ti,clock-mult = <1>;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_usb_m2_ck: dpll_usb_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0190>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       ducati_clk_mux_ck: ducati_clk_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&div_core_ck>, <&dpll_per_m6x2_ck>;
+               reg = <0x0100>;
+       };
+
+       func_12m_fclk: func_12m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       func_24m_clk: func_24m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_24mc_fclk: func_24mc_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       func_48m_fclk: func_48m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               reg = <0x0108>;
+               ti,dividers = <4>, <8>;
+       };
+
+       func_48mc_fclk: func_48mc_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_64m_fclk: func_64m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m4x2_ck>;
+               reg = <0x0108>;
+               ti,dividers = <2>, <4>;
+       };
+
+       func_96m_fclk: func_96m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               reg = <0x0108>;
+               ti,dividers = <2>, <4>;
+       };
+
+       init_60m_fclk: init_60m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               reg = <0x0104>;
+               ti,dividers = <1>, <8>;
+       };
+
+       per_abe_nc_fclk: per_abe_nc_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2_ck>;
+               reg = <0x0108>;
+               ti,max-div = <2>;
+       };
+
+       aes1_fck: aes1_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x15a0>;
+       };
+
+       aes2_fck: aes2_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x15a8>;
+       };
+
+       dss_sys_clk: dss_sys_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&syc_clk_div_ck>;
+               ti,bit-shift = <10>;
+               reg = <0x1120>;
+       };
+
+       dss_tv_clk: dss_tv_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&extalt_clkin_ck>;
+               ti,bit-shift = <11>;
+               reg = <0x1120>;
+       };
+
+       dss_dss_clk: dss_dss_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_per_m5x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1120>;
+               ti,set-rate-parent;
+       };
+
+       dss_48mhz_clk: dss_48mhz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48mc_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1120>;
+       };
+
+       dss_fck: dss_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x1120>;
+       };
+
+       fdif_fck: fdif_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m4x2_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <4>;
+               reg = <0x1028>;
+               ti,index-power-of-two;
+       };
+
+       gpio2_dbclk: gpio2_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1460>;
+       };
+
+       gpio3_dbclk: gpio3_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1468>;
+       };
+
+       gpio4_dbclk: gpio4_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1470>;
+       };
+
+       gpio5_dbclk: gpio5_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1478>;
+       };
+
+       gpio6_dbclk: gpio6_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1480>;
+       };
+
+       sgx_clk_mux: sgx_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_m7x2_ck>, <&dpll_per_m7x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1220>;
+       };
+
+       hsi_fck: hsi_fck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <4>;
+               reg = <0x1338>;
+               ti,index-power-of-two;
+       };
+
+       iss_ctrlclk: iss_ctrlclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_96m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1020>;
+       };
+
+       mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_96m_fclk>, <&per_abe_nc_fclk>;
+               ti,bit-shift = <25>;
+               reg = <0x14e0>;
+       };
+
+       per_mcbsp4_gfclk: per_mcbsp4_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp4_sync_mux_ck>, <&pad_clks_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x14e0>;
+       };
+
+       hsmmc1_fclk: hsmmc1_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_64m_fclk>, <&func_96m_fclk>;
+               ti,bit-shift = <24>;
+               reg = <0x1328>;
+       };
+
+       hsmmc2_fclk: hsmmc2_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_64m_fclk>, <&func_96m_fclk>;
+               ti,bit-shift = <24>;
+               reg = <0x1330>;
+       };
+
+       ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x13e0>;
+       };
+
+       sha2md5_fck: sha2md5_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x15c8>;
+       };
+
+       slimbus2_fclk_1: slimbus2_fclk_1 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&per_abe_24m_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1538>;
+       };
+
+       slimbus2_fclk_0: slimbus2_fclk_0 {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_24mc_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1538>;
+       };
+
+       slimbus2_slimbus_clk: slimbus2_slimbus_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pad_slimbus_core_clks_ck>;
+               ti,bit-shift = <10>;
+               reg = <0x1538>;
+       };
+
+       smartreflex_core_fck: smartreflex_core_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l4_wkup_clk_mux_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0638>;
+       };
+
+       smartreflex_iva_fck: smartreflex_iva_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l4_wkup_clk_mux_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0630>;
+       };
+
+       smartreflex_mpu_fck: smartreflex_mpu_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l4_wkup_clk_mux_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0628>;
+       };
+
+       cm2_dm10_mux: cm2_dm10_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1428>;
+       };
+
+       cm2_dm11_mux: cm2_dm11_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1430>;
+       };
+
+       cm2_dm2_mux: cm2_dm2_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1438>;
+       };
+
+       cm2_dm3_mux: cm2_dm3_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1440>;
+       };
+
+       cm2_dm4_mux: cm2_dm4_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1448>;
+       };
+
+       cm2_dm9_mux: cm2_dm9_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1450>;
+       };
+
+       usb_host_fs_fck: usb_host_fs_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48mc_fclk>;
+               ti,bit-shift = <1>;
+               reg = <0x13d0>;
+       };
+
+       utmi_p1_gfclk: utmi_p1_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&init_60m_fclk>, <&xclk60mhsp1_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&utmi_p1_gfclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1358>;
+       };
+
+       utmi_p2_gfclk: utmi_p2_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&init_60m_fclk>, <&xclk60mhsp2_ck>;
+               ti,bit-shift = <25>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&utmi_p2_gfclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <10>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,bit-shift = <13>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <11>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <12>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,bit-shift = <14>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_func48mclk: usb_host_hs_func48mclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48mc_fclk>;
+               ti,bit-shift = <15>;
+               reg = <0x1358>;
+       };
+
+       usb_host_hs_fck: usb_host_hs_fck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <1>;
+               reg = <0x1358>;
+       };
+
+       otg_60m_gfclk: otg_60m_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&utmi_phy_clkout_ck>, <&xclk60motg_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1360>;
+       };
+
+       usb_otg_hs_xclk: usb_otg_hs_xclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&otg_60m_gfclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1360>;
+       };
+
+       usb_otg_hs_ick: usb_otg_hs_ick {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3_div_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x1360>;
+       };
+
+       usb_phy_cm_clk32k: usb_phy_cm_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0640>;
+       };
+
+       usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <10>;
+               reg = <0x1368>;
+       };
+
+       usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1368>;
+       };
+
+       usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&init_60m_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1368>;
+       };
+
+       usb_tll_hs_ick: usb_tll_hs_ick {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l4_div_ck>;
+               ti,bit-shift = <0>;
+               reg = <0x1368>;
+       };
+};
+
+&cm2_clockdomains {
+       l3_init_clkdm: l3_init_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll_usb_ck>, <&usb_host_fs_fck>;
+       };
+};
+
+&scrm_clocks {
+       auxclk0_src_gate_ck: auxclk0_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0310>;
+       };
+
+       auxclk0_src_mux_ck: auxclk0_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0310>;
+       };
+
+       auxclk0_src_ck: auxclk0_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>;
+       };
+
+       auxclk0_ck: auxclk0_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk0_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0310>;
+       };
+
+       auxclk1_src_gate_ck: auxclk1_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0314>;
+       };
+
+       auxclk1_src_mux_ck: auxclk1_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0314>;
+       };
+
+       auxclk1_src_ck: auxclk1_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>;
+       };
+
+       auxclk1_ck: auxclk1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk1_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0314>;
+       };
+
+       auxclk2_src_gate_ck: auxclk2_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0318>;
+       };
+
+       auxclk2_src_mux_ck: auxclk2_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0318>;
+       };
+
+       auxclk2_src_ck: auxclk2_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>;
+       };
+
+       auxclk2_ck: auxclk2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk2_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0318>;
+       };
+
+       auxclk3_src_gate_ck: auxclk3_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x031c>;
+       };
+
+       auxclk3_src_mux_ck: auxclk3_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x031c>;
+       };
+
+       auxclk3_src_ck: auxclk3_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>;
+       };
+
+       auxclk3_ck: auxclk3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk3_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x031c>;
+       };
+
+       auxclk4_src_gate_ck: auxclk4_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0320>;
+       };
+
+       auxclk4_src_mux_ck: auxclk4_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0320>;
+       };
+
+       auxclk4_src_ck: auxclk4_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>;
+       };
+
+       auxclk4_ck: auxclk4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk4_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0320>;
+       };
+
+       auxclk5_src_gate_ck: auxclk5_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0324>;
+       };
+
+       auxclk5_src_mux_ck: auxclk5_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0324>;
+       };
+
+       auxclk5_src_ck: auxclk5_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk5_src_gate_ck>, <&auxclk5_src_mux_ck>;
+       };
+
+       auxclk5_ck: auxclk5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk5_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0324>;
+       };
+
+       auxclkreq0_ck: auxclkreq0_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0210>;
+       };
+
+       auxclkreq1_ck: auxclkreq1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0214>;
+       };
+
+       auxclkreq2_ck: auxclkreq2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0218>;
+       };
+
+       auxclkreq3_ck: auxclkreq3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x021c>;
+       };
+
+       auxclkreq4_ck: auxclkreq4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0220>;
+       };
+
+       auxclkreq5_ck: auxclkreq5_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0224>;
+       };
+};
index ab9a21ae82f34a7a19a27529a8c8bfd04bef5610..a72813a9663eccd7075b185489cbda4694fd0003 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
+               prm: prm@4ae06000 {
+                       compatible = "ti,omap5-prm";
+                       reg = <0x4ae06000 0x3000>;
+
+                       prm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       prm_clockdomains: clockdomains {
+                       };
+               };
+
+               cm_core_aon: cm_core_aon@4a004000 {
+                       compatible = "ti,omap5-cm-core-aon";
+                       reg = <0x4a004000 0x2000>;
+
+                       cm_core_aon_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm_core_aon_clockdomains: clockdomains {
+                       };
+               };
+
+               scrm: scrm@4ae0a000 {
+                       compatible = "ti,omap5-scrm";
+                       reg = <0x4ae0a000 0x2000>;
+
+                       scrm_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       scrm_clockdomains: clockdomains {
+                       };
+               };
+
+               cm_core: cm_core@4a008000 {
+                       compatible = "ti,omap5-cm-core";
+                       reg = <0x4a008000 0x3000>;
+
+                       cm_core_clocks: clocks {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       cm_core_clockdomains: clockdomains {
+                       };
+               };
+
                counter32k: counter@4ae04000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x4ae04000 0x40>;
                };
        };
 };
+
+/include/ "omap54xx-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/omap54xx-clocks.dtsi
new file mode 100644 (file)
index 0000000..d487fda
--- /dev/null
@@ -0,0 +1,1399 @@
+/*
+ * Device Tree Source for OMAP5 clock data
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ */
+&cm_core_aon_clocks {
+       pad_clks_src_ck: pad_clks_src_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       pad_clks_ck: pad_clks_ck {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&pad_clks_src_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0108>;
+       };
+
+       secure_32k_clk_src_ck: secure_32k_clk_src_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       slimbus_src_clk: slimbus_src_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       slimbus_clk: slimbus_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&slimbus_src_clk>;
+               ti,bit-shift = <10>;
+               reg = <0x0108>;
+       };
+
+       sys_32k_ck: sys_32k_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <32768>;
+       };
+
+       virt_12000000_ck: virt_12000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+       };
+
+       virt_13000000_ck: virt_13000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <13000000>;
+       };
+
+       virt_16800000_ck: virt_16800000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16800000>;
+       };
+
+       virt_19200000_ck: virt_19200000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <19200000>;
+       };
+
+       virt_26000000_ck: virt_26000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <26000000>;
+       };
+
+       virt_27000000_ck: virt_27000000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <27000000>;
+       };
+
+       virt_38400000_ck: virt_38400000_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <38400000>;
+       };
+
+       xclk60mhsp1_ck: xclk60mhsp1_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       xclk60mhsp2_ck: xclk60mhsp2_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <60000000>;
+       };
+
+       dpll_abe_ck: dpll_abe_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-m4xen-clock";
+               clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
+               reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
+       };
+
+       dpll_abe_x2_ck: dpll_abe_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_abe_ck>;
+       };
+
+       dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       abe_24m_fclk: abe_24m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <8>;
+       };
+
+       abe_clk: abe_clk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               ti,max-div = <4>;
+               reg = <0x0108>;
+               ti,index-power-of-two;
+       };
+
+       abe_iclk: abe_iclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&abe_clk>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       abe_lp_clk_div: abe_lp_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_abe_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01f4>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_ck: dpll_core_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-core-clock";
+               clocks = <&sys_clkin>, <&dpll_abe_m3x2_ck>;
+               reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>;
+       };
+
+       dpll_core_x2_ck: dpll_core_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_core_ck>;
+       };
+
+       dpll_core_h21x2_ck: dpll_core_h21x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       c2c_fclk: c2c_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h21x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       c2c_iclk: c2c_iclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&c2c_fclk>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       dpll_core_h11x2_ck: dpll_core_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0138>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h12x2_ck: dpll_core_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x013c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h13x2_ck: dpll_core_h13x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0140>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h14x2_ck: dpll_core_h14x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0144>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h22x2_ck: dpll_core_h22x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0154>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h23x2_ck: dpll_core_h23x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0158>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_h24x2_ck: dpll_core_h24x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x015c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m2_ck: dpll_core_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0130>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_core_m3x2_ck: dpll_core_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_core_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0134>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       iva_dpll_hs_clk_div: iva_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_iva_ck: dpll_iva_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin>, <&iva_dpll_hs_clk_div>;
+               reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>;
+       };
+
+       dpll_iva_x2_ck: dpll_iva_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_iva_ck>;
+       };
+
+       dpll_iva_h11x2_ck: dpll_iva_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_iva_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01b8>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_iva_h12x2_ck: dpll_iva_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_iva_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01bc>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       mpu_dpll_hs_clk_div: mpu_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_mpu_ck: dpll_mpu_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>;
+               reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
+       };
+
+       dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_mpu_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0170>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       per_dpll_hs_clk_div: per_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       usb_dpll_hs_clk_div: usb_dpll_hs_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_abe_m3x2_ck>;
+               clock-mult = <1>;
+               clock-div = <3>;
+       };
+
+       l3_iclk_div: l3_iclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_core_h12x2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gpu_l3_iclk: gpu_l3_iclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l3_iclk_div>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       l4_root_clk_div: l4_root_clk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&l3_iclk_div>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       slimbus1_slimbus_clk: slimbus1_slimbus_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&slimbus_clk>;
+               ti,bit-shift = <11>;
+               reg = <0x0560>;
+       };
+
+       aess_fclk: aess_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&abe_clk>;
+               ti,bit-shift = <24>;
+               ti,max-div = <2>;
+               reg = <0x0528>;
+       };
+
+       dmic_sync_mux_ck: dmic_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
+               ti,bit-shift = <26>;
+               reg = <0x0538>;
+       };
+
+       dmic_gfclk: dmic_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0538>;
+       };
+
+       mcasp_sync_mux_ck: mcasp_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
+               ti,bit-shift = <26>;
+               reg = <0x0540>;
+       };
+
+       mcasp_gfclk: mcasp_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0540>;
+       };
+
+       mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
+               ti,bit-shift = <26>;
+               reg = <0x0548>;
+       };
+
+       mcbsp1_gfclk: mcbsp1_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0548>;
+       };
+
+       mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
+               ti,bit-shift = <26>;
+               reg = <0x0550>;
+       };
+
+       mcbsp2_gfclk: mcbsp2_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0550>;
+       };
+
+       mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
+               ti,bit-shift = <26>;
+               reg = <0x0558>;
+       };
+
+       mcbsp3_gfclk: mcbsp3_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
+               ti,bit-shift = <24>;
+               reg = <0x0558>;
+       };
+
+       timer5_gfclk_mux: timer5_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0568>;
+       };
+
+       timer6_gfclk_mux: timer6_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0570>;
+       };
+
+       timer7_gfclk_mux: timer7_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0578>;
+       };
+
+       timer8_gfclk_mux: timer8_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x0580>;
+       };
+
+       dummy_ck: dummy_ck {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+};
+&prm_clocks {
+       sys_clkin: sys_clkin {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
+               reg = <0x0110>;
+               ti,index-starts-at-one;
+       };
+
+       abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               reg = <0x0108>;
+       };
+
+       abe_dpll_clk_mux: abe_dpll_clk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               reg = <0x010c>;
+       };
+
+       custefuse_sys_gfclk_div: custefuse_sys_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       dss_syc_gfclk_div: dss_syc_gfclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&sys_clkin>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       wkupaon_iclk_mux: wkupaon_iclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&abe_lp_clk_div>;
+               reg = <0x0108>;
+       };
+
+       l3instr_ts_gclk_div: l3instr_ts_gclk_div {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&wkupaon_iclk_mux>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       gpio1_dbclk: gpio1_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1938>;
+       };
+
+       timer1_gfclk_mux: timer1_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1940>;
+       };
+};
+&cm_core_clocks {
+       dpll_per_ck: dpll_per_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin>, <&per_dpll_hs_clk_div>;
+               reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>;
+       };
+
+       dpll_per_x2_ck: dpll_per_x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-x2-clock";
+               clocks = <&dpll_per_ck>;
+       };
+
+       dpll_per_h11x2_ck: dpll_per_h11x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0158>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_h12x2_ck: dpll_per_h12x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x015c>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_h14x2_ck: dpll_per_h14x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <63>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0164>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m2_ck: dpll_per_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0150>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_per_m3x2_ck: dpll_per_m3x2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_x2_ck>;
+               ti,max-div = <31>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0154>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_unipro1_ck: dpll_unipro1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin>, <&sys_clkin>;
+               reg = <0x0200>, <0x0204>, <0x020c>, <0x0208>;
+       };
+
+       dpll_unipro1_clkdcoldo: dpll_unipro1_clkdcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_unipro1_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_unipro1_m2_ck: dpll_unipro1_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_unipro1_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0210>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_unipro2_ck: dpll_unipro2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-clock";
+               clocks = <&sys_clkin>, <&sys_clkin>;
+               reg = <0x01c0>, <0x01c4>, <0x01cc>, <0x01c8>;
+       };
+
+       dpll_unipro2_clkdcoldo: dpll_unipro2_clkdcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_unipro2_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_unipro2_m2_ck: dpll_unipro2_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_unipro2_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x01d0>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       dpll_usb_ck: dpll_usb_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap4-dpll-j-type-clock";
+               clocks = <&sys_clkin>, <&usb_dpll_hs_clk_div>;
+               reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
+       };
+
+       dpll_usb_clkdcoldo: dpll_usb_clkdcoldo {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_usb_ck>;
+               clock-mult = <1>;
+               clock-div = <1>;
+       };
+
+       dpll_usb_m2_ck: dpll_usb_m2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_ck>;
+               ti,max-div = <127>;
+               ti,autoidle-shift = <8>;
+               reg = <0x0190>;
+               ti,index-starts-at-one;
+               ti,invert-autoidle-bit;
+       };
+
+       func_128m_clk: func_128m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_h11x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       func_12m_fclk: func_12m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <16>;
+       };
+
+       func_24m_clk: func_24m_clk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_48m_fclk: func_48m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <4>;
+       };
+
+       func_96m_fclk: func_96m_fclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
+       l3init_60m_fclk: l3init_60m_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               reg = <0x0104>;
+               ti,dividers = <1>, <8>;
+       };
+
+       dss_32khz_clk: dss_32khz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <11>;
+               reg = <0x1420>;
+       };
+
+       dss_48mhz_clk: dss_48mhz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_48m_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1420>;
+       };
+
+       dss_dss_clk: dss_dss_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_per_h12x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1420>;
+       };
+
+       dss_sys_clk: dss_sys_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dss_syc_gfclk_div>;
+               ti,bit-shift = <10>;
+               reg = <0x1420>;
+       };
+
+       gpio2_dbclk: gpio2_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1060>;
+       };
+
+       gpio3_dbclk: gpio3_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1068>;
+       };
+
+       gpio4_dbclk: gpio4_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1070>;
+       };
+
+       gpio5_dbclk: gpio5_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1078>;
+       };
+
+       gpio6_dbclk: gpio6_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1080>;
+       };
+
+       gpio7_dbclk: gpio7_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1110>;
+       };
+
+       gpio8_dbclk: gpio8_dbclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1118>;
+       };
+
+       iss_ctrlclk: iss_ctrlclk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&func_96m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1320>;
+       };
+
+       lli_txphy_clk: lli_txphy_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_unipro1_clkdcoldo>;
+               ti,bit-shift = <8>;
+               reg = <0x0f20>;
+       };
+
+       lli_txphy_ls_clk: lli_txphy_ls_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_unipro1_m2_ck>;
+               ti,bit-shift = <9>;
+               reg = <0x0f20>;
+       };
+
+       mmc1_32khz_clk: mmc1_32khz_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x1628>;
+       };
+
+       sata_ref_clk: sata_ref_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_clkin>;
+               ti,bit-shift = <8>;
+               reg = <0x1688>;
+       };
+
+       usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,bit-shift = <13>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,bit-shift = <14>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_m2_ck>;
+               ti,bit-shift = <7>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <11>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <12>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <6>;
+               reg = <0x1658>;
+       };
+
+       utmi_p1_gfclk: utmi_p1_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3init_60m_fclk>, <&xclk60mhsp1_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&utmi_p1_gfclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1658>;
+       };
+
+       utmi_p2_gfclk: utmi_p2_gfclk {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&l3init_60m_fclk>, <&xclk60mhsp2_ck>;
+               ti,bit-shift = <25>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&utmi_p2_gfclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1658>;
+       };
+
+       usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <10>;
+               reg = <0x1658>;
+       };
+
+       usb_otg_ss_refclk960m: usb_otg_ss_refclk960m {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_usb_clkdcoldo>;
+               ti,bit-shift = <8>;
+               reg = <0x16f0>;
+       };
+
+       usb_phy_cm_clk32k: usb_phy_cm_clk32k {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&sys_32k_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0640>;
+       };
+
+       usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <8>;
+               reg = <0x1668>;
+       };
+
+       usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <9>;
+               reg = <0x1668>;
+       };
+
+       usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&l3init_60m_fclk>;
+               ti,bit-shift = <10>;
+               reg = <0x1668>;
+       };
+
+       fdif_fclk: fdif_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_h11x2_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <2>;
+               reg = <0x1328>;
+       };
+
+       gpu_core_gclk_mux: gpu_core_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1520>;
+       };
+
+       gpu_hyd_gclk_mux: gpu_hyd_gclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>;
+               ti,bit-shift = <25>;
+               reg = <0x1520>;
+       };
+
+       hsi_fclk: hsi_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               ti,max-div = <2>;
+               reg = <0x1638>;
+       };
+
+       mmc1_fclk_mux: mmc1_fclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1628>;
+       };
+
+       mmc1_fclk: mmc1_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc1_fclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <2>;
+               reg = <0x1628>;
+       };
+
+       mmc2_fclk_mux: mmc2_fclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1630>;
+       };
+
+       mmc2_fclk: mmc2_fclk {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&mmc2_fclk_mux>;
+               ti,bit-shift = <25>;
+               ti,max-div = <2>;
+               reg = <0x1630>;
+       };
+
+       timer10_gfclk_mux: timer10_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1028>;
+       };
+
+       timer11_gfclk_mux: timer11_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1030>;
+       };
+
+       timer2_gfclk_mux: timer2_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1038>;
+       };
+
+       timer3_gfclk_mux: timer3_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1040>;
+       };
+
+       timer4_gfclk_mux: timer4_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1048>;
+       };
+
+       timer9_gfclk_mux: timer9_gfclk_mux {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&sys_clkin>, <&sys_32k_ck>;
+               ti,bit-shift = <24>;
+               reg = <0x1050>;
+       };
+};
+
+&cm_core_clockdomains {
+       l3init_clkdm: l3init_clkdm {
+               compatible = "ti,clockdomain";
+               clocks = <&dpll_usb_ck>;
+       };
+};
+
+&scrm_clocks {
+       auxclk0_src_gate_ck: auxclk0_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0310>;
+       };
+
+       auxclk0_src_mux_ck: auxclk0_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0310>;
+       };
+
+       auxclk0_src_ck: auxclk0_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>;
+       };
+
+       auxclk0_ck: auxclk0_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk0_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0310>;
+       };
+
+       auxclk1_src_gate_ck: auxclk1_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0314>;
+       };
+
+       auxclk1_src_mux_ck: auxclk1_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0314>;
+       };
+
+       auxclk1_src_ck: auxclk1_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>;
+       };
+
+       auxclk1_ck: auxclk1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk1_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0314>;
+       };
+
+       auxclk2_src_gate_ck: auxclk2_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0318>;
+       };
+
+       auxclk2_src_mux_ck: auxclk2_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0318>;
+       };
+
+       auxclk2_src_ck: auxclk2_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>;
+       };
+
+       auxclk2_ck: auxclk2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk2_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0318>;
+       };
+
+       auxclk3_src_gate_ck: auxclk3_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x031c>;
+       };
+
+       auxclk3_src_mux_ck: auxclk3_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x031c>;
+       };
+
+       auxclk3_src_ck: auxclk3_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>;
+       };
+
+       auxclk3_ck: auxclk3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk3_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x031c>;
+       };
+
+       auxclk4_src_gate_ck: auxclk4_src_gate_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&dpll_core_m3x2_ck>;
+               ti,bit-shift = <8>;
+               reg = <0x0320>;
+       };
+
+       auxclk4_src_mux_ck: auxclk4_src_mux_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
+               ti,bit-shift = <1>;
+               reg = <0x0320>;
+       };
+
+       auxclk4_src_ck: auxclk4_src_ck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-clock";
+               clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>;
+       };
+
+       auxclk4_ck: auxclk4_ck {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&auxclk4_src_ck>;
+               ti,bit-shift = <16>;
+               ti,max-div = <16>;
+               reg = <0x0320>;
+       };
+
+       auxclkreq0_ck: auxclkreq0_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0210>;
+       };
+
+       auxclkreq1_ck: auxclkreq1_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0214>;
+       };
+
+       auxclkreq2_ck: auxclkreq2_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x0218>;
+       };
+
+       auxclkreq3_ck: auxclkreq3_ck {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
+               ti,bit-shift = <2>;
+               reg = <0x021c>;
+       };
+};
index 1e8b030dbefd8b2b19da27d9ca8ecabfaf610bba..b0df9761de6dc1109f727e0300ff91448f8fd55b 100644 (file)
@@ -731,7 +731,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
        kernel_data.end     = virt_to_phys(_end - 1);
 
        for_each_memblock(memory, region) {
-               res = memblock_virt_alloc(sizeof(*res), 0);
+               res = memblock_virt_alloc_low(sizeof(*res), 0);
                res->name  = "System RAM";
                res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
                res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
index 6f424eced1816914bf59e39e48608b50bb338fe5..b3738e616f197bef538f2610bd519ad066f8cddd 100644 (file)
@@ -236,32 +236,26 @@ static struct mc13xxx_led_platform_data moboard_led[] = {
        {
                .id = MC13783_LED_R1,
                .name = "coreboard-led-4:red",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_G1,
                .name = "coreboard-led-4:green",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_B1,
                .name = "coreboard-led-4:blue",
-               .max_current = 2,
        },
        {
                .id = MC13783_LED_R2,
                .name = "coreboard-led-5:red",
-               .max_current = 3,
        },
        {
                .id = MC13783_LED_G2,
                .name = "coreboard-led-5:green",
-               .max_current = 3,
        },
        {
                .id = MC13783_LED_B2,
                .name = "coreboard-led-5:blue",
-               .max_current = 3,
        },
 };
 
@@ -271,8 +265,14 @@ static struct mc13xxx_leds_platform_data moboard_leds = {
        .led_control[0] = MC13783_LED_C0_ENABLE | MC13783_LED_C0_ABMODE(0),
        .led_control[1] = MC13783_LED_C1_SLEWLIM,
        .led_control[2] = MC13783_LED_C2_SLEWLIM,
-       .led_control[3] = MC13783_LED_C3_PERIOD(0),
-       .led_control[4] = MC13783_LED_C3_PERIOD(0),
+       .led_control[3] = MC13783_LED_C3_PERIOD(0) |
+                         MC13783_LED_C3_CURRENT_R1(2) |
+                         MC13783_LED_C3_CURRENT_G1(2) |
+                         MC13783_LED_C3_CURRENT_B1(2),
+       .led_control[4] = MC13783_LED_C4_PERIOD(0) |
+                         MC13783_LED_C4_CURRENT_R2(3) |
+                         MC13783_LED_C4_CURRENT_G2(3) |
+                         MC13783_LED_C4_CURRENT_B2(3),
 };
 
 static struct mc13xxx_buttons_platform_data moboard_buttons = {
index 4191ae08f4c81a2c95059df01fac77f883f30b70..653b489479e0ee2d4166d6d033d315a1e56430e4 100644 (file)
@@ -76,6 +76,16 @@ config SOC_AM43XX
        select ARM_GIC
        select MACH_OMAP_GENERIC
 
+config SOC_DRA7XX
+       bool "TI DRA7XX"
+       depends on ARCH_MULTI_V7
+       select ARCH_OMAP2PLUS
+       select ARM_CPU_SUSPEND if PM
+       select ARM_GIC
+       select CPU_V7
+       select HAVE_SMP
+       select HAVE_ARM_ARCH_TIMER
+
 config ARCH_OMAP2PLUS
        bool
        select ARCH_HAS_BANDGAP
@@ -128,14 +138,6 @@ config SOC_HAS_REALTIME_COUNTER
        depends on SOC_OMAP5 || SOC_DRA7XX
        default y
 
-config SOC_DRA7XX
-       bool "TI DRA7XX"
-       select ARM_ARCH_TIMER
-       select CPU_V7
-       select ARM_GIC
-       select HAVE_SMP
-       select COMMON_CLK
-
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
 
index f78b177e8f4fd17849c3265200b319fc17d52198..e6eec6f72fd3ed76b30af03bb4923fbacc62af7c 100644 (file)
@@ -130,6 +130,7 @@ obj-$(CONFIG_SOC_AM33XX)            += $(voltagedomain-common)
 obj-$(CONFIG_SOC_AM43XX)               += $(voltagedomain-common)
 obj-$(CONFIG_SOC_OMAP5)                        += $(voltagedomain-common)
 obj-$(CONFIG_SOC_OMAP5)                += voltagedomains54xx_data.o
+obj-$(CONFIG_SOC_DRA7XX)               += $(voltagedomain-common)
 
 # OMAP powerdomain framework
 powerdomain-common                     += powerdomain.o powerdomain-common.o
@@ -184,12 +185,14 @@ obj-$(CONFIG_ARCH_OMAP3)          += clock34xx.o clkt34xx_dpll3m2.o
 obj-$(CONFIG_ARCH_OMAP3)               += clock3517.o clock36xx.o
 obj-$(CONFIG_ARCH_OMAP3)               += dpll3xxx.o cclock3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += clkt_iclk.o
-obj-$(CONFIG_ARCH_OMAP4)               += $(clock-common) cclock44xx_data.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(clock-common)
 obj-$(CONFIG_ARCH_OMAP4)               += dpll3xxx.o dpll44xx.o
 obj-$(CONFIG_SOC_AM33XX)               += $(clock-common) dpll3xxx.o
-obj-$(CONFIG_SOC_AM33XX)               += cclock33xx_data.o
 obj-$(CONFIG_SOC_OMAP5)                        += $(clock-common)
 obj-$(CONFIG_SOC_OMAP5)                        += dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_DRA7XX)               += $(clock-common)
+obj-$(CONFIG_SOC_DRA7XX)               += dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clock-common) dpll3xxx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)             += opp2420_data.o
diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
deleted file mode 100644 (file)
index 865d30e..0000000
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * AM33XX Clock data
- *
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Vaibhav Hiremath <hvaibhav@ti.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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk-private.h>
-#include <linux/clkdev.h>
-#include <linux/io.h>
-
-#include "am33xx.h"
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "control.h"
-#include "cm.h"
-#include "cm33xx.h"
-#include "cm-regbits-33xx.h"
-#include "prm.h"
-
-/* Modulemode control */
-#define AM33XX_MODULEMODE_HWCTRL_SHIFT         0
-#define AM33XX_MODULEMODE_SWCTRL_SHIFT         1
-
-/*LIST_HEAD(clocks);*/
-
-/* Root clocks */
-
-/* RTC 32k */
-DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0);
-
-/* On-Chip 32KHz RC OSC */
-DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0);
-
-/* Crystal input clks */
-DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
-
-/* Oscillator clock */
-/* 19.2, 24, 25 or 26 MHz */
-static const char *sys_clkin_ck_parents[] = {
-       "virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck",
-       "virt_26000000_ck",
-};
-
-/*
- * sys_clk in: input to the dpll and also used as funtional clock for,
- *   adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
- *
- */
-DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
-              AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
-              AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT,
-              AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH,
-              0, NULL);
-
-/* External clock - 12 MHz */
-DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0);
-
-/* Module clocks and DPLL outputs */
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
-       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_CORE,
-       .clk_bypass     = &sys_clkin_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = AM33XX_CM_CLKMODE_DPLL_CORE,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_CORE,
-       .mult_mask      = AM33XX_DPLL_MULT_MASK,
-       .div1_mask      = AM33XX_DPLL_DIV_MASK,
-       .enable_mask    = AM33XX_DPLL_EN_MASK,
-       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-/* CLKDCOLDO output */
-static const char *dpll_core_ck_parents[] = {
-       "sys_clkin_ck",
-};
-
-static struct clk dpll_core_ck;
-
-static const struct clk_ops dpll_core_ck_ops = {
-       .recalc_rate    = &omap3_dpll_recalc,
-       .get_parent     = &omap2_init_dpll_parent,
-};
-
-static struct clk_hw_omap dpll_core_ck_hw = {
-       .hw     = {
-               .clk    = &dpll_core_ck,
-       },
-       .dpll_data      = &dpll_core_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
-
-static const char *dpll_core_x2_ck_parents[] = {
-       "dpll_core_ck",
-};
-
-static struct clk dpll_core_x2_ck;
-
-static const struct clk_ops dpll_x2_ck_ops = {
-       .recalc_rate    = &omap3_clkoutx2_recalc,
-};
-
-static struct clk_hw_omap dpll_core_x2_ck_hw = {
-       .hw     = {
-               .clk    = &dpll_core_x2_ck,
-       },
-       .flags          = CLOCK_CLKOUTX2,
-};
-
-DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops);
-
-DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
-                  0x0, AM33XX_CM_DIV_M4_DPLL_CORE,
-                  AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT,
-                  AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
-                  NULL);
-
-DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
-                  0x0, AM33XX_CM_DIV_M5_DPLL_CORE,
-                  AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT,
-                  AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH,
-                  CLK_DIVIDER_ONE_BASED, NULL);
-
-DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck,
-                  0x0, AM33XX_CM_DIV_M6_DPLL_CORE,
-                  AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT,
-                  AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH,
-                  CLK_DIVIDER_ONE_BASED, NULL);
-
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
-       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_MPU,
-       .clk_bypass     = &sys_clkin_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = AM33XX_CM_CLKMODE_DPLL_MPU,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_MPU,
-       .mult_mask      = AM33XX_DPLL_MULT_MASK,
-       .div1_mask      = AM33XX_DPLL_DIV_MASK,
-       .enable_mask    = AM33XX_DPLL_EN_MASK,
-       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_mpu_ck;
-
-static const struct clk_ops dpll_mpu_ck_ops = {
-       .enable         = &omap3_noncore_dpll_enable,
-       .disable        = &omap3_noncore_dpll_disable,
-       .recalc_rate    = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
-       .set_rate       = &omap3_noncore_dpll_set_rate,
-       .get_parent     = &omap2_init_dpll_parent,
-};
-
-static struct clk_hw_omap dpll_mpu_ck_hw = {
-       .hw = {
-               .clk    = &dpll_mpu_ck,
-       },
-       .dpll_data      = &dpll_mpu_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_mpu_ck_ops);
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-DEFINE_CLK_DIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck,
-                  0x0, AM33XX_CM_DIV_M2_DPLL_MPU, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
-                  AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
-
-/* DPLL_DDR */
-static struct dpll_data dpll_ddr_dd = {
-       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_DDR,
-       .clk_bypass     = &sys_clkin_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = AM33XX_CM_CLKMODE_DPLL_DDR,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_DDR,
-       .mult_mask      = AM33XX_DPLL_MULT_MASK,
-       .div1_mask      = AM33XX_DPLL_DIV_MASK,
-       .enable_mask    = AM33XX_DPLL_EN_MASK,
-       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_ddr_ck;
-
-static const struct clk_ops dpll_ddr_ck_ops = {
-       .recalc_rate    = &omap3_dpll_recalc,
-       .get_parent     = &omap2_init_dpll_parent,
-       .round_rate     = &omap2_dpll_round_rate,
-       .set_rate       = &omap3_noncore_dpll_set_rate,
-};
-
-static struct clk_hw_omap dpll_ddr_ck_hw = {
-       .hw = {
-               .clk    = &dpll_ddr_ck,
-       },
-       .dpll_data      = &dpll_ddr_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_ddr_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-DEFINE_CLK_DIVIDER(dpll_ddr_m2_ck, "dpll_ddr_ck", &dpll_ddr_ck,
-                  0x0, AM33XX_CM_DIV_M2_DPLL_DDR,
-                  AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
-                  CLK_DIVIDER_ONE_BASED, NULL);
-
-/* emif_fck functional clock */
-DEFINE_CLK_FIXED_FACTOR(dpll_ddr_m2_div2_ck, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck,
-                       0x0, 1, 2);
-
-/* DPLL_DISP */
-static struct dpll_data dpll_disp_dd = {
-       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_DISP,
-       .clk_bypass     = &sys_clkin_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = AM33XX_CM_CLKMODE_DPLL_DISP,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_DISP,
-       .mult_mask      = AM33XX_DPLL_MULT_MASK,
-       .div1_mask      = AM33XX_DPLL_DIV_MASK,
-       .enable_mask    = AM33XX_DPLL_EN_MASK,
-       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-/* CLKOUT: fdpll/M2 */
-static struct clk dpll_disp_ck;
-
-static struct clk_hw_omap dpll_disp_ck_hw = {
-       .hw = {
-               .clk    = &dpll_disp_ck,
-       },
-       .dpll_data      = &dpll_disp_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
-
-/*
- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
- * and ALT_CLK1/2)
- */
-DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck,
-                  CLK_SET_RATE_PARENT, AM33XX_CM_DIV_M2_DPLL_DISP,
-                  AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
-                  CLK_DIVIDER_ONE_BASED, NULL);
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
-       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_PERIPH,
-       .clk_bypass     = &sys_clkin_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = AM33XX_CM_CLKMODE_DPLL_PER,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_PER,
-       .mult_mask      = AM33XX_DPLL_MULT_PERIPH_MASK,
-       .div1_mask      = AM33XX_DPLL_PER_DIV_MASK,
-       .enable_mask    = AM33XX_DPLL_EN_MASK,
-       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-       .flags          = DPLL_J_TYPE,
-};
-
-/* CLKDCOLDO */
-static struct clk dpll_per_ck;
-
-static struct clk_hw_omap dpll_per_ck_hw = {
-       .hw     = {
-               .clk    = &dpll_per_ck,
-       },
-       .dpll_data      = &dpll_per_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
-
-/* CLKOUT: fdpll/M2 */
-DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
-                  AM33XX_CM_DIV_M2_DPLL_PER, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
-                  AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED,
-                  NULL);
-
-DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_wkupdm_ck, "dpll_per_m2_ck",
-                       &dpll_per_m2_ck, 0x0, 1, 4);
-
-DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_ck, "dpll_per_m2_ck",
-                       &dpll_per_m2_ck, 0x0, 1, 4);
-
-DEFINE_CLK_FIXED_FACTOR(dpll_core_m4_div2_ck, "dpll_core_m4_ck",
-                       &dpll_core_m4_ck, 0x0, 1, 2);
-
-DEFINE_CLK_FIXED_FACTOR(l4_rtc_gclk, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
-                       1, 2);
-
-DEFINE_CLK_FIXED_FACTOR(clk_24mhz, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1,
-                       8);
-
-/*
- * Below clock nodes describes clockdomains derived out
- * of core clock.
- */
-static const struct clk_ops clk_ops_null = {
-};
-
-static const char *l3_gclk_parents[] = {
-       "dpll_core_m4_ck"
-};
-
-static struct clk l3_gclk;
-DEFINE_STRUCT_CLK_HW_OMAP(l3_gclk, NULL);
-DEFINE_STRUCT_CLK(l3_gclk, l3_gclk_parents, clk_ops_null);
-
-static struct clk l4hs_gclk;
-DEFINE_STRUCT_CLK_HW_OMAP(l4hs_gclk, NULL);
-DEFINE_STRUCT_CLK(l4hs_gclk, l3_gclk_parents, clk_ops_null);
-
-static const char *l3s_gclk_parents[] = {
-       "dpll_core_m4_div2_ck"
-};
-
-static struct clk l3s_gclk;
-DEFINE_STRUCT_CLK_HW_OMAP(l3s_gclk, NULL);
-DEFINE_STRUCT_CLK(l3s_gclk, l3s_gclk_parents, clk_ops_null);
-
-static struct clk l4fw_gclk;
-DEFINE_STRUCT_CLK_HW_OMAP(l4fw_gclk, NULL);
-DEFINE_STRUCT_CLK(l4fw_gclk, l3s_gclk_parents, clk_ops_null);
-
-static struct clk l4ls_gclk;
-DEFINE_STRUCT_CLK_HW_OMAP(l4ls_gclk, NULL);
-DEFINE_STRUCT_CLK(l4ls_gclk, l3s_gclk_parents, clk_ops_null);
-
-static struct clk sysclk_div_ck;
-DEFINE_STRUCT_CLK_HW_OMAP(sysclk_div_ck, NULL);
-DEFINE_STRUCT_CLK(sysclk_div_ck, l3_gclk_parents, clk_ops_null);
-
-/*
- * In order to match the clock domain with hwmod clockdomain entry,
- * separate clock nodes is required for the modules which are
- * directly getting their funtioncal clock from sys_clkin.
- */
-static struct clk adc_tsc_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(adc_tsc_fck, NULL);
-DEFINE_STRUCT_CLK(adc_tsc_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk dcan0_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(dcan0_fck, NULL);
-DEFINE_STRUCT_CLK(dcan0_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk dcan1_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(dcan1_fck, NULL);
-DEFINE_STRUCT_CLK(dcan1_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk mcasp0_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(mcasp0_fck, NULL);
-DEFINE_STRUCT_CLK(mcasp0_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk mcasp1_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(mcasp1_fck, NULL);
-DEFINE_STRUCT_CLK(mcasp1_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk smartreflex0_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(smartreflex0_fck, NULL);
-DEFINE_STRUCT_CLK(smartreflex0_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk smartreflex1_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL);
-DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk sha0_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(sha0_fck, NULL);
-DEFINE_STRUCT_CLK(sha0_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk aes0_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(aes0_fck, NULL);
-DEFINE_STRUCT_CLK(aes0_fck, dpll_core_ck_parents, clk_ops_null);
-
-static struct clk rng_fck;
-DEFINE_STRUCT_CLK_HW_OMAP(rng_fck, NULL);
-DEFINE_STRUCT_CLK(rng_fck, dpll_core_ck_parents, clk_ops_null);
-
-/*
- * Modules clock nodes
- *
- * The following clock leaf nodes are added for the moment because:
- *
- *  - hwmod data is not present for these modules, either hwmod
- *    control is not required or its not populated.
- *  - Driver code is not yet migrated to use hwmod/runtime pm
- *  - Modules outside kernel access (to disable them by default)
- *
- *     - mmu (gfx domain)
- *     - cefuse
- *     - usbotg_fck (its additional clock and not really a modulemode)
- *     - ieee5000
- */
-
-DEFINE_CLK_GATE(mmu_fck, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
-               AM33XX_CM_GFX_MMUDATA_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
-               AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
-               0x0, NULL);
-
-/*
- * clkdiv32 is generated from fixed division of 732.4219
- */
-DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732);
-
-static struct clk clkdiv32k_ick;
-
-static const char *clkdiv32k_ick_parent_names[] = {
-       "clkdiv32k_ck",
-};
-
-static const struct clk_ops clkdiv32k_ick_ops = {
-       .enable         = &omap2_dflt_clk_enable,
-       .disable        = &omap2_dflt_clk_disable,
-       .is_enabled     = &omap2_dflt_clk_is_enabled,
-       .init           = &omap2_init_clk_clkdm,
-};
-
-static struct clk_hw_omap clkdiv32k_ick_hw = {
-       .hw     = {
-               .clk    = &clkdiv32k_ick,
-       },
-       .enable_reg     = AM33XX_CM_PER_CLKDIV32K_CLKCTRL,
-       .enable_bit     = AM33XX_MODULEMODE_SWCTRL_SHIFT,
-       .clkdm_name     = "clk_24mhz_clkdm",
-};
-
-DEFINE_STRUCT_CLK(clkdiv32k_ick, clkdiv32k_ick_parent_names, clkdiv32k_ick_ops);
-
-/* "usbotg_fck" is an additional clock and not really a modulemode */
-DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0,
-               AM33XX_CM_CLKDCOLDO_DPLL_PER, AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(ieee5000_fck, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck,
-               0x0, AM33XX_CM_PER_IEEE5000_CLKCTRL,
-               AM33XX_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-/* Timers */
-static const struct clksel timer1_clkmux_sel[] = {
-       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-       { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
-       { .parent = &tclkin_ck, .rates = div_1_2_rates },
-       { .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
-       { .parent = &clk_32768_ck, .rates = div_1_4_rates },
-       { .parent = NULL },
-};
-
-static const char *timer1_ck_parents[] = {
-       "sys_clkin_ck", "clkdiv32k_ick", "tclkin_ck", "clk_rc32k_ck",
-       "clk_32768_ck",
-};
-
-static struct clk timer1_fck;
-
-static const struct clk_ops timer1_fck_ops = {
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-       .set_parent     = &omap2_clksel_set_parent,
-       .init           = &omap2_init_clk_clkdm,
-};
-
-static struct clk_hw_omap timer1_fck_hw = {
-       .hw     = {
-               .clk    = &timer1_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer1_clkmux_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER1MS_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_2_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer1_fck, timer1_ck_parents, timer1_fck_ops);
-
-static const struct clksel timer2_to_7_clk_sel[] = {
-       { .parent = &tclkin_ck, .rates = div_1_0_rates },
-       { .parent = &sys_clkin_ck, .rates = div_1_1_rates },
-       { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *timer2_to_7_ck_parents[] = {
-       "tclkin_ck", "sys_clkin_ck", "clkdiv32k_ick",
-};
-
-static struct clk timer2_fck;
-
-static struct clk_hw_omap timer2_fck_hw = {
-       .hw     = {
-               .clk    = &timer2_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER2_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer2_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-static struct clk timer3_fck;
-
-static struct clk_hw_omap timer3_fck_hw = {
-       .hw     = {
-               .clk    = &timer3_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER3_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer3_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-static struct clk timer4_fck;
-
-static struct clk_hw_omap timer4_fck_hw = {
-       .hw     = {
-               .clk    = &timer4_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER4_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer4_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-static struct clk timer5_fck;
-
-static struct clk_hw_omap timer5_fck_hw = {
-       .hw     = {
-               .clk    = &timer5_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER5_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer5_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-static struct clk timer6_fck;
-
-static struct clk_hw_omap timer6_fck_hw = {
-       .hw     = {
-               .clk    = &timer6_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER6_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer6_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-static struct clk timer7_fck;
-
-static struct clk_hw_omap timer7_fck_hw = {
-       .hw     = {
-               .clk    = &timer7_fck,
-       },
-       .clkdm_name     = "l4ls_clkdm",
-       .clksel         = timer2_to_7_clk_sel,
-       .clksel_reg     = AM33XX_CLKSEL_TIMER7_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(timer7_fck, timer2_to_7_ck_parents, timer1_fck_ops);
-
-DEFINE_CLK_FIXED_FACTOR(cpsw_125mhz_gclk,
-                       "dpll_core_m5_ck",
-                       &dpll_core_m5_ck,
-                       0x0,
-                       1, 2);
-
-static const struct clk_ops cpsw_fck_ops = {
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-       .set_parent     = &omap2_clksel_set_parent,
-};
-
-static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
-       { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
-       { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static const char *cpsw_cpts_rft_ck_parents[] = {
-       "dpll_core_m5_ck", "dpll_core_m4_ck",
-};
-
-static struct clk cpsw_cpts_rft_clk;
-
-static struct clk_hw_omap cpsw_cpts_rft_clk_hw = {
-       .hw     = {
-               .clk    = &cpsw_cpts_rft_clk,
-       },
-       .clkdm_name     = "cpsw_125mhz_clkdm",
-       .clksel         = cpsw_cpts_rft_clkmux_sel,
-       .clksel_reg     = AM33XX_CM_CPTS_RFT_CLKSEL,
-       .clksel_mask    = AM33XX_CLKSEL_0_0_MASK,
-};
-
-DEFINE_STRUCT_CLK(cpsw_cpts_rft_clk, cpsw_cpts_rft_ck_parents, cpsw_fck_ops);
-
-
-/* gpio */
-static const char *gpio0_ck_parents[] = {
-       "clk_rc32k_ck", "clk_32768_ck", "clkdiv32k_ick",
-};
-
-static const struct clksel gpio0_dbclk_mux_sel[] = {
-       { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
-       { .parent = &clk_32768_ck, .rates = div_1_1_rates },
-       { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const struct clk_ops gpio_fck_ops = {
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-       .set_parent     = &omap2_clksel_set_parent,
-       .init           = &omap2_init_clk_clkdm,
-};
-
-static struct clk gpio0_dbclk_mux_ck;
-
-static struct clk_hw_omap gpio0_dbclk_mux_ck_hw = {
-       .hw     = {
-               .clk    = &gpio0_dbclk_mux_ck,
-       },
-       .clkdm_name     = "l4_wkup_clkdm",
-       .clksel         = gpio0_dbclk_mux_sel,
-       .clksel_reg     = AM33XX_CLKSEL_GPIO0_DBCLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(gpio0_dbclk_mux_ck, gpio0_ck_parents, gpio_fck_ops);
-
-DEFINE_CLK_GATE(gpio0_dbclk, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, 0x0,
-               AM33XX_CM_WKUP_GPIO0_CLKCTRL,
-               AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpio1_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
-               AM33XX_CM_PER_GPIO1_CLKCTRL,
-               AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpio2_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
-               AM33XX_CM_PER_GPIO2_CLKCTRL,
-               AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpio3_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0,
-               AM33XX_CM_PER_GPIO3_CLKCTRL,
-               AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, 0x0, NULL);
-
-
-static const char *pruss_ck_parents[] = {
-       "l3_gclk", "dpll_disp_m2_ck",
-};
-
-static const struct clksel pruss_ocp_clk_mux_sel[] = {
-       { .parent = &l3_gclk, .rates = div_1_0_rates },
-       { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static struct clk pruss_ocp_gclk;
-
-static struct clk_hw_omap pruss_ocp_gclk_hw = {
-       .hw     = {
-               .clk    = &pruss_ocp_gclk,
-       },
-       .clkdm_name     = "pruss_ocp_clkdm",
-       .clksel         = pruss_ocp_clk_mux_sel,
-       .clksel_reg     = AM33XX_CLKSEL_PRUSS_OCP_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_0_MASK,
-};
-
-DEFINE_STRUCT_CLK(pruss_ocp_gclk, pruss_ck_parents, gpio_fck_ops);
-
-static const char *lcd_ck_parents[] = {
-       "dpll_disp_m2_ck", "dpll_core_m5_ck", "dpll_per_m2_ck",
-};
-
-static const struct clksel lcd_clk_mux_sel[] = {
-       { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
-       { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
-       { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static struct clk lcd_gclk;
-
-static struct clk_hw_omap lcd_gclk_hw = {
-       .hw     = {
-               .clk    = &lcd_gclk,
-       },
-       .clkdm_name     = "lcdc_clkdm",
-       .clksel         = lcd_clk_mux_sel,
-       .clksel_reg     = AM33XX_CLKSEL_LCDC_PIXEL_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK_FLAGS(lcd_gclk, lcd_ck_parents,
-                       gpio_fck_ops, CLK_SET_RATE_PARENT);
-
-DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
-
-static const char *gfx_ck_parents[] = {
-       "dpll_core_m4_ck", "dpll_per_m2_ck",
-};
-
-static const struct clksel gfx_clksel_sel[] = {
-       { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
-       { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static struct clk gfx_fclk_clksel_ck;
-
-static struct clk_hw_omap gfx_fclk_clksel_ck_hw = {
-       .hw     = {
-               .clk    = &gfx_fclk_clksel_ck,
-       },
-       .clksel         = gfx_clksel_sel,
-       .clksel_reg     = AM33XX_CLKSEL_GFX_FCLK,
-       .clksel_mask    = AM33XX_CLKSEL_GFX_FCLK_MASK,
-};
-
-DEFINE_STRUCT_CLK(gfx_fclk_clksel_ck, gfx_ck_parents, gpio_fck_ops);
-
-static const struct clk_div_table div_1_0_2_1_rates[] = {
-       { .div = 1, .val = 0, },
-       { .div = 2, .val = 1, },
-       { .div = 0 },
-};
-
-DEFINE_CLK_DIVIDER_TABLE(gfx_fck_div_ck, "gfx_fclk_clksel_ck",
-                        &gfx_fclk_clksel_ck, 0x0, AM33XX_CLKSEL_GFX_FCLK,
-                        AM33XX_CLKSEL_0_0_SHIFT, AM33XX_CLKSEL_0_0_WIDTH,
-                        0x0, div_1_0_2_1_rates, NULL);
-
-static const char *sysclkout_ck_parents[] = {
-       "clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
-       "lcd_gclk",
-};
-
-static const struct clksel sysclkout_pre_sel[] = {
-       { .parent = &clk_32768_ck, .rates = div_1_0_rates },
-       { .parent = &l3_gclk, .rates = div_1_1_rates },
-       { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
-       { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
-       { .parent = &lcd_gclk, .rates = div_1_4_rates },
-       { .parent = NULL },
-};
-
-static struct clk sysclkout_pre_ck;
-
-static struct clk_hw_omap sysclkout_pre_ck_hw = {
-       .hw     = {
-               .clk    = &sysclkout_pre_ck,
-       },
-       .clksel         = sysclkout_pre_sel,
-       .clksel_reg     = AM33XX_CM_CLKOUT_CTRL,
-       .clksel_mask    = AM33XX_CLKOUT2SOURCE_MASK,
-};
-
-DEFINE_STRUCT_CLK(sysclkout_pre_ck, sysclkout_ck_parents, gpio_fck_ops);
-
-/* Divide by 8 clock rates with default clock is 1/1*/
-static const struct clk_div_table div8_rates[] = {
-       { .div = 1, .val = 0, },
-       { .div = 2, .val = 1, },
-       { .div = 3, .val = 2, },
-       { .div = 4, .val = 3, },
-       { .div = 5, .val = 4, },
-       { .div = 6, .val = 5, },
-       { .div = 7, .val = 6, },
-       { .div = 8, .val = 7, },
-       { .div = 0 },
-};
-
-DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
-                        0x0, AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2DIV_SHIFT,
-                        AM33XX_CLKOUT2DIV_WIDTH, 0x0, div8_rates, NULL);
-
-DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
-               AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
-
-static const char *wdt_ck_parents[] = {
-       "clk_rc32k_ck", "clkdiv32k_ick",
-};
-
-static const struct clksel wdt_clkmux_sel[] = {
-       { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
-       { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static struct clk wdt1_fck;
-
-static struct clk_hw_omap wdt1_fck_hw = {
-       .hw     = {
-               .clk    = &wdt1_fck,
-       },
-       .clkdm_name     = "l4_wkup_clkdm",
-       .clksel         = wdt_clkmux_sel,
-       .clksel_reg     = AM33XX_CLKSEL_WDT1_CLK,
-       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
-};
-
-DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
-
-static const char *pwmss_clk_parents[] = {
-       "dpll_per_m2_ck",
-};
-
-static const struct clk_ops ehrpwm_tbclk_ops = {
-       .enable         = &omap2_dflt_clk_enable,
-       .disable        = &omap2_dflt_clk_disable,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm0_tbclk, "l4ls_clkdm",
-                        NULL, NULL, 0,
-                        AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
-                        AM33XX_PWMSS0_TBCLKEN_SHIFT,
-                        NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm1_tbclk, "l4ls_clkdm",
-                        NULL, NULL, 0,
-                        AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
-                        AM33XX_PWMSS1_TBCLKEN_SHIFT,
-                        NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
-
-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm2_tbclk, "l4ls_clkdm",
-                        NULL, NULL, 0,
-                        AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
-                        AM33XX_PWMSS2_TBCLKEN_SHIFT,
-                        NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
-
-/*
- * debugss optional clocks
- */
-DEFINE_CLK_GATE(dbg_sysclk_ck, "sys_clkin_ck", &sys_clkin_ck,
-               0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-               AM33XX_OPTFCLKEN_DBGSYSCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(dbg_clka_ck, "dpll_core_m4_ck", &dpll_core_m4_ck,
-               0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-               AM33XX_OPTCLK_DEBUG_CLKA_SHIFT, 0x0, NULL);
-
-static const char *stm_pmd_clock_mux_ck_parents[] = {
-       "dbg_sysclk_ck", "dbg_clka_ck",
-};
-
-DEFINE_CLK_MUX(stm_pmd_clock_mux_ck, stm_pmd_clock_mux_ck_parents, NULL, 0x0,
-              AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_STM_PMD_CLKSEL_SHIFT,
-              AM33XX_STM_PMD_CLKSEL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_MUX(trace_pmd_clk_mux_ck, stm_pmd_clock_mux_ck_parents, NULL, 0x0,
-              AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-              AM33XX_TRC_PMD_CLKSEL_SHIFT,
-              AM33XX_TRC_PMD_CLKSEL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(stm_clk_div_ck, "stm_pmd_clock_mux_ck",
-                  &stm_pmd_clock_mux_ck, 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-                  AM33XX_STM_PMD_CLKDIVSEL_SHIFT,
-                  AM33XX_STM_PMD_CLKDIVSEL_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
-                  NULL);
-
-DEFINE_CLK_DIVIDER(trace_clk_div_ck, "trace_pmd_clk_mux_ck",
-                  &trace_pmd_clk_mux_ck, 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
-                  AM33XX_TRC_PMD_CLKDIVSEL_SHIFT,
-                  AM33XX_TRC_PMD_CLKDIVSEL_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
-                  NULL);
-
-/*
- * clkdev
- */
-static struct omap_clk am33xx_clks[] = {
-       CLK(NULL,       "clk_32768_ck",         &clk_32768_ck),
-       CLK(NULL,       "clk_rc32k_ck",         &clk_rc32k_ck),
-       CLK(NULL,       "virt_19200000_ck",     &virt_19200000_ck),
-       CLK(NULL,       "virt_24000000_ck",     &virt_24000000_ck),
-       CLK(NULL,       "virt_25000000_ck",     &virt_25000000_ck),
-       CLK(NULL,       "virt_26000000_ck",     &virt_26000000_ck),
-       CLK(NULL,       "sys_clkin_ck",         &sys_clkin_ck),
-       CLK(NULL,       "tclkin_ck",            &tclkin_ck),
-       CLK(NULL,       "dpll_core_ck",         &dpll_core_ck),
-       CLK(NULL,       "dpll_core_x2_ck",      &dpll_core_x2_ck),
-       CLK(NULL,       "dpll_core_m4_ck",      &dpll_core_m4_ck),
-       CLK(NULL,       "dpll_core_m5_ck",      &dpll_core_m5_ck),
-       CLK(NULL,       "dpll_core_m6_ck",      &dpll_core_m6_ck),
-       CLK(NULL,       "dpll_mpu_ck",          &dpll_mpu_ck),
-       CLK("cpu0",     NULL,                   &dpll_mpu_ck),
-       CLK(NULL,       "dpll_mpu_m2_ck",       &dpll_mpu_m2_ck),
-       CLK(NULL,       "dpll_ddr_ck",          &dpll_ddr_ck),
-       CLK(NULL,       "dpll_ddr_m2_ck",       &dpll_ddr_m2_ck),
-       CLK(NULL,       "dpll_ddr_m2_div2_ck",  &dpll_ddr_m2_div2_ck),
-       CLK(NULL,       "dpll_disp_ck",         &dpll_disp_ck),
-       CLK(NULL,       "dpll_disp_m2_ck",      &dpll_disp_m2_ck),
-       CLK(NULL,       "dpll_per_ck",          &dpll_per_ck),
-       CLK(NULL,       "dpll_per_m2_ck",       &dpll_per_m2_ck),
-       CLK(NULL,       "dpll_per_m2_div4_wkupdm_ck",   &dpll_per_m2_div4_wkupdm_ck),
-       CLK(NULL,       "dpll_per_m2_div4_ck",  &dpll_per_m2_div4_ck),
-       CLK(NULL,       "adc_tsc_fck",          &adc_tsc_fck),
-       CLK(NULL,       "cefuse_fck",           &cefuse_fck),
-       CLK(NULL,       "clkdiv32k_ck",         &clkdiv32k_ck),
-       CLK(NULL,       "clkdiv32k_ick",        &clkdiv32k_ick),
-       CLK(NULL,       "dcan0_fck",            &dcan0_fck),
-       CLK("481cc000.d_can",   NULL,           &dcan0_fck),
-       CLK(NULL,       "dcan1_fck",            &dcan1_fck),
-       CLK("481d0000.d_can",   NULL,           &dcan1_fck),
-       CLK(NULL,       "pruss_ocp_gclk",       &pruss_ocp_gclk),
-       CLK(NULL,       "mcasp0_fck",           &mcasp0_fck),
-       CLK(NULL,       "mcasp1_fck",           &mcasp1_fck),
-       CLK(NULL,       "mmu_fck",              &mmu_fck),
-       CLK(NULL,       "smartreflex0_fck",     &smartreflex0_fck),
-       CLK(NULL,       "smartreflex1_fck",     &smartreflex1_fck),
-       CLK(NULL,       "sha0_fck",             &sha0_fck),
-       CLK(NULL,       "aes0_fck",             &aes0_fck),
-       CLK(NULL,       "rng_fck",              &rng_fck),
-       CLK(NULL,       "timer1_fck",           &timer1_fck),
-       CLK(NULL,       "timer2_fck",           &timer2_fck),
-       CLK(NULL,       "timer3_fck",           &timer3_fck),
-       CLK(NULL,       "timer4_fck",           &timer4_fck),
-       CLK(NULL,       "timer5_fck",           &timer5_fck),
-       CLK(NULL,       "timer6_fck",           &timer6_fck),
-       CLK(NULL,       "timer7_fck",           &timer7_fck),
-       CLK(NULL,       "usbotg_fck",           &usbotg_fck),
-       CLK(NULL,       "ieee5000_fck",         &ieee5000_fck),
-       CLK(NULL,       "wdt1_fck",             &wdt1_fck),
-       CLK(NULL,       "l4_rtc_gclk",          &l4_rtc_gclk),
-       CLK(NULL,       "l3_gclk",              &l3_gclk),
-       CLK(NULL,       "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck),
-       CLK(NULL,       "l4hs_gclk",            &l4hs_gclk),
-       CLK(NULL,       "l3s_gclk",             &l3s_gclk),
-       CLK(NULL,       "l4fw_gclk",            &l4fw_gclk),
-       CLK(NULL,       "l4ls_gclk",            &l4ls_gclk),
-       CLK(NULL,       "clk_24mhz",            &clk_24mhz),
-       CLK(NULL,       "sysclk_div_ck",        &sysclk_div_ck),
-       CLK(NULL,       "cpsw_125mhz_gclk",     &cpsw_125mhz_gclk),
-       CLK(NULL,       "cpsw_cpts_rft_clk",    &cpsw_cpts_rft_clk),
-       CLK(NULL,       "gpio0_dbclk_mux_ck",   &gpio0_dbclk_mux_ck),
-       CLK(NULL,       "gpio0_dbclk",          &gpio0_dbclk),
-       CLK(NULL,       "gpio1_dbclk",          &gpio1_dbclk),
-       CLK(NULL,       "gpio2_dbclk",          &gpio2_dbclk),
-       CLK(NULL,       "gpio3_dbclk",          &gpio3_dbclk),
-       CLK(NULL,       "lcd_gclk",             &lcd_gclk),
-       CLK(NULL,       "mmc_clk",              &mmc_clk),
-       CLK(NULL,       "gfx_fclk_clksel_ck",   &gfx_fclk_clksel_ck),
-       CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck),
-       CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck),
-       CLK(NULL,       "clkout2_div_ck",       &clkout2_div_ck),
-       CLK(NULL,       "timer_32k_ck",         &clkdiv32k_ick),
-       CLK(NULL,       "timer_sys_ck",         &sys_clkin_ck),
-       CLK(NULL,       "dbg_sysclk_ck",        &dbg_sysclk_ck),
-       CLK(NULL,       "dbg_clka_ck",          &dbg_clka_ck),
-       CLK(NULL,       "stm_pmd_clock_mux_ck", &stm_pmd_clock_mux_ck),
-       CLK(NULL,       "trace_pmd_clk_mux_ck", &trace_pmd_clk_mux_ck),
-       CLK(NULL,       "stm_clk_div_ck",       &stm_clk_div_ck),
-       CLK(NULL,       "trace_clk_div_ck",     &trace_clk_div_ck),
-       CLK(NULL,       "clkout2_ck",           &clkout2_ck),
-       CLK("48300200.ehrpwm",  "tbclk",        &ehrpwm0_tbclk),
-       CLK("48302200.ehrpwm",  "tbclk",        &ehrpwm1_tbclk),
-       CLK("48304200.ehrpwm",  "tbclk",        &ehrpwm2_tbclk),
-};
-
-
-static const char *enable_init_clks[] = {
-       "dpll_ddr_m2_ck",
-       "dpll_mpu_m2_ck",
-       "l3_gclk",
-       "l4hs_gclk",
-       "l4fw_gclk",
-       "l4ls_gclk",
-       "clkout2_ck",   /* Required for external peripherals like, Audio codecs */
-};
-
-int __init am33xx_clk_init(void)
-{
-       if (soc_is_am33xx())
-               cpu_mask = RATE_IN_AM33XX;
-
-       omap_clocks_register(am33xx_clks, ARRAY_SIZE(am33xx_clks));
-
-       omap2_clk_disable_autoidle_all();
-
-       omap2_clk_enable_init_clocks(enable_init_clks,
-                                    ARRAY_SIZE(enable_init_clks));
-
-       /* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
-        *    physically present, in such a case HWMOD enabling of
-        *    clock would be failure with default parent. And timer
-        *    probe thinks clock is already enabled, this leads to
-        *    crash upon accessing timer 3 & 6 registers in probe.
-        *    Fix by setting parent of both these timers to master
-        *    oscillator clock.
-        */
-
-       clk_set_parent(&timer3_fck, &sys_clkin_ck);
-       clk_set_parent(&timer6_fck, &sys_clkin_ck);
-       /*
-        * The On-Chip 32K RC Osc clock is not an accurate clock-source as per
-        * the design/spec, so as a result, for example, timer which supposed
-        * to get expired @60Sec, but will expire somewhere ~@40Sec, which is
-        * not expected by any use-case, so change WDT1 clock source to PRCM
-        * 32KHz clock.
-        */
-       clk_set_parent(&wdt1_fck, &clkdiv32k_ick);
-
-       return 0;
-}
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
deleted file mode 100644 (file)
index ec0dc0b..0000000
+++ /dev/null
@@ -1,1735 +0,0 @@
-/*
- * OMAP4 Clock data
- *
- * Copyright (C) 2009-2012 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Paul Walmsley (paul@pwsan.com)
- * Rajendra Nayak (rnayak@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- * Mike Turquette (mturquette@ti.com)
- *
- * 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.
- *
- * XXX Some of the ES1 clocks have been removed/changed; once support
- * is added for discriminating clocks by ES level, these should be added back
- * in.
- *
- * XXX All of the remaining MODULEMODE clock nodes should be removed
- * once the drivers are updated to use pm_runtime or to use the appropriate
- * upstream clock node for rate/parent selection.
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/clk-private.h>
-#include <linux/clkdev.h>
-#include <linux/io.h>
-
-#include "soc.h"
-#include "iomap.h"
-#include "clock.h"
-#include "clock44xx.h"
-#include "cm1_44xx.h"
-#include "cm2_44xx.h"
-#include "cm-regbits-44xx.h"
-#include "prm44xx.h"
-#include "prm-regbits-44xx.h"
-#include "control.h"
-#include "scrm44xx.h"
-
-/* OMAP4 modulemode control */
-#define OMAP4430_MODULEMODE_HWCTRL_SHIFT               0
-#define OMAP4430_MODULEMODE_SWCTRL_SHIFT               1
-
-/*
- * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
- * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
- * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
- * half of this value.
- */
-#define OMAP4_DPLL_ABE_DEFFREQ                         98304000
-
-/*
- * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
- * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
- * locked frequency for the USB DPLL is 960MHz.
- */
-#define OMAP4_DPLL_USB_DEFFREQ                         960000000
-
-/* Root clocks */
-
-DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(pad_clks_src_ck, CLK_IS_ROOT, 12000000, 0x0);
-
-DEFINE_CLK_GATE(pad_clks_ck, "pad_clks_src_ck", &pad_clks_src_ck, 0x0,
-               OMAP4430_CM_CLKSEL_ABE, OMAP4430_PAD_CLKS_GATE_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_FIXED_RATE(pad_slimbus_core_clks_ck, CLK_IS_ROOT, 12000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(secure_32k_clk_src_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(slimbus_src_clk, CLK_IS_ROOT, 12000000, 0x0);
-
-DEFINE_CLK_GATE(slimbus_clk, "slimbus_src_clk", &slimbus_src_clk, 0x0,
-               OMAP4430_CM_CLKSEL_ABE, OMAP4430_SLIMBUS_CLK_GATE_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_FIXED_RATE(sys_32k_ck, CLK_IS_ROOT, 32768, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_12000000_ck, CLK_IS_ROOT, 12000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_13000000_ck, CLK_IS_ROOT, 13000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_16800000_ck, CLK_IS_ROOT, 16800000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_27000000_ck, CLK_IS_ROOT, 27000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(virt_38400000_ck, CLK_IS_ROOT, 38400000, 0x0);
-
-static const char *sys_clkin_ck_parents[] = {
-       "virt_12000000_ck", "virt_13000000_ck", "virt_16800000_ck",
-       "virt_19200000_ck", "virt_26000000_ck", "virt_27000000_ck",
-       "virt_38400000_ck",
-};
-
-DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0,
-              OMAP4430_CM_SYS_CLKSEL, OMAP4430_SYS_CLKSEL_SHIFT,
-              OMAP4430_SYS_CLKSEL_WIDTH, CLK_MUX_INDEX_ONE, NULL);
-
-DEFINE_CLK_FIXED_RATE(tie_low_clock_ck, CLK_IS_ROOT, 0, 0x0);
-
-DEFINE_CLK_FIXED_RATE(utmi_phy_clkout_ck, CLK_IS_ROOT, 60000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(xclk60mhsp1_ck, CLK_IS_ROOT, 60000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(xclk60mhsp2_ck, CLK_IS_ROOT, 60000000, 0x0);
-
-DEFINE_CLK_FIXED_RATE(xclk60motg_ck, CLK_IS_ROOT, 60000000, 0x0);
-
-/* Module clocks and DPLL outputs */
-
-static const char *abe_dpll_bypass_clk_mux_ck_parents[] = {
-       "sys_clkin_ck", "sys_32k_ck",
-};
-
-DEFINE_CLK_MUX(abe_dpll_bypass_clk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents,
-              NULL, 0x0, OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_SHIFT,
-              OMAP4430_CLKSEL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_MUX(abe_dpll_refclk_mux_ck, abe_dpll_bypass_clk_mux_ck_parents, NULL,
-              0x0, OMAP4430_CM_ABE_PLL_REF_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
-              OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
-
-/* DPLL_ABE */
-static struct dpll_data dpll_abe_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_ABE,
-       .clk_bypass     = &abe_dpll_bypass_clk_mux_ck,
-       .clk_ref        = &abe_dpll_refclk_mux_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_ABE,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_ABE,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_ABE,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .m4xen_mask     = OMAP4430_DPLL_REGM4XEN_MASK,
-       .lpmode_mask    = OMAP4430_DPLL_LPMODE_EN_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-
-static const char *dpll_abe_ck_parents[] = {
-       "abe_dpll_refclk_mux_ck",
-};
-
-static struct clk dpll_abe_ck;
-
-static const struct clk_ops dpll_abe_ck_ops = {
-       .enable         = &omap3_noncore_dpll_enable,
-       .disable        = &omap3_noncore_dpll_disable,
-       .recalc_rate    = &omap4_dpll_regm4xen_recalc,
-       .round_rate     = &omap4_dpll_regm4xen_round_rate,
-       .set_rate       = &omap3_noncore_dpll_set_rate,
-       .get_parent     = &omap2_init_dpll_parent,
-};
-
-static struct clk_hw_omap dpll_abe_ck_hw = {
-       .hw = {
-               .clk = &dpll_abe_ck,
-       },
-       .dpll_data      = &dpll_abe_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_abe_ck, dpll_abe_ck_parents, dpll_abe_ck_ops);
-
-static const char *dpll_abe_x2_ck_parents[] = {
-       "dpll_abe_ck",
-};
-
-static struct clk dpll_abe_x2_ck;
-
-static const struct clk_ops dpll_abe_x2_ck_ops = {
-       .recalc_rate    = &omap3_clkoutx2_recalc,
-};
-
-static struct clk_hw_omap dpll_abe_x2_ck_hw = {
-       .hw = {
-               .clk = &dpll_abe_x2_ck,
-       },
-       .flags          = CLOCK_CLKOUTX2,
-       .clksel_reg     = OMAP4430_CM_DIV_M2_DPLL_ABE,
-       .ops            = &clkhwops_omap4_dpllmx,
-};
-
-DEFINE_STRUCT_CLK(dpll_abe_x2_ck, dpll_abe_x2_ck_parents, dpll_abe_x2_ck_ops);
-
-static const struct clk_ops omap_hsdivider_ops = {
-       .set_rate       = &omap2_clksel_set_rate,
-       .recalc_rate    = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-};
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m2x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M2_DPLL_ABE,
-                         OMAP4430_DPLL_CLKOUT_DIV_MASK);
-
-DEFINE_CLK_FIXED_FACTOR(abe_24m_fclk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
-                       0x0, 1, 8);
-
-DEFINE_CLK_DIVIDER(abe_clk, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck, 0x0,
-                  OMAP4430_CM_CLKSEL_ABE, OMAP4430_CLKSEL_OPP_SHIFT,
-                  OMAP4430_CLKSEL_OPP_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_DIVIDER(aess_fclk, "abe_clk", &abe_clk, 0x0,
-                  OMAP4430_CM1_ABE_AESS_CLKCTRL,
-                  OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
-                  OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_abe_m3x2_ck, "dpll_abe_x2_ck", &dpll_abe_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M3_DPLL_ABE,
-                         OMAP4430_DPLL_CLKOUTHIF_DIV_MASK);
-
-static const char *core_hsd_byp_clk_mux_ck_parents[] = {
-       "sys_clkin_ck", "dpll_abe_m3x2_ck",
-};
-
-DEFINE_CLK_MUX(core_hsd_byp_clk_mux_ck, core_hsd_byp_clk_mux_ck_parents, NULL,
-              0x0, OMAP4430_CM_CLKSEL_DPLL_CORE,
-              OMAP4430_DPLL_BYP_CLKSEL_SHIFT, OMAP4430_DPLL_BYP_CLKSEL_WIDTH,
-              0x0, NULL);
-
-/* DPLL_CORE */
-static struct dpll_data dpll_core_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_CORE,
-       .clk_bypass     = &core_hsd_byp_clk_mux_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_CORE,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_CORE,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-
-static const char *dpll_core_ck_parents[] = {
-       "sys_clkin_ck", "core_hsd_byp_clk_mux_ck"
-};
-
-static struct clk dpll_core_ck;
-
-static const struct clk_ops dpll_core_ck_ops = {
-       .recalc_rate    = &omap3_dpll_recalc,
-       .get_parent     = &omap2_init_dpll_parent,
-};
-
-static struct clk_hw_omap dpll_core_ck_hw = {
-       .hw = {
-               .clk = &dpll_core_ck,
-       },
-       .dpll_data      = &dpll_core_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops);
-
-static const char *dpll_core_x2_ck_parents[] = {
-       "dpll_core_ck",
-};
-
-static struct clk dpll_core_x2_ck;
-
-static struct clk_hw_omap dpll_core_x2_ck_hw = {
-       .hw = {
-               .clk = &dpll_core_x2_ck,
-       },
-};
-
-DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_abe_x2_ck_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m6x2_ck, "dpll_core_x2_ck",
-                         &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M6_DPLL_CORE,
-                         OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m2_ck, "dpll_core_ck", &dpll_core_ck, 0x0,
-                         OMAP4430_CM_DIV_M2_DPLL_CORE,
-                         OMAP4430_DPLL_CLKOUT_DIV_MASK);
-
-DEFINE_CLK_FIXED_FACTOR(ddrphy_ck, "dpll_core_m2_ck", &dpll_core_m2_ck, 0x0, 1,
-                       2);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m5x2_ck, "dpll_core_x2_ck",
-                         &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M5_DPLL_CORE,
-                         OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
-
-DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0,
-                  OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT,
-                  OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
-                  0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, OMAP4430_CLKSEL_0_1_SHIFT,
-                  OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
-                  0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT,
-                  OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m4x2_ck, "dpll_core_x2_ck",
-                         &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M4_DPLL_CORE,
-                         OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
-
-DEFINE_CLK_FIXED_FACTOR(dll_clk_div_ck, "dpll_core_m4x2_ck", &dpll_core_m4x2_ck,
-                       0x0, 1, 2);
-
-DEFINE_CLK_DIVIDER(dpll_abe_m2_ck, "dpll_abe_ck", &dpll_abe_ck, 0x0,
-                  OMAP4430_CM_DIV_M2_DPLL_ABE, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
-                  OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
-
-static const struct clk_ops dpll_hsd_ops = {
-       .enable         = &omap2_dflt_clk_enable,
-       .disable        = &omap2_dflt_clk_disable,
-       .is_enabled     = &omap2_dflt_clk_is_enabled,
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-       .set_parent     = &omap2_clksel_set_parent,
-       .init           = &omap2_init_clk_clkdm,
-};
-
-static const struct clk_ops func_dmic_abe_gfclk_ops = {
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-       .set_parent     = &omap2_clksel_set_parent,
-};
-
-static const char *dpll_core_m3x2_ck_parents[] = {
-       "dpll_core_x2_ck",
-};
-
-static const struct clksel dpll_core_m3x2_div[] = {
-       { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
-       { .parent = NULL },
-};
-
-/* XXX Missing round_rate, set_rate in ops */
-DEFINE_CLK_OMAP_MUX_GATE(dpll_core_m3x2_ck, NULL, dpll_core_m3x2_div,
-                        OMAP4430_CM_DIV_M3_DPLL_CORE,
-                        OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-                        OMAP4430_CM_DIV_M3_DPLL_CORE,
-                        OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
-                        dpll_core_m3x2_ck_parents, dpll_hsd_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m7x2_ck, "dpll_core_x2_ck",
-                         &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M7_DPLL_CORE,
-                         OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
-
-static const char *iva_hsd_byp_clk_mux_ck_parents[] = {
-       "sys_clkin_ck", "div_iva_hs_clk",
-};
-
-DEFINE_CLK_MUX(iva_hsd_byp_clk_mux_ck, iva_hsd_byp_clk_mux_ck_parents, NULL,
-              0x0, OMAP4430_CM_CLKSEL_DPLL_IVA, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
-              OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
-
-/* DPLL_IVA */
-static struct dpll_data dpll_iva_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_IVA,
-       .clk_bypass     = &iva_hsd_byp_clk_mux_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_IVA,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_IVA,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-static const char *dpll_iva_ck_parents[] = {
-       "sys_clkin_ck", "iva_hsd_byp_clk_mux_ck"
-};
-
-static struct clk dpll_iva_ck;
-
-static const struct clk_ops dpll_ck_ops = {
-       .enable         = &omap3_noncore_dpll_enable,
-       .disable        = &omap3_noncore_dpll_disable,
-       .recalc_rate    = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
-       .set_rate       = &omap3_noncore_dpll_set_rate,
-       .get_parent     = &omap2_init_dpll_parent,
-};
-
-static struct clk_hw_omap dpll_iva_ck_hw = {
-       .hw = {
-               .clk = &dpll_iva_ck,
-       },
-       .dpll_data      = &dpll_iva_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_iva_ck_parents, dpll_ck_ops);
-
-static const char *dpll_iva_x2_ck_parents[] = {
-       "dpll_iva_ck",
-};
-
-static struct clk dpll_iva_x2_ck;
-
-static struct clk_hw_omap dpll_iva_x2_ck_hw = {
-       .hw = {
-               .clk = &dpll_iva_x2_ck,
-       },
-};
-
-DEFINE_STRUCT_CLK(dpll_iva_x2_ck, dpll_iva_x2_ck_parents, dpll_abe_x2_ck_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m4x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M4_DPLL_IVA,
-                         OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_iva_m5x2_ck, "dpll_iva_x2_ck", &dpll_iva_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M5_DPLL_IVA,
-                         OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
-
-/* DPLL_MPU */
-static struct dpll_data dpll_mpu_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_MPU,
-       .clk_bypass     = &div_mpu_hs_clk,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_MPU,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_MPU,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-static const char *dpll_mpu_ck_parents[] = {
-       "sys_clkin_ck", "div_mpu_hs_clk"
-};
-
-static struct clk dpll_mpu_ck;
-
-static struct clk_hw_omap dpll_mpu_ck_hw = {
-       .hw = {
-               .clk = &dpll_mpu_ck,
-       },
-       .dpll_data      = &dpll_mpu_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_mpu_ck_parents, dpll_ck_ops);
-
-DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck, 0x0,
-                         OMAP4430_CM_DIV_M2_DPLL_MPU,
-                         OMAP4430_DPLL_CLKOUT_DIV_MASK);
-
-DEFINE_CLK_FIXED_FACTOR(per_hs_clk_div_ck, "dpll_abe_m3x2_ck",
-                       &dpll_abe_m3x2_ck, 0x0, 1, 2);
-
-static const char *per_hsd_byp_clk_mux_ck_parents[] = {
-       "sys_clkin_ck", "per_hs_clk_div_ck",
-};
-
-DEFINE_CLK_MUX(per_hsd_byp_clk_mux_ck, per_hsd_byp_clk_mux_ck_parents, NULL,
-              0x0, OMAP4430_CM_CLKSEL_DPLL_PER, OMAP4430_DPLL_BYP_CLKSEL_SHIFT,
-              OMAP4430_DPLL_BYP_CLKSEL_WIDTH, 0x0, NULL);
-
-/* DPLL_PER */
-static struct dpll_data dpll_per_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_PER,
-       .clk_bypass     = &per_hsd_byp_clk_mux_ck,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_PER,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_PER,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_PER,
-       .mult_mask      = OMAP4430_DPLL_MULT_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .max_multiplier = 2047,
-       .max_divider    = 128,
-       .min_divider    = 1,
-};
-
-static const char *dpll_per_ck_parents[] = {
-       "sys_clkin_ck", "per_hsd_byp_clk_mux_ck"
-};
-
-static struct clk dpll_per_ck;
-
-static struct clk_hw_omap dpll_per_ck_hw = {
-       .hw = {
-               .clk = &dpll_per_ck,
-       },
-       .dpll_data      = &dpll_per_dd,
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_per_ck, dpll_per_ck_parents, dpll_ck_ops);
-
-DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
-                  OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
-                  OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
-
-static const char *dpll_per_x2_ck_parents[] = {
-       "dpll_per_ck",
-};
-
-static struct clk dpll_per_x2_ck;
-
-static struct clk_hw_omap dpll_per_x2_ck_hw = {
-       .hw = {
-               .clk = &dpll_per_x2_ck,
-       },
-       .flags          = CLOCK_CLKOUTX2,
-       .clksel_reg     = OMAP4430_CM_DIV_M2_DPLL_PER,
-       .ops            = &clkhwops_omap4_dpllmx,
-};
-
-DEFINE_STRUCT_CLK(dpll_per_x2_ck, dpll_per_x2_ck_parents, dpll_abe_x2_ck_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m2x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M2_DPLL_PER,
-                         OMAP4430_DPLL_CLKOUT_DIV_MASK);
-
-static const char *dpll_per_m3x2_ck_parents[] = {
-       "dpll_per_x2_ck",
-};
-
-static const struct clksel dpll_per_m3x2_div[] = {
-       { .parent = &dpll_per_x2_ck, .rates = div31_1to31_rates },
-       { .parent = NULL },
-};
-
-/* XXX Missing round_rate, set_rate in ops */
-DEFINE_CLK_OMAP_MUX_GATE(dpll_per_m3x2_ck, NULL, dpll_per_m3x2_div,
-                        OMAP4430_CM_DIV_M3_DPLL_PER,
-                        OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-                        OMAP4430_CM_DIV_M3_DPLL_PER,
-                        OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
-                        dpll_per_m3x2_ck_parents, dpll_hsd_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m4x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M4_DPLL_PER,
-                         OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m5x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M5_DPLL_PER,
-                         OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m6x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M6_DPLL_PER,
-                         OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m7x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
-                         0x0, OMAP4430_CM_DIV_M7_DPLL_PER,
-                         OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK);
-
-DEFINE_CLK_FIXED_FACTOR(usb_hs_clk_div_ck, "dpll_abe_m3x2_ck",
-                       &dpll_abe_m3x2_ck, 0x0, 1, 3);
-
-/* DPLL_USB */
-static struct dpll_data dpll_usb_dd = {
-       .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_USB,
-       .clk_bypass     = &usb_hs_clk_div_ck,
-       .flags          = DPLL_J_TYPE,
-       .clk_ref        = &sys_clkin_ck,
-       .control_reg    = OMAP4430_CM_CLKMODE_DPLL_USB,
-       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
-       .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_USB,
-       .idlest_reg     = OMAP4430_CM_IDLEST_DPLL_USB,
-       .mult_mask      = OMAP4430_DPLL_MULT_USB_MASK,
-       .div1_mask      = OMAP4430_DPLL_DIV_0_7_MASK,
-       .enable_mask    = OMAP4430_DPLL_EN_MASK,
-       .autoidle_mask  = OMAP4430_AUTO_DPLL_MODE_MASK,
-       .idlest_mask    = OMAP4430_ST_DPLL_CLK_MASK,
-       .sddiv_mask     = OMAP4430_DPLL_SD_DIV_MASK,
-       .max_multiplier = 4095,
-       .max_divider    = 256,
-       .min_divider    = 1,
-};
-
-static const char *dpll_usb_ck_parents[] = {
-       "sys_clkin_ck", "usb_hs_clk_div_ck"
-};
-
-static struct clk dpll_usb_ck;
-
-static const struct clk_ops dpll_usb_ck_ops = {
-       .enable         = &omap3_noncore_dpll_enable,
-       .disable        = &omap3_noncore_dpll_disable,
-       .recalc_rate    = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
-       .set_rate       = &omap3_noncore_dpll_set_rate,
-       .get_parent     = &omap2_init_dpll_parent,
-       .init           = &omap2_init_clk_clkdm,
-};
-
-static struct clk_hw_omap dpll_usb_ck_hw = {
-       .hw = {
-               .clk = &dpll_usb_ck,
-       },
-       .dpll_data      = &dpll_usb_dd,
-       .clkdm_name     = "l3_init_clkdm",
-       .ops            = &clkhwops_omap3_dpll,
-};
-
-DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_usb_ck_parents, dpll_usb_ck_ops);
-
-static const char *dpll_usb_clkdcoldo_ck_parents[] = {
-       "dpll_usb_ck",
-};
-
-static struct clk dpll_usb_clkdcoldo_ck;
-
-static const struct clk_ops dpll_usb_clkdcoldo_ck_ops = {
-};
-
-static struct clk_hw_omap dpll_usb_clkdcoldo_ck_hw = {
-       .hw = {
-               .clk = &dpll_usb_clkdcoldo_ck,
-       },
-       .clksel_reg     = OMAP4430_CM_CLKDCOLDO_DPLL_USB,
-       .ops            = &clkhwops_omap4_dpllmx,
-};
-
-DEFINE_STRUCT_CLK(dpll_usb_clkdcoldo_ck, dpll_usb_clkdcoldo_ck_parents,
-                 dpll_usb_clkdcoldo_ck_ops);
-
-DEFINE_CLK_OMAP_HSDIVIDER(dpll_usb_m2_ck, "dpll_usb_ck", &dpll_usb_ck, 0x0,
-                         OMAP4430_CM_DIV_M2_DPLL_USB,
-                         OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK);
-
-static const char *ducati_clk_mux_ck_parents[] = {
-       "div_core_ck", "dpll_per_m6x2_ck",
-};
-
-DEFINE_CLK_MUX(ducati_clk_mux_ck, ducati_clk_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM_CLKSEL_DUCATI_ISS_ROOT, OMAP4430_CLKSEL_0_0_SHIFT,
-              OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_FIXED_FACTOR(func_12m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
-                       0x0, 1, 16);
-
-DEFINE_CLK_FIXED_FACTOR(func_24m_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0,
-                       1, 4);
-
-DEFINE_CLK_FIXED_FACTOR(func_24mc_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
-                       0x0, 1, 8);
-
-static const struct clk_div_table func_48m_fclk_rates[] = {
-       { .div = 4, .val = 0 },
-       { .div = 8, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(func_48m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
-                        0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
-                        OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_48m_fclk_rates,
-                        NULL);
-
-DEFINE_CLK_FIXED_FACTOR(func_48mc_fclk,        "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
-                       0x0, 1, 4);
-
-static const struct clk_div_table func_64m_fclk_rates[] = {
-       { .div = 2, .val = 0 },
-       { .div = 4, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(func_64m_fclk, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck,
-                        0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
-                        OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_64m_fclk_rates,
-                        NULL);
-
-static const struct clk_div_table func_96m_fclk_rates[] = {
-       { .div = 2, .val = 0 },
-       { .div = 4, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(func_96m_fclk, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck,
-                        0x0, OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
-                        OMAP4430_SCALE_FCLK_WIDTH, 0x0, func_96m_fclk_rates,
-                        NULL);
-
-static const struct clk_div_table init_60m_fclk_rates[] = {
-       { .div = 1, .val = 0 },
-       { .div = 8, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(init_60m_fclk, "dpll_usb_m2_ck", &dpll_usb_m2_ck,
-                        0x0, OMAP4430_CM_CLKSEL_USB_60MHZ,
-                        OMAP4430_CLKSEL_0_0_SHIFT, OMAP4430_CLKSEL_0_0_WIDTH,
-                        0x0, init_60m_fclk_rates, NULL);
-
-DEFINE_CLK_DIVIDER(l3_div_ck, "div_core_ck", &div_core_ck, 0x0,
-                  OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L3_SHIFT,
-                  OMAP4430_CLKSEL_L3_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(l4_div_ck, "l3_div_ck", &l3_div_ck, 0x0,
-                  OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_L4_SHIFT,
-                  OMAP4430_CLKSEL_L4_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_FIXED_FACTOR(lp_clk_div_ck, "dpll_abe_m2x2_ck", &dpll_abe_m2x2_ck,
-                       0x0, 1, 16);
-
-static const char *l4_wkup_clk_mux_ck_parents[] = {
-       "sys_clkin_ck", "lp_clk_div_ck",
-};
-
-DEFINE_CLK_MUX(l4_wkup_clk_mux_ck, l4_wkup_clk_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM_L4_WKUP_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
-              OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
-
-static const struct clk_div_table ocp_abe_iclk_rates[] = {
-       { .div = 2, .val = 0 },
-       { .div = 1, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(ocp_abe_iclk, "aess_fclk", &aess_fclk, 0x0,
-                        OMAP4430_CM1_ABE_AESS_CLKCTRL,
-                        OMAP4430_CLKSEL_AESS_FCLK_SHIFT,
-                        OMAP4430_CLKSEL_AESS_FCLK_WIDTH,
-                        0x0, ocp_abe_iclk_rates, NULL);
-
-DEFINE_CLK_FIXED_FACTOR(per_abe_24m_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck,
-                       0x0, 1, 4);
-
-DEFINE_CLK_DIVIDER(per_abe_nc_fclk, "dpll_abe_m2_ck", &dpll_abe_m2_ck, 0x0,
-                  OMAP4430_CM_SCALE_FCLK, OMAP4430_SCALE_FCLK_SHIFT,
-                  OMAP4430_SCALE_FCLK_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
-                  OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
-                  OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);
-
-static const char *dbgclk_mux_ck_parents[] = {
-       "sys_clkin_ck"
-};
-
-static struct clk dbgclk_mux_ck;
-DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL);
-DEFINE_STRUCT_CLK(dbgclk_mux_ck, dbgclk_mux_ck_parents,
-                 dpll_usb_clkdcoldo_ck_ops);
-
-/* Leaf clocks controlled by modules */
-
-DEFINE_CLK_GATE(aes1_fck, "l3_div_ck", &l3_div_ck, 0x0,
-               OMAP4430_CM_L4SEC_AES1_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(aes2_fck, "l3_div_ck", &l3_div_ck, 0x0,
-               OMAP4430_CM_L4SEC_AES2_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(bandgap_fclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-               OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, 0x0, NULL);
-
-static const struct clk_div_table div_ts_ck_rates[] = {
-       { .div = 8, .val = 0 },
-       { .div = 16, .val = 1 },
-       { .div = 32, .val = 2 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(div_ts_ck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
-                        0x0, OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-                        OMAP4430_CLKSEL_24_25_SHIFT,
-                        OMAP4430_CLKSEL_24_25_WIDTH, 0x0, div_ts_ck_rates,
-                        NULL);
-
-DEFINE_CLK_GATE(bandgap_ts_fclk, "div_ts_ck", &div_ts_ck, 0x0,
-               OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
-               OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
-               0x0, NULL);
-
-static const char *dmic_sync_mux_ck_parents[] = {
-       "abe_24m_fclk", "syc_clk_div_ck", "func_24m_clk",
-};
-
-DEFINE_CLK_MUX(dmic_sync_mux_ck, dmic_sync_mux_ck_parents, NULL,
-              0x0, OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel func_dmic_abe_gfclk_sel[] = {
-       { .parent = &dmic_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = &slimbus_clk, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *func_dmic_abe_gfclk_parents[] = {
-       "dmic_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
-};
-
-DEFINE_CLK_OMAP_MUX(func_dmic_abe_gfclk, "abe_clkdm", func_dmic_abe_gfclk_sel,
-                   OMAP4430_CM1_ABE_DMIC_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK,
-                   func_dmic_abe_gfclk_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_GATE(dss_sys_clk, "syc_clk_div_ck", &syc_clk_div_ck, 0x0,
-               OMAP4430_CM_DSS_DSS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(dss_tv_clk, "extalt_clkin_ck", &extalt_clkin_ck, 0x0,
-               OMAP4430_CM_DSS_DSS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_TV_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(dss_dss_clk, "dpll_per_m5x2_ck", &dpll_per_m5x2_ck,
-               CLK_SET_RATE_PARENT,
-               OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(dss_48mhz_clk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
-               OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(dss_fck, "l3_div_ck", &l3_div_ck, 0x0,
-               OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_DIVIDER(fdif_fck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
-                  OMAP4430_CM_CAM_FDIF_CLKCTRL, OMAP4430_CLKSEL_FCLK_SHIFT,
-                  OMAP4430_CLKSEL_FCLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
-
-DEFINE_CLK_GATE(gpio1_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
-               OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpio2_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_L4PER_GPIO2_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(gpio3_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
-               OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpio4_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_L4PER_GPIO4_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(gpio5_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_L4PER_GPIO5_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_GATE(gpio6_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_L4PER_GPIO6_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
-               0x0, NULL);
-
-static const struct clksel sgx_clk_mux_sel[] = {
-       { .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
-       { .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static const char *sgx_clk_mux_parents[] = {
-       "dpll_core_m7x2_ck", "dpll_per_m7x2_ck",
-};
-
-DEFINE_CLK_OMAP_MUX(sgx_clk_mux, "l3_gfx_clkdm", sgx_clk_mux_sel,
-                   OMAP4430_CM_GFX_GFX_CLKCTRL, OMAP4430_CLKSEL_SGX_FCLK_MASK,
-                   sgx_clk_mux_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_DIVIDER(hsi_fck, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0,
-                  OMAP4430_CM_L3INIT_HSI_CLKCTRL, OMAP4430_CLKSEL_24_25_SHIFT,
-                  OMAP4430_CLKSEL_24_25_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
-                  NULL);
-
-DEFINE_CLK_GATE(iss_ctrlclk, "func_96m_fclk", &func_96m_fclk, 0x0,
-               OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
-               0x0, NULL);
-
-DEFINE_CLK_MUX(mcasp_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel func_mcasp_abe_gfclk_sel[] = {
-       { .parent = &mcasp_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = &slimbus_clk, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *func_mcasp_abe_gfclk_parents[] = {
-       "mcasp_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
-};
-
-DEFINE_CLK_OMAP_MUX(func_mcasp_abe_gfclk, "abe_clkdm", func_mcasp_abe_gfclk_sel,
-                   OMAP4430_CM1_ABE_MCASP_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK,
-                   func_mcasp_abe_gfclk_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_MUX(mcbsp1_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel func_mcbsp1_gfclk_sel[] = {
-       { .parent = &mcbsp1_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = &slimbus_clk, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *func_mcbsp1_gfclk_parents[] = {
-       "mcbsp1_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
-};
-
-DEFINE_CLK_OMAP_MUX(func_mcbsp1_gfclk, "abe_clkdm", func_mcbsp1_gfclk_sel,
-                   OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-                   OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp1_gfclk_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_MUX(mcbsp2_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel func_mcbsp2_gfclk_sel[] = {
-       { .parent = &mcbsp2_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = &slimbus_clk, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *func_mcbsp2_gfclk_parents[] = {
-       "mcbsp2_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
-};
-
-DEFINE_CLK_OMAP_MUX(func_mcbsp2_gfclk, "abe_clkdm", func_mcbsp2_gfclk_sel,
-                   OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-                   OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp2_gfclk_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_MUX(mcbsp3_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel func_mcbsp3_gfclk_sel[] = {
-       { .parent = &mcbsp3_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = &slimbus_clk, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *func_mcbsp3_gfclk_parents[] = {
-       "mcbsp3_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
-};
-
-DEFINE_CLK_OMAP_MUX(func_mcbsp3_gfclk, "abe_clkdm", func_mcbsp3_gfclk_sel,
-                   OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-                   OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp3_gfclk_parents,
-                   func_dmic_abe_gfclk_ops);
-
-static const char *mcbsp4_sync_mux_ck_parents[] = {
-       "func_96m_fclk", "per_abe_nc_fclk",
-};
-
-DEFINE_CLK_MUX(mcbsp4_sync_mux_ck, mcbsp4_sync_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
-              OMAP4430_CLKSEL_INTERNAL_SOURCE_WIDTH, 0x0, NULL);
-
-static const struct clksel per_mcbsp4_gfclk_sel[] = {
-       { .parent = &mcbsp4_sync_mux_ck, .rates = div_1_0_rates },
-       { .parent = &pad_clks_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static const char *per_mcbsp4_gfclk_parents[] = {
-       "mcbsp4_sync_mux_ck", "pad_clks_ck",
-};
-
-DEFINE_CLK_OMAP_MUX(per_mcbsp4_gfclk, "l4_per_clkdm", per_mcbsp4_gfclk_sel,
-                   OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-                   OMAP4430_CLKSEL_SOURCE_24_24_MASK, per_mcbsp4_gfclk_parents,
-                   func_dmic_abe_gfclk_ops);
-
-static const struct clksel hsmmc1_fclk_sel[] = {
-       { .parent = &func_64m_fclk, .rates = div_1_0_rates },
-       { .parent = &func_96m_fclk, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static const char *hsmmc1_fclk_parents[] = {
-       "func_64m_fclk", "func_96m_fclk",
-};
-
-DEFINE_CLK_OMAP_MUX(hsmmc1_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
-                   OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
-                   OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-               OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
-               OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus1_fclk_1, "func_24m_clk", &func_24m_clk, 0x0,
-               OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_FCLK1_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus1_fclk_0, "abe_24m_fclk", &abe_24m_fclk, 0x0,
-               OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_FCLK0_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus1_fclk_2, "pad_clks_ck", &pad_clks_ck, 0x0,
-               OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_FCLK2_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus1_slimbus_clk, "slimbus_clk", &slimbus_clk, 0x0,
-               OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-               OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus2_fclk_1, "per_abe_24m_fclk", &per_abe_24m_fclk, 0x0,
-               OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-               OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus2_fclk_0, "func_24mc_fclk", &func_24mc_fclk, 0x0,
-               OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-               OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(slimbus2_slimbus_clk, "pad_slimbus_core_clks_ck",
-               &pad_slimbus_core_clks_ck, 0x0,
-               OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-               OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(smartreflex_core_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
-               0x0, OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(smartreflex_iva_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
-               0x0, OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(smartreflex_mpu_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
-               0x0, OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-static const struct clksel dmt1_clk_mux_sel[] = {
-       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-DEFINE_CLK_OMAP_MUX(dmt1_clk_mux, "l4_wkup_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm10_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm11_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm2_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm3_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm4_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-static const struct clksel timer5_sync_mux_sel[] = {
-       { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-static const char *timer5_sync_mux_parents[] = {
-       "syc_clk_div_ck", "sys_32k_ck",
-};
-
-DEFINE_CLK_OMAP_MUX(timer5_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
-                   OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(timer6_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
-                   OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(timer7_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
-                   OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(timer8_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
-                   OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
-
-DEFINE_CLK_OMAP_MUX(cm2_dm9_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
-                   OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, OMAP4430_CLKSEL_MASK,
-                   abe_dpll_bypass_clk_mux_ck_parents,
-                   func_dmic_abe_gfclk_ops);
-
-static struct clk usb_host_fs_fck;
-
-static const char *usb_host_fs_fck_parent_names[] = {
-       "func_48mc_fclk",
-};
-
-static const struct clk_ops usb_host_fs_fck_ops = {
-       .enable         = &omap2_dflt_clk_enable,
-       .disable        = &omap2_dflt_clk_disable,
-       .is_enabled     = &omap2_dflt_clk_is_enabled,
-};
-
-static struct clk_hw_omap usb_host_fs_fck_hw = {
-       .hw = {
-               .clk = &usb_host_fs_fck,
-       },
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-       .clkdm_name     = "l3_init_clkdm",
-};
-
-DEFINE_STRUCT_CLK(usb_host_fs_fck, usb_host_fs_fck_parent_names,
-                 usb_host_fs_fck_ops);
-
-static const char *utmi_p1_gfclk_parents[] = {
-       "init_60m_fclk", "xclk60mhsp1_ck",
-};
-
-DEFINE_CLK_MUX(utmi_p1_gfclk, utmi_p1_gfclk_parents, NULL, 0x0,
-              OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-              OMAP4430_CLKSEL_UTMI_P1_SHIFT, OMAP4430_CLKSEL_UTMI_P1_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_utmi_p1_clk, "utmi_p1_gfclk", &utmi_p1_gfclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT, 0x0, NULL);
-
-static const char *utmi_p2_gfclk_parents[] = {
-       "init_60m_fclk", "xclk60mhsp2_ck",
-};
-
-DEFINE_CLK_MUX(utmi_p2_gfclk, utmi_p2_gfclk_parents, NULL, 0x0,
-              OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-              OMAP4430_CLKSEL_UTMI_P2_SHIFT, OMAP4430_CLKSEL_UTMI_P2_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_utmi_p2_clk, "utmi_p2_gfclk", &utmi_p2_gfclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_utmi_p3_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_hsic480m_p1_clk, "dpll_usb_m2_ck",
-               &dpll_usb_m2_ck, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_hsic60m_p1_clk, "init_60m_fclk",
-               &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_hsic60m_p2_clk, "init_60m_fclk",
-               &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_hsic480m_p2_clk, "dpll_usb_m2_ck",
-               &dpll_usb_m2_ck, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_func48mclk, "func_48mc_fclk", &func_48mc_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_host_hs_fck, "init_60m_fclk", &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-               OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-static const char *otg_60m_gfclk_parents[] = {
-       "utmi_phy_clkout_ck", "xclk60motg_ck",
-};
-
-DEFINE_CLK_MUX(otg_60m_gfclk, otg_60m_gfclk_parents, NULL, 0x0,
-              OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL, OMAP4430_CLKSEL_60M_SHIFT,
-              OMAP4430_CLKSEL_60M_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_otg_hs_xclk, "otg_60m_gfclk", &otg_60m_gfclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-               OMAP4430_OPTFCLKEN_XCLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_otg_hs_ick, "l3_div_ck", &l3_div_ck, 0x0,
-               OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-               OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_phy_cm_clk32k, "sys_32k_ck", &sys_32k_ck, 0x0,
-               OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
-               OMAP4430_OPTFCLKEN_CLK32K_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_tll_hs_usb_ch2_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-               OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_tll_hs_usb_ch0_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-               OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_tll_hs_usb_ch1_clk, "init_60m_fclk", &init_60m_fclk, 0x0,
-               OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-               OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(usb_tll_hs_ick, "l4_div_ck", &l4_div_ck, 0x0,
-               OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-               OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-static const struct clk_div_table usim_ck_rates[] = {
-       { .div = 14, .val = 0 },
-       { .div = 18, .val = 1 },
-       { .div = 0 },
-};
-DEFINE_CLK_DIVIDER_TABLE(usim_ck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
-                        OMAP4430_CM_WKUP_USIM_CLKCTRL,
-                        OMAP4430_CLKSEL_DIV_SHIFT, OMAP4430_CLKSEL_DIV_WIDTH,
-                        0x0, usim_ck_rates, NULL);
-
-DEFINE_CLK_GATE(usim_fclk, "usim_ck", &usim_ck, 0x0,
-               OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK_SHIFT,
-               0x0, NULL);
-
-/* Remaining optional clocks */
-static const char *pmd_stm_clock_mux_ck_parents[] = {
-       "sys_clkin_ck", "dpll_core_m6x2_ck", "tie_low_clock_ck",
-};
-
-DEFINE_CLK_MUX(pmd_stm_clock_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM_EMU_DEBUGSS_CLKCTRL, OMAP4430_PMD_STM_MUX_CTRL_SHIFT,
-              OMAP4430_PMD_STM_MUX_CTRL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_MUX(pmd_trace_clk_mux_ck, pmd_stm_clock_mux_ck_parents, NULL, 0x0,
-              OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-              OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT,
-              OMAP4430_PMD_TRACE_MUX_CTRL_WIDTH, 0x0, NULL);
-
-DEFINE_CLK_DIVIDER(stm_clk_div_ck, "pmd_stm_clock_mux_ck",
-                  &pmd_stm_clock_mux_ck, 0x0, OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-                  OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT,
-                  OMAP4430_CLKSEL_PMD_STM_CLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
-                  NULL);
-
-static const char *trace_clk_div_ck_parents[] = {
-       "pmd_trace_clk_mux_ck",
-};
-
-static const struct clksel trace_clk_div_div[] = {
-       { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
-};
-
-static struct clk trace_clk_div_ck;
-
-static const struct clk_ops trace_clk_div_ck_ops = {
-       .recalc_rate    = &omap2_clksel_recalc,
-       .set_rate       = &omap2_clksel_set_rate,
-       .round_rate     = &omap2_clksel_round_rate,
-       .init           = &omap2_init_clk_clkdm,
-       .enable         = &omap2_clkops_enable_clkdm,
-       .disable        = &omap2_clkops_disable_clkdm,
-};
-
-static struct clk_hw_omap trace_clk_div_ck_hw = {
-       .hw = {
-               .clk = &trace_clk_div_ck,
-       },
-       .clkdm_name     = "emu_sys_clkdm",
-       .clksel         = trace_clk_div_div,
-       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
-};
-
-DEFINE_STRUCT_CLK(trace_clk_div_ck, trace_clk_div_ck_parents,
-                 trace_clk_div_ck_ops);
-
-/* SCRM aux clk nodes */
-
-static const struct clksel auxclk_src_sel[] = {
-       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-       { .parent = &dpll_core_m3x2_ck, .rates = div_1_1_rates },
-       { .parent = &dpll_per_m3x2_ck, .rates = div_1_2_rates },
-       { .parent = NULL },
-};
-
-static const char *auxclk_src_ck_parents[] = {
-       "sys_clkin_ck", "dpll_core_m3x2_ck", "dpll_per_m3x2_ck",
-};
-
-static const struct clk_ops auxclk_src_ck_ops = {
-       .enable         = &omap2_dflt_clk_enable,
-       .disable        = &omap2_dflt_clk_disable,
-       .is_enabled     = &omap2_dflt_clk_is_enabled,
-       .recalc_rate    = &omap2_clksel_recalc,
-       .get_parent     = &omap2_clksel_find_parent_index,
-};
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk0_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK0, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK0, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk0_ck, "auxclk0_src_ck", &auxclk0_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK0, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk1_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK1, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK1, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk1_ck, "auxclk1_src_ck", &auxclk1_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK1, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk2_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK2, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK2, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk2_ck, "auxclk2_src_ck", &auxclk2_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK2, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk3_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK3, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK3, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk3_ck, "auxclk3_src_ck", &auxclk3_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK3, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk4_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK4, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK4, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk4_ck, "auxclk4_src_ck", &auxclk4_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK4, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-DEFINE_CLK_OMAP_MUX_GATE(auxclk5_src_ck, NULL, auxclk_src_sel,
-                        OMAP4_SCRM_AUXCLK5, OMAP4_SRCSELECT_MASK,
-                        OMAP4_SCRM_AUXCLK5, OMAP4_ENABLE_SHIFT, NULL,
-                        auxclk_src_ck_parents, auxclk_src_ck_ops);
-
-DEFINE_CLK_DIVIDER(auxclk5_ck, "auxclk5_src_ck", &auxclk5_src_ck, 0x0,
-                  OMAP4_SCRM_AUXCLK5, OMAP4_CLKDIV_SHIFT, OMAP4_CLKDIV_WIDTH,
-                  0x0, NULL);
-
-static const char *auxclkreq_ck_parents[] = {
-       "auxclk0_ck", "auxclk1_ck", "auxclk2_ck", "auxclk3_ck", "auxclk4_ck",
-       "auxclk5_ck",
-};
-
-DEFINE_CLK_MUX(auxclkreq0_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ0, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_MUX(auxclkreq1_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ1, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_MUX(auxclkreq2_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ2, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_MUX(auxclkreq3_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ3, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_MUX(auxclkreq4_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ4, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-DEFINE_CLK_MUX(auxclkreq5_ck, auxclkreq_ck_parents, NULL, 0x0,
-              OMAP4_SCRM_AUXCLKREQ5, OMAP4_MAPPING_SHIFT, OMAP4_MAPPING_WIDTH,
-              0x0, NULL);
-
-/*
- * clocks specific to omap4460
- */
-static struct omap_clk omap446x_clks[] = {
-       CLK(NULL,       "div_ts_ck",                    &div_ts_ck),
-       CLK(NULL,       "bandgap_ts_fclk",              &bandgap_ts_fclk),
-};
-
-/*
- * clocks specific to omap4430
- */
-static struct omap_clk omap443x_clks[] = {
-       CLK(NULL,       "bandgap_fclk",                 &bandgap_fclk),
-};
-
-/*
- * clocks common to omap44xx
- */
-static struct omap_clk omap44xx_clks[] = {
-       CLK(NULL,       "extalt_clkin_ck",              &extalt_clkin_ck),
-       CLK(NULL,       "pad_clks_src_ck",              &pad_clks_src_ck),
-       CLK(NULL,       "pad_clks_ck",                  &pad_clks_ck),
-       CLK(NULL,       "pad_slimbus_core_clks_ck",     &pad_slimbus_core_clks_ck),
-       CLK(NULL,       "secure_32k_clk_src_ck",        &secure_32k_clk_src_ck),
-       CLK(NULL,       "slimbus_src_clk",              &slimbus_src_clk),
-       CLK(NULL,       "slimbus_clk",                  &slimbus_clk),
-       CLK(NULL,       "sys_32k_ck",                   &sys_32k_ck),
-       CLK(NULL,       "virt_12000000_ck",             &virt_12000000_ck),
-       CLK(NULL,       "virt_13000000_ck",             &virt_13000000_ck),
-       CLK(NULL,       "virt_16800000_ck",             &virt_16800000_ck),
-       CLK(NULL,       "virt_19200000_ck",             &virt_19200000_ck),
-       CLK(NULL,       "virt_26000000_ck",             &virt_26000000_ck),
-       CLK(NULL,       "virt_27000000_ck",             &virt_27000000_ck),
-       CLK(NULL,       "virt_38400000_ck",             &virt_38400000_ck),
-       CLK(NULL,       "sys_clkin_ck",                 &sys_clkin_ck),
-       CLK(NULL,       "tie_low_clock_ck",             &tie_low_clock_ck),
-       CLK(NULL,       "utmi_phy_clkout_ck",           &utmi_phy_clkout_ck),
-       CLK(NULL,       "xclk60mhsp1_ck",               &xclk60mhsp1_ck),
-       CLK(NULL,       "xclk60mhsp2_ck",               &xclk60mhsp2_ck),
-       CLK(NULL,       "xclk60motg_ck",                &xclk60motg_ck),
-       CLK(NULL,       "abe_dpll_bypass_clk_mux_ck",   &abe_dpll_bypass_clk_mux_ck),
-       CLK(NULL,       "abe_dpll_refclk_mux_ck",       &abe_dpll_refclk_mux_ck),
-       CLK(NULL,       "dpll_abe_ck",                  &dpll_abe_ck),
-       CLK(NULL,       "dpll_abe_x2_ck",               &dpll_abe_x2_ck),
-       CLK(NULL,       "dpll_abe_m2x2_ck",             &dpll_abe_m2x2_ck),
-       CLK(NULL,       "abe_24m_fclk",                 &abe_24m_fclk),
-       CLK(NULL,       "abe_clk",                      &abe_clk),
-       CLK(NULL,       "aess_fclk",                    &aess_fclk),
-       CLK(NULL,       "dpll_abe_m3x2_ck",             &dpll_abe_m3x2_ck),
-       CLK(NULL,       "core_hsd_byp_clk_mux_ck",      &core_hsd_byp_clk_mux_ck),
-       CLK(NULL,       "dpll_core_ck",                 &dpll_core_ck),
-       CLK(NULL,       "dpll_core_x2_ck",              &dpll_core_x2_ck),
-       CLK(NULL,       "dpll_core_m6x2_ck",            &dpll_core_m6x2_ck),
-       CLK(NULL,       "dbgclk_mux_ck",                &dbgclk_mux_ck),
-       CLK(NULL,       "dpll_core_m2_ck",              &dpll_core_m2_ck),
-       CLK(NULL,       "ddrphy_ck",                    &ddrphy_ck),
-       CLK(NULL,       "dpll_core_m5x2_ck",            &dpll_core_m5x2_ck),
-       CLK(NULL,       "div_core_ck",                  &div_core_ck),
-       CLK(NULL,       "div_iva_hs_clk",               &div_iva_hs_clk),
-       CLK(NULL,       "div_mpu_hs_clk",               &div_mpu_hs_clk),
-       CLK(NULL,       "dpll_core_m4x2_ck",            &dpll_core_m4x2_ck),
-       CLK(NULL,       "dll_clk_div_ck",               &dll_clk_div_ck),
-       CLK(NULL,       "dpll_abe_m2_ck",               &dpll_abe_m2_ck),
-       CLK(NULL,       "dpll_core_m3x2_ck",            &dpll_core_m3x2_ck),
-       CLK(NULL,       "dpll_core_m7x2_ck",            &dpll_core_m7x2_ck),
-       CLK(NULL,       "iva_hsd_byp_clk_mux_ck",       &iva_hsd_byp_clk_mux_ck),
-       CLK(NULL,       "dpll_iva_ck",                  &dpll_iva_ck),
-       CLK(NULL,       "dpll_iva_x2_ck",               &dpll_iva_x2_ck),
-       CLK(NULL,       "dpll_iva_m4x2_ck",             &dpll_iva_m4x2_ck),
-       CLK(NULL,       "dpll_iva_m5x2_ck",             &dpll_iva_m5x2_ck),
-       CLK(NULL,       "dpll_mpu_ck",                  &dpll_mpu_ck),
-       CLK(NULL,       "dpll_mpu_m2_ck",               &dpll_mpu_m2_ck),
-       CLK(NULL,       "per_hs_clk_div_ck",            &per_hs_clk_div_ck),
-       CLK(NULL,       "per_hsd_byp_clk_mux_ck",       &per_hsd_byp_clk_mux_ck),
-       CLK(NULL,       "dpll_per_ck",                  &dpll_per_ck),
-       CLK(NULL,       "dpll_per_m2_ck",               &dpll_per_m2_ck),
-       CLK(NULL,       "dpll_per_x2_ck",               &dpll_per_x2_ck),
-       CLK(NULL,       "dpll_per_m2x2_ck",             &dpll_per_m2x2_ck),
-       CLK(NULL,       "dpll_per_m3x2_ck",             &dpll_per_m3x2_ck),
-       CLK(NULL,       "dpll_per_m4x2_ck",             &dpll_per_m4x2_ck),
-       CLK(NULL,       "dpll_per_m5x2_ck",             &dpll_per_m5x2_ck),
-       CLK(NULL,       "dpll_per_m6x2_ck",             &dpll_per_m6x2_ck),
-       CLK(NULL,       "dpll_per_m7x2_ck",             &dpll_per_m7x2_ck),
-       CLK(NULL,       "usb_hs_clk_div_ck",            &usb_hs_clk_div_ck),
-       CLK(NULL,       "dpll_usb_ck",                  &dpll_usb_ck),
-       CLK(NULL,       "dpll_usb_clkdcoldo_ck",        &dpll_usb_clkdcoldo_ck),
-       CLK(NULL,       "dpll_usb_m2_ck",               &dpll_usb_m2_ck),
-       CLK(NULL,       "ducati_clk_mux_ck",            &ducati_clk_mux_ck),
-       CLK(NULL,       "func_12m_fclk",                &func_12m_fclk),
-       CLK(NULL,       "func_24m_clk",                 &func_24m_clk),
-       CLK(NULL,       "func_24mc_fclk",               &func_24mc_fclk),
-       CLK(NULL,       "func_48m_fclk",                &func_48m_fclk),
-       CLK(NULL,       "func_48mc_fclk",               &func_48mc_fclk),
-       CLK(NULL,       "func_64m_fclk",                &func_64m_fclk),
-       CLK(NULL,       "func_96m_fclk",                &func_96m_fclk),
-       CLK(NULL,       "init_60m_fclk",                &init_60m_fclk),
-       CLK(NULL,       "l3_div_ck",                    &l3_div_ck),
-       CLK(NULL,       "l4_div_ck",                    &l4_div_ck),
-       CLK(NULL,       "lp_clk_div_ck",                &lp_clk_div_ck),
-       CLK(NULL,       "l4_wkup_clk_mux_ck",           &l4_wkup_clk_mux_ck),
-       CLK("smp_twd",  NULL,                           &mpu_periphclk),
-       CLK(NULL,       "ocp_abe_iclk",                 &ocp_abe_iclk),
-       CLK(NULL,       "per_abe_24m_fclk",             &per_abe_24m_fclk),
-       CLK(NULL,       "per_abe_nc_fclk",              &per_abe_nc_fclk),
-       CLK(NULL,       "syc_clk_div_ck",               &syc_clk_div_ck),
-       CLK(NULL,       "aes1_fck",                     &aes1_fck),
-       CLK(NULL,       "aes2_fck",                     &aes2_fck),
-       CLK(NULL,       "dmic_sync_mux_ck",             &dmic_sync_mux_ck),
-       CLK(NULL,       "func_dmic_abe_gfclk",          &func_dmic_abe_gfclk),
-       CLK(NULL,       "dss_sys_clk",                  &dss_sys_clk),
-       CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk),
-       CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk),
-       CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk),
-       CLK(NULL,       "dss_fck",                      &dss_fck),
-       CLK("omapdss_dss",      "ick",                  &dss_fck),
-       CLK(NULL,       "fdif_fck",                     &fdif_fck),
-       CLK(NULL,       "gpio1_dbclk",                  &gpio1_dbclk),
-       CLK(NULL,       "gpio2_dbclk",                  &gpio2_dbclk),
-       CLK(NULL,       "gpio3_dbclk",                  &gpio3_dbclk),
-       CLK(NULL,       "gpio4_dbclk",                  &gpio4_dbclk),
-       CLK(NULL,       "gpio5_dbclk",                  &gpio5_dbclk),
-       CLK(NULL,       "gpio6_dbclk",                  &gpio6_dbclk),
-       CLK(NULL,       "sgx_clk_mux",                  &sgx_clk_mux),
-       CLK(NULL,       "hsi_fck",                      &hsi_fck),
-       CLK(NULL,       "iss_ctrlclk",                  &iss_ctrlclk),
-       CLK(NULL,       "mcasp_sync_mux_ck",            &mcasp_sync_mux_ck),
-       CLK(NULL,       "func_mcasp_abe_gfclk",         &func_mcasp_abe_gfclk),
-       CLK(NULL,       "mcbsp1_sync_mux_ck",           &mcbsp1_sync_mux_ck),
-       CLK(NULL,       "func_mcbsp1_gfclk",            &func_mcbsp1_gfclk),
-       CLK(NULL,       "mcbsp2_sync_mux_ck",           &mcbsp2_sync_mux_ck),
-       CLK(NULL,       "func_mcbsp2_gfclk",            &func_mcbsp2_gfclk),
-       CLK(NULL,       "mcbsp3_sync_mux_ck",           &mcbsp3_sync_mux_ck),
-       CLK(NULL,       "func_mcbsp3_gfclk",            &func_mcbsp3_gfclk),
-       CLK(NULL,       "mcbsp4_sync_mux_ck",           &mcbsp4_sync_mux_ck),
-       CLK(NULL,       "per_mcbsp4_gfclk",             &per_mcbsp4_gfclk),
-       CLK(NULL,       "hsmmc1_fclk",                  &hsmmc1_fclk),
-       CLK(NULL,       "hsmmc2_fclk",                  &hsmmc2_fclk),
-       CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m),
-       CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck),
-       CLK(NULL,       "slimbus1_fclk_1",              &slimbus1_fclk_1),
-       CLK(NULL,       "slimbus1_fclk_0",              &slimbus1_fclk_0),
-       CLK(NULL,       "slimbus1_fclk_2",              &slimbus1_fclk_2),
-       CLK(NULL,       "slimbus1_slimbus_clk",         &slimbus1_slimbus_clk),
-       CLK(NULL,       "slimbus2_fclk_1",              &slimbus2_fclk_1),
-       CLK(NULL,       "slimbus2_fclk_0",              &slimbus2_fclk_0),
-       CLK(NULL,       "slimbus2_slimbus_clk",         &slimbus2_slimbus_clk),
-       CLK(NULL,       "smartreflex_core_fck",         &smartreflex_core_fck),
-       CLK(NULL,       "smartreflex_iva_fck",          &smartreflex_iva_fck),
-       CLK(NULL,       "smartreflex_mpu_fck",          &smartreflex_mpu_fck),
-       CLK(NULL,       "dmt1_clk_mux",                 &dmt1_clk_mux),
-       CLK(NULL,       "cm2_dm10_mux",                 &cm2_dm10_mux),
-       CLK(NULL,       "cm2_dm11_mux",                 &cm2_dm11_mux),
-       CLK(NULL,       "cm2_dm2_mux",                  &cm2_dm2_mux),
-       CLK(NULL,       "cm2_dm3_mux",                  &cm2_dm3_mux),
-       CLK(NULL,       "cm2_dm4_mux",                  &cm2_dm4_mux),
-       CLK(NULL,       "timer5_sync_mux",              &timer5_sync_mux),
-       CLK(NULL,       "timer6_sync_mux",              &timer6_sync_mux),
-       CLK(NULL,       "timer7_sync_mux",              &timer7_sync_mux),
-       CLK(NULL,       "timer8_sync_mux",              &timer8_sync_mux),
-       CLK(NULL,       "cm2_dm9_mux",                  &cm2_dm9_mux),
-       CLK(NULL,       "usb_host_fs_fck",              &usb_host_fs_fck),
-       CLK("usbhs_omap",       "fs_fck",               &usb_host_fs_fck),
-       CLK(NULL,       "utmi_p1_gfclk",                &utmi_p1_gfclk),
-       CLK(NULL,       "usb_host_hs_utmi_p1_clk",      &usb_host_hs_utmi_p1_clk),
-       CLK(NULL,       "utmi_p2_gfclk",                &utmi_p2_gfclk),
-       CLK(NULL,       "usb_host_hs_utmi_p2_clk",      &usb_host_hs_utmi_p2_clk),
-       CLK(NULL,       "usb_host_hs_utmi_p3_clk",      &usb_host_hs_utmi_p3_clk),
-       CLK(NULL,       "usb_host_hs_hsic480m_p1_clk",  &usb_host_hs_hsic480m_p1_clk),
-       CLK(NULL,       "usb_host_hs_hsic60m_p1_clk",   &usb_host_hs_hsic60m_p1_clk),
-       CLK(NULL,       "usb_host_hs_hsic60m_p2_clk",   &usb_host_hs_hsic60m_p2_clk),
-       CLK(NULL,       "usb_host_hs_hsic480m_p2_clk",  &usb_host_hs_hsic480m_p2_clk),
-       CLK(NULL,       "usb_host_hs_func48mclk",       &usb_host_hs_func48mclk),
-       CLK(NULL,       "usb_host_hs_fck",              &usb_host_hs_fck),
-       CLK("usbhs_omap",       "hs_fck",               &usb_host_hs_fck),
-       CLK(NULL,       "otg_60m_gfclk",                &otg_60m_gfclk),
-       CLK(NULL,       "usb_otg_hs_xclk",              &usb_otg_hs_xclk),
-       CLK(NULL,       "usb_otg_hs_ick",               &usb_otg_hs_ick),
-       CLK("musb-omap2430",    "ick",                  &usb_otg_hs_ick),
-       CLK(NULL,       "usb_phy_cm_clk32k",            &usb_phy_cm_clk32k),
-       CLK(NULL,       "usb_tll_hs_usb_ch2_clk",       &usb_tll_hs_usb_ch2_clk),
-       CLK(NULL,       "usb_tll_hs_usb_ch0_clk",       &usb_tll_hs_usb_ch0_clk),
-       CLK(NULL,       "usb_tll_hs_usb_ch1_clk",       &usb_tll_hs_usb_ch1_clk),
-       CLK(NULL,       "usb_tll_hs_ick",               &usb_tll_hs_ick),
-       CLK("usbhs_omap",       "usbtll_ick",           &usb_tll_hs_ick),
-       CLK("usbhs_tll",        "usbtll_ick",           &usb_tll_hs_ick),
-       CLK(NULL,       "usim_ck",                      &usim_ck),
-       CLK(NULL,       "usim_fclk",                    &usim_fclk),
-       CLK(NULL,       "pmd_stm_clock_mux_ck",         &pmd_stm_clock_mux_ck),
-       CLK(NULL,       "pmd_trace_clk_mux_ck",         &pmd_trace_clk_mux_ck),
-       CLK(NULL,       "stm_clk_div_ck",               &stm_clk_div_ck),
-       CLK(NULL,       "trace_clk_div_ck",             &trace_clk_div_ck),
-       CLK(NULL,       "auxclk0_src_ck",               &auxclk0_src_ck),
-       CLK(NULL,       "auxclk0_ck",                   &auxclk0_ck),
-       CLK(NULL,       "auxclkreq0_ck",                &auxclkreq0_ck),
-       CLK(NULL,       "auxclk1_src_ck",               &auxclk1_src_ck),
-       CLK(NULL,       "auxclk1_ck",                   &auxclk1_ck),
-       CLK(NULL,       "auxclkreq1_ck",                &auxclkreq1_ck),
-       CLK(NULL,       "auxclk2_src_ck",               &auxclk2_src_ck),
-       CLK(NULL,       "auxclk2_ck",                   &auxclk2_ck),
-       CLK(NULL,       "auxclkreq2_ck",                &auxclkreq2_ck),
-       CLK(NULL,       "auxclk3_src_ck",               &auxclk3_src_ck),
-       CLK(NULL,       "auxclk3_ck",                   &auxclk3_ck),
-       CLK(NULL,       "auxclkreq3_ck",                &auxclkreq3_ck),
-       CLK(NULL,       "auxclk4_src_ck",               &auxclk4_src_ck),
-       CLK(NULL,       "auxclk4_ck",                   &auxclk4_ck),
-       CLK(NULL,       "auxclkreq4_ck",                &auxclkreq4_ck),
-       CLK(NULL,       "auxclk5_src_ck",               &auxclk5_src_ck),
-       CLK(NULL,       "auxclk5_ck",                   &auxclk5_ck),
-       CLK(NULL,       "auxclkreq5_ck",                &auxclkreq5_ck),
-       CLK("50000000.gpmc",    "fck",                  &dummy_ck),
-       CLK("omap_i2c.1",       "ick",                  &dummy_ck),
-       CLK("omap_i2c.2",       "ick",                  &dummy_ck),
-       CLK("omap_i2c.3",       "ick",                  &dummy_ck),
-       CLK("omap_i2c.4",       "ick",                  &dummy_ck),
-       CLK(NULL,       "mailboxes_ick",                &dummy_ck),
-       CLK("omap_hsmmc.0",     "ick",                  &dummy_ck),
-       CLK("omap_hsmmc.1",     "ick",                  &dummy_ck),
-       CLK("omap_hsmmc.2",     "ick",                  &dummy_ck),
-       CLK("omap_hsmmc.3",     "ick",                  &dummy_ck),
-       CLK("omap_hsmmc.4",     "ick",                  &dummy_ck),
-       CLK("omap-mcbsp.1",     "ick",                  &dummy_ck),
-       CLK("omap-mcbsp.2",     "ick",                  &dummy_ck),
-       CLK("omap-mcbsp.3",     "ick",                  &dummy_ck),
-       CLK("omap-mcbsp.4",     "ick",                  &dummy_ck),
-       CLK("omap2_mcspi.1",    "ick",                  &dummy_ck),
-       CLK("omap2_mcspi.2",    "ick",                  &dummy_ck),
-       CLK("omap2_mcspi.3",    "ick",                  &dummy_ck),
-       CLK("omap2_mcspi.4",    "ick",                  &dummy_ck),
-       CLK(NULL,       "uart1_ick",                    &dummy_ck),
-       CLK(NULL,       "uart2_ick",                    &dummy_ck),
-       CLK(NULL,       "uart3_ick",                    &dummy_ck),
-       CLK(NULL,       "uart4_ick",                    &dummy_ck),
-       CLK("usbhs_omap",       "usbhost_ick",          &dummy_ck),
-       CLK("usbhs_omap",       "usbtll_fck",           &dummy_ck),
-       CLK("usbhs_tll",        "usbtll_fck",           &dummy_ck),
-       CLK("omap_wdt", "ick",                          &dummy_ck),
-       CLK(NULL,       "timer_32k_ck", &sys_32k_ck),
-       /* TODO: Remove "omap_timer.X" aliases once DT migration is complete */
-       CLK("omap_timer.1",     "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.2",     "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.3",     "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.4",     "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.9",     "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.10",    "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.11",    "timer_sys_ck", &sys_clkin_ck),
-       CLK("omap_timer.5",     "timer_sys_ck", &syc_clk_div_ck),
-       CLK("omap_timer.6",     "timer_sys_ck", &syc_clk_div_ck),
-       CLK("omap_timer.7",     "timer_sys_ck", &syc_clk_div_ck),
-       CLK("omap_timer.8",     "timer_sys_ck", &syc_clk_div_ck),
-       CLK("4a318000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("48032000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("48034000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("48036000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("4803e000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("48086000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("48088000.timer",   "timer_sys_ck", &sys_clkin_ck),
-       CLK("40138000.timer",   "timer_sys_ck", &syc_clk_div_ck),
-       CLK("4013a000.timer",   "timer_sys_ck", &syc_clk_div_ck),
-       CLK("4013c000.timer",   "timer_sys_ck", &syc_clk_div_ck),
-       CLK("4013e000.timer",   "timer_sys_ck", &syc_clk_div_ck),
-       CLK(NULL,       "cpufreq_ck",   &dpll_mpu_ck),
-};
-
-int __init omap4xxx_clk_init(void)
-{
-       int rc;
-
-       if (cpu_is_omap443x()) {
-               cpu_mask = RATE_IN_4430;
-               omap_clocks_register(omap443x_clks, ARRAY_SIZE(omap443x_clks));
-       } else if (cpu_is_omap446x() || cpu_is_omap447x()) {
-               cpu_mask = RATE_IN_4460 | RATE_IN_4430;
-               omap_clocks_register(omap446x_clks, ARRAY_SIZE(omap446x_clks));
-               if (cpu_is_omap447x())
-                       pr_warn("WARNING: OMAP4470 clock data incomplete!\n");
-       } else {
-               return 0;
-       }
-
-       omap_clocks_register(omap44xx_clks, ARRAY_SIZE(omap44xx_clks));
-
-       omap2_clk_disable_autoidle_all();
-
-       /*
-        * A set rate of ABE DPLL inturn triggers a set rate of USB DPLL
-        * when its in bypass. So always lock USB before ABE DPLL.
-        */
-       /*
-        * Lock USB DPLL on OMAP4 devices so that the L3INIT power
-        * domain can transition to retention state when not in use.
-        */
-       rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ);
-       if (rc)
-               pr_err("%s: failed to configure USB DPLL!\n", __func__);
-
-       /*
-        * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
-        * state when turning the ABE clock domain. Workaround this by
-        * locking the ABE DPLL on boot.
-        * Lock the ABE DPLL in any case to avoid issues with audio.
-        */
-       rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
-       if (!rc)
-               rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
-       if (rc)
-               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-
-       return 0;
-}
index 0ec9f6fdf0463bb6ff435f250c748db075c62ca4..7ee26108ac0d36b76b156b93b619b2cbee0b89d7 100644 (file)
@@ -97,12 +97,12 @@ static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
 {
        u32 v;
 
-       v = __raw_readl(clk->clksel_reg);
+       v = omap2_clk_readl(clk, clk->clksel_reg);
        v &= ~clk->clksel_mask;
        v |= field_val << __ffs(clk->clksel_mask);
-       __raw_writel(v, clk->clksel_reg);
+       omap2_clk_writel(v, clk, clk->clksel_reg);
 
-       v = __raw_readl(clk->clksel_reg); /* OCP barrier */
+       v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
 }
 
 /**
@@ -204,7 +204,7 @@ static u32 _read_divisor(struct clk_hw_omap *clk)
        if (!clk->clksel || !clk->clksel_mask)
                return 0;
 
-       v = __raw_readl(clk->clksel_reg);
+       v = omap2_clk_readl(clk, clk->clksel_reg);
        v &= clk->clksel_mask;
        v >>= __ffs(clk->clksel_mask);
 
@@ -320,7 +320,7 @@ u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
        WARN((!clk->clksel || !clk->clksel_mask),
             "clock: %s: attempt to call on a non-clksel clock", clk_name);
 
-       r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
+       r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
        r >>= __ffs(clk->clksel_mask);
 
        for (clks = clk->clksel; clks->parent && !found; clks++) {
index 924c230f89484473f057246fb7f3a8b53a28c2bd..47f9562ca7aa0f3007cfac811ffceb90b7cce80e 100644 (file)
@@ -196,7 +196,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
        if (!dd)
                return -EINVAL;
 
-       v = __raw_readl(dd->control_reg);
+       v = omap2_clk_readl(clk, dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
@@ -243,7 +243,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
                return 0;
 
        /* Return bypass rate if DPLL is bypassed */
-       v = __raw_readl(dd->control_reg);
+       v = omap2_clk_readl(clk, dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
@@ -262,7 +262,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
                        return __clk_get_rate(dd->clk_bypass);
        }
 
-       v = __raw_readl(dd->mult_div1_reg);
+       v = omap2_clk_readl(clk, dd->mult_div1_reg);
        dpll_mult = v & dd->mult_mask;
        dpll_mult >>= __ffs(dd->mult_mask);
        dpll_div = v & dd->div1_mask;
index f10eb03ce3e27493ee1d52b18444ff52d4cf1507..333f0a66617165fa23448e19cd6b59c8856c78d3 100644 (file)
 /* XXX */
 void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
 {
-       u32 v, r;
+       u32 v;
+       void __iomem *r;
 
-       r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
 
-       v = __raw_readl((__force void __iomem *)r);
+       v = omap2_clk_readl(clk, r);
        v |= (1 << clk->enable_bit);
-       __raw_writel(v, (__force void __iomem *)r);
+       omap2_clk_writel(v, clk, r);
 }
 
 /* XXX */
 void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
 {
-       u32 v, r;
+       u32 v;
+       void __iomem *r;
 
-       r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+       r = (__force void __iomem *)
+               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
 
-       v = __raw_readl((__force void __iomem *)r);
+       v = omap2_clk_readl(clk, r);
        v &= ~(1 << clk->enable_bit);
-       __raw_writel(v, (__force void __iomem *)r);
+       omap2_clk_writel(v, clk, r);
 }
 
 /* Public data */
index c7c5d31e90829141373662f32ffb39ce6c32637a..591581a665321c09fafbe78fd9c5bdbcae53c5a4 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/clk-private.h>
 #include <asm/cpu.h>
 
-
 #include <trace/events/power.h>
 
 #include "soc.h"
@@ -56,6 +55,31 @@ u16 cpu_mask;
 static bool clkdm_control = true;
 
 static LIST_HEAD(clk_hw_omap_clocks);
+void __iomem *clk_memmaps[CLK_MAX_MEMMAPS];
+
+void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
+{
+       if (clk->flags & MEMMAP_ADDRESSING) {
+               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+               writel_relaxed(val, clk_memmaps[r->index] + r->offset);
+       } else {
+               writel_relaxed(val, reg);
+       }
+}
+
+u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
+{
+       u32 val;
+
+       if (clk->flags & MEMMAP_ADDRESSING) {
+               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+               val = readl_relaxed(clk_memmaps[r->index] + r->offset);
+       } else {
+               val = readl_relaxed(reg);
+       }
+
+       return val;
+}
 
 /*
  * Used for clocks that have the same value as the parent clock,
@@ -87,6 +111,7 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
 
 /**
  * _wait_idlest_generic - wait for a module to leave the idle state
+ * @clk: module clock to wait for (needed for register offsets)
  * @reg: virtual address of module IDLEST register
  * @mask: value to mask against to determine if the module is active
  * @idlest: idle state indicator (0 or 1) for the clock
@@ -98,14 +123,14 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
  * elapsed.  XXX Deprecated - should be moved into drivers for the
  * individual IP block that the IDLEST register exists in.
  */
-static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
-                               const char *name)
+static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
+                               u32 mask, u8 idlest, const char *name)
 {
        int i = 0, ena = 0;
 
        ena = (idlest) ? 0 : mask;
 
-       omap_test_timeout(((__raw_readl(reg) & mask) == ena),
+       omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
                          MAX_MODULE_ENABLE_WAIT, i);
 
        if (i < MAX_MODULE_ENABLE_WAIT)
@@ -138,7 +163,7 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
        /* Not all modules have multiple clocks that their IDLEST depends on */
        if (clk->ops->find_companion) {
                clk->ops->find_companion(clk, &companion_reg, &other_bit);
-               if (!(__raw_readl(companion_reg) & (1 << other_bit)))
+               if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
                        return;
        }
 
@@ -146,8 +171,8 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
        r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
        if (r) {
                /* IDLEST register not in the CM module */
-               _wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
-                                    __clk_get_name(clk->hw.clk));
+               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
+                                    idlest_val, __clk_get_name(clk->hw.clk));
        } else {
                cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
        };
@@ -309,13 +334,13 @@ int omap2_dflt_clk_enable(struct clk_hw *hw)
        }
 
        /* FIXME should not have INVERT_ENABLE bit here */
-       v = __raw_readl(clk->enable_reg);
+       v = omap2_clk_readl(clk, clk->enable_reg);
        if (clk->flags & INVERT_ENABLE)
                v &= ~(1 << clk->enable_bit);
        else
                v |= (1 << clk->enable_bit);
-       __raw_writel(v, clk->enable_reg);
-       v = __raw_readl(clk->enable_reg); /* OCP barrier */
+       omap2_clk_writel(v, clk, clk->enable_reg);
+       v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
 
        if (clk->ops && clk->ops->find_idlest)
                _omap2_module_wait_ready(clk);
@@ -353,12 +378,12 @@ void omap2_dflt_clk_disable(struct clk_hw *hw)
                return;
        }
 
-       v = __raw_readl(clk->enable_reg);
+       v = omap2_clk_readl(clk, clk->enable_reg);
        if (clk->flags & INVERT_ENABLE)
                v |= (1 << clk->enable_bit);
        else
                v &= ~(1 << clk->enable_bit);
-       __raw_writel(v, clk->enable_reg);
+       omap2_clk_writel(v, clk, clk->enable_reg);
        /* No OCP barrier needed here since it is a disable operation */
 
        if (clkdm_control && clk->clkdm)
@@ -454,7 +479,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        u32 v;
 
-       v = __raw_readl(clk->enable_reg);
+       v = omap2_clk_readl(clk, clk->enable_reg);
 
        if (clk->flags & INVERT_ENABLE)
                v ^= BIT(clk->enable_bit);
@@ -520,6 +545,9 @@ int omap2_clk_enable_autoidle_all(void)
        list_for_each_entry(c, &clk_hw_omap_clocks, node)
                if (c->ops && c->ops->allow_idle)
                        c->ops->allow_idle(c);
+
+       of_ti_clk_allow_autoidle_all();
+
        return 0;
 }
 
@@ -539,6 +567,9 @@ int omap2_clk_disable_autoidle_all(void)
        list_for_each_entry(c, &clk_hw_omap_clocks, node)
                if (c->ops && c->ops->deny_idle)
                        c->ops->deny_idle(c);
+
+       of_ti_clk_deny_autoidle_all();
+
        return 0;
 }
 
index 82916cc82c920d6fb7d08dcec444dded07ede0bb..bda767a9dea862d7223d86d1a59c0b1505e091f9 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
 
 struct omap_clk {
        u16                             cpu;
@@ -37,7 +38,6 @@ struct omap_clk {
        }
 
 struct clockdomain;
-#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
 #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)     \
        static struct clk _name = {                             \
@@ -178,141 +178,6 @@ struct clksel {
        const struct clksel_rate *rates;
 };
 
-/**
- * struct dpll_data - DPLL registers and integration data
- * @mult_div1_reg: register containing the DPLL M and N bitfields
- * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
- * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
- * @clk_bypass: struct clk pointer to the clock's bypass clock input
- * @clk_ref: struct clk pointer to the clock's reference clock input
- * @control_reg: register containing the DPLL mode bitfield
- * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
- * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
- * @last_rounded_m4xen: cache of the last M4X result of
- *                     omap4_dpll_regm4xen_round_rate()
- * @last_rounded_lpmode: cache of the last lpmode result of
- *                      omap4_dpll_lpmode_recalc()
- * @max_multiplier: maximum valid non-bypass multiplier value (actual)
- * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
- * @min_divider: minimum valid non-bypass divider value (actual)
- * @max_divider: maximum valid non-bypass divider value (actual)
- * @modes: possible values of @enable_mask
- * @autoidle_reg: register containing the DPLL autoidle mode bitfield
- * @idlest_reg: register containing the DPLL idle status bitfield
- * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
- * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
- * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
- * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
- * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
- * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
- * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
- * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
- * @flags: DPLL type/features (see below)
- *
- * Possible values for @flags:
- * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
- *
- * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
- *
- * XXX Some DPLLs have multiple bypass inputs, so it's not technically
- * correct to only have one @clk_bypass pointer.
- *
- * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
- * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a different structure, so that the runtime-fixed data
- * can be placed into read-only space.
- */
-struct dpll_data {
-       void __iomem            *mult_div1_reg;
-       u32                     mult_mask;
-       u32                     div1_mask;
-       struct clk              *clk_bypass;
-       struct clk              *clk_ref;
-       void __iomem            *control_reg;
-       u32                     enable_mask;
-       unsigned long           last_rounded_rate;
-       u16                     last_rounded_m;
-       u8                      last_rounded_m4xen;
-       u8                      last_rounded_lpmode;
-       u16                     max_multiplier;
-       u8                      last_rounded_n;
-       u8                      min_divider;
-       u16                     max_divider;
-       u8                      modes;
-       void __iomem            *autoidle_reg;
-       void __iomem            *idlest_reg;
-       u32                     autoidle_mask;
-       u32                     freqsel_mask;
-       u32                     idlest_mask;
-       u32                     dco_mask;
-       u32                     sddiv_mask;
-       u32                     lpmode_mask;
-       u32                     m4xen_mask;
-       u8                      auto_recal_bit;
-       u8                      recal_en_bit;
-       u8                      recal_st_bit;
-       u8                      flags;
-};
-
-/*
- * struct clk.flags possibilities
- *
- * XXX document the rest of the clock flags here
- *
- * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
- *     bits share the same register.  This flag allows the
- *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
- *     should be used.  This is a temporary solution - a better approach
- *     would be to associate clock type-specific data with the clock,
- *     similar to the struct dpll_data approach.
- */
-#define ENABLE_REG_32BIT       (1 << 0)        /* Use 32-bit access */
-#define CLOCK_IDLE_CONTROL     (1 << 1)
-#define CLOCK_NO_IDLE_PARENT   (1 << 2)
-#define ENABLE_ON_INIT         (1 << 3)        /* Enable upon framework init */
-#define INVERT_ENABLE          (1 << 4)        /* 0 enables, 1 disables */
-#define CLOCK_CLKOUTX2         (1 << 5)
-
-/**
- * struct clk_hw_omap - OMAP struct clk
- * @node: list_head connecting this clock into the full clock list
- * @enable_reg: register to write to enable the clock (see @enable_bit)
- * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
- * @flags: see "struct clk.flags possibilities" above
- * @clksel_reg: for clksel clks, register va containing src/divisor select
- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
- * @clksel: for clksel clks, pointer to struct clksel for this clock
- * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
- * @clkdm_name: clockdomain name that this clock is contained in
- * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
- * @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
- * @src_offset: bitshift for source selection bitfield (OMAP1 only)
- *
- * XXX @rate_offset, @src_offset should probably be removed and OMAP1
- * clock code converted to use clksel.
- *
- */
-
-struct clk_hw_omap_ops;
-
-struct clk_hw_omap {
-       struct clk_hw           hw;
-       struct list_head        node;
-       unsigned long           fixed_rate;
-       u8                      fixed_div;
-       void __iomem            *enable_reg;
-       u8                      enable_bit;
-       u8                      flags;
-       void __iomem            *clksel_reg;
-       u32                     clksel_mask;
-       const struct clksel     *clksel;
-       struct dpll_data        *dpll_data;
-       const char              *clkdm_name;
-       struct clockdomain      *clkdm;
-       const struct clk_hw_omap_ops    *ops;
-};
-
 struct clk_hw_omap_ops {
        void                    (*find_idlest)(struct clk_hw_omap *oclk,
                                        void __iomem **idlest_reg,
@@ -348,36 +213,13 @@ unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
 #define OMAP4XXX_EN_DPLL_FRBYPASS              0x6
 #define OMAP4XXX_EN_DPLL_LOCKED                        0x7
 
-/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
-#define DPLL_LOW_POWER_STOP    0x1
-#define DPLL_LOW_POWER_BYPASS  0x5
-#define DPLL_LOCKED            0x7
-
-/* DPLL Type and DCO Selection Flags */
-#define DPLL_J_TYPE            0x1
-
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                       unsigned long *parent_rate);
-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
-int omap3_noncore_dpll_enable(struct clk_hw *hw);
-void omap3_noncore_dpll_disable(struct clk_hw *hw);
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long parent_rate);
 u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
 void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
 void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate);
 int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk);
 void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
 void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
-                               unsigned long parent_rate);
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate);
 
-void omap2_init_clk_clkdm(struct clk_hw *clk);
 void __init omap2_clk_disable_clkdm_control(void);
 
 /* clkt_clksel.c public functions */
@@ -396,29 +238,25 @@ int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
 extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
 extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
 
-u8 omap2_init_dpll_parent(struct clk_hw *hw);
 unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
 
-int omap2_dflt_clk_enable(struct clk_hw *hw);
-void omap2_dflt_clk_disable(struct clk_hw *hw);
-int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
                                   void __iomem **other_reg,
                                   u8 *other_bit);
 void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
                                void __iomem **idlest_reg,
                                u8 *idlest_bit, u8 *idlest_val);
-void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap2_clk_enable_autoidle_all(void);
-int omap2_clk_disable_autoidle_all(void);
 int omap2_clk_allow_idle(struct clk *clk);
 int omap2_clk_deny_idle(struct clk *clk);
-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
                               const char *core_ck_name,
                               const char *mpu_ck_name);
 
+u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
+void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
+
 extern u16 cpu_mask;
 
 extern const struct clkops clkops_omap2_dflt_wait;
@@ -433,19 +271,12 @@ extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
 extern struct clk dummy_ck;
 
-extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
 extern const struct clk_hw_omap_ops clkhwops_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
-extern const struct clk_hw_omap_ops clkhwops_iclk;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
 extern const struct clk_hw_omap_ops clkhwops_apll54;
 extern const struct clk_hw_omap_ops clkhwops_apll96;
 extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
@@ -460,6 +291,8 @@ extern const struct clksel_rate div_1_3_rates[];
 extern const struct clksel_rate div_1_4_rates[];
 extern const struct clksel_rate div31_1to31_rates[];
 
+extern void __iomem *clk_memmaps[];
+
 extern int am33xx_clk_init(void);
 
 extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
index bbd6a3f717e64e5b23cce67591f374d4dcb7b2f3..91ccb962e09e9ed7a59e45c1399de556048724d7 100644 (file)
@@ -43,6 +43,7 @@ int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
        struct clk_divider *parent;
        struct clk_hw *parent_hw;
        u32 dummy_v, orig_v;
+       struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
        int ret;
 
        /* Clear PWRDN bit of HSDIVIDER */
@@ -53,15 +54,15 @@ int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
 
        /* Restore the dividers */
        if (!ret) {
-               orig_v = __raw_readl(parent->reg);
+               orig_v = omap2_clk_readl(omap_clk, parent->reg);
                dummy_v = orig_v;
 
                /* Write any other value different from the Read value */
                dummy_v ^= (1 << parent->shift);
-               __raw_writel(dummy_v, parent->reg);
+               omap2_clk_writel(dummy_v, omap_clk, parent->reg);
 
                /* Write the original divider */
-               __raw_writel(orig_v, parent->reg);
+               omap2_clk_writel(orig_v, omap_clk, parent->reg);
        }
 
        return ret;
index 8cd4b0a882aec39418c8adcd4e41daab0a010c0d..78d9f562e3ce796b76821c812ea3a7cf56050fb0 100644 (file)
@@ -9,11 +9,8 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H
 
 int omap3xxx_clk_init(void);
-int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
-                                       unsigned long parent_rate);
 int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate,
                                        unsigned long parent_rate);
-void omap3_clk_lock_dpll5(void);
 
 extern struct clk *sdrc_ick_p;
 extern struct clk *arm_fck_p;
index 240db38f232c66226bca15be02aa144a8021acce..e515278351600436a691a77770153690f29348d4 100644 (file)
@@ -306,7 +306,7 @@ struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
 /* SoC specific clock initializer */
-extern int (*omap_clk_init)(void);
+int omap_clk_init(void);
 
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
index 3a0296cfcace879a322a6c414b4b9de9bb0cce62..3185ced807c952804d50199fd3ff7bc8ea68fb8f 100644 (file)
@@ -50,10 +50,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 
        dd = clk->dpll_data;
 
-       v = __raw_readl(dd->control_reg);
+       v = omap2_clk_readl(clk, dd->control_reg);
        v &= ~dd->enable_mask;
        v |= clken_bits << __ffs(dd->enable_mask);
-       __raw_writel(v, dd->control_reg);
+       omap2_clk_writel(v, clk, dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -69,8 +69,8 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
 
        state <<= __ffs(dd->idlest_mask);
 
-       while (((__raw_readl(dd->idlest_reg) & dd->idlest_mask) != state) &&
-              i < MAX_DPLL_WAIT_TRIES) {
+       while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask)
+               != state) && i < MAX_DPLL_WAIT_TRIES) {
                i++;
                udelay(1);
        }
@@ -147,7 +147,7 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
        state <<= __ffs(dd->idlest_mask);
 
        /* Check if already locked */
-       if ((__raw_readl(dd->idlest_reg) & dd->idlest_mask) == state)
+       if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state)
                goto done;
 
        ai = omap3_dpll_autoidle_read(clk);
@@ -311,14 +311,14 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
         * only since freqsel field is no longer present on other devices.
         */
        if (cpu_is_omap343x()) {
-               v = __raw_readl(dd->control_reg);
+               v = omap2_clk_readl(clk, dd->control_reg);
                v &= ~dd->freqsel_mask;
                v |= freqsel << __ffs(dd->freqsel_mask);
-               __raw_writel(v, dd->control_reg);
+               omap2_clk_writel(v, clk, dd->control_reg);
        }
 
        /* Set DPLL multiplier, divider */
-       v = __raw_readl(dd->mult_div1_reg);
+       v = omap2_clk_readl(clk, dd->mult_div1_reg);
        v &= ~(dd->mult_mask | dd->div1_mask);
        v |= dd->last_rounded_m << __ffs(dd->mult_mask);
        v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
@@ -336,11 +336,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                v |= sd_div << __ffs(dd->sddiv_mask);
        }
 
-       __raw_writel(v, dd->mult_div1_reg);
+       omap2_clk_writel(v, clk, dd->mult_div1_reg);
 
        /* Set 4X multiplier and low-power mode */
        if (dd->m4xen_mask || dd->lpmode_mask) {
-               v = __raw_readl(dd->control_reg);
+               v = omap2_clk_readl(clk, dd->control_reg);
 
                if (dd->m4xen_mask) {
                        if (dd->last_rounded_m4xen)
@@ -356,7 +356,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                                v &= ~dd->lpmode_mask;
                }
 
-               __raw_writel(v, dd->control_reg);
+               omap2_clk_writel(v, clk, dd->control_reg);
        }
 
        /* We let the clock framework set the other output dividers later */
@@ -554,7 +554,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return -EINVAL;
 
-       v = __raw_readl(dd->autoidle_reg);
+       v = omap2_clk_readl(clk, dd->autoidle_reg);
        v &= dd->autoidle_mask;
        v >>= __ffs(dd->autoidle_mask);
 
@@ -588,10 +588,10 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
         * by writing 0x5 instead of 0x1.  Add some mechanism to
         * optionally enter this mode.
         */
-       v = __raw_readl(dd->autoidle_reg);
+       v = omap2_clk_readl(clk, dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
-       __raw_writel(v, dd->autoidle_reg);
+       omap2_clk_writel(v, clk, dd->autoidle_reg);
 
 }
 
@@ -614,10 +614,10 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
        if (!dd->autoidle_reg)
                return;
 
-       v = __raw_readl(dd->autoidle_reg);
+       v = omap2_clk_readl(clk, dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-       __raw_writel(v, dd->autoidle_reg);
+       omap2_clk_writel(v, clk, dd->autoidle_reg);
 
 }
 
@@ -639,6 +639,9 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
        struct clk_hw_omap *pclk = NULL;
        struct clk *parent;
 
+       if (!parent_rate)
+               return 0;
+
        /* Walk up the parents of clk, looking for a DPLL */
        do {
                do {
@@ -660,7 +663,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 
        WARN_ON(!dd->enable_mask);
 
-       v = __raw_readl(dd->control_reg) & dd->enable_mask;
+       v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
                rate = parent_rate;
index d28b0f7267151dfdcf2909b1647c9a5b80ba661b..52f9438b92f2a5d165b548b323bacb8680588bae 100644 (file)
@@ -42,7 +42,7 @@ int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = __raw_readl(clk->clksel_reg);
+       v = omap2_clk_readl(clk, clk->clksel_reg);
        v &= mask;
        v >>= __ffs(mask);
 
@@ -61,10 +61,10 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = __raw_readl(clk->clksel_reg);
+       v = omap2_clk_readl(clk, clk->clksel_reg);
        /* Clear the bit to allow gatectrl */
        v &= ~mask;
-       __raw_writel(v, clk->clksel_reg);
+       omap2_clk_writel(v, clk, clk->clksel_reg);
 }
 
 void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
@@ -79,10 +79,10 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = __raw_readl(clk->clksel_reg);
+       v = omap2_clk_readl(clk, clk->clksel_reg);
        /* Set the bit to deny gatectrl */
        v |= mask;
-       __raw_writel(v, clk->clksel_reg);
+       omap2_clk_writel(v, clk, clk->clksel_reg);
 }
 
 const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -140,7 +140,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
        rate = omap2_get_dpll_rate(clk);
 
        /* regm4xen adds a multiplier of 4 to DPLL calculations */
-       v = __raw_readl(dd->control_reg);
+       v = omap2_clk_readl(clk, dd->control_reg);
        if (v & OMAP4430_DPLL_REGM4XEN_MASK)
                rate *= OMAP4430_REGM4XEN_MULT;
 
index 07b68d5a7940e402705568114b7e0523cdda44f8..47381fd8746f6f673a6c2aeaa25ca11436c3809e 100644 (file)
 #include "prm44xx.h"
 
 /*
- * omap_clk_init: points to a function that does the SoC-specific
+ * omap_clk_soc_init: points to a function that does the SoC-specific
  * clock initializations
  */
-int (*omap_clk_init)(void);
+static int (*omap_clk_soc_init)(void);
 
 /*
  * The machine specific code may provide the extra mapping besides the
@@ -419,7 +419,7 @@ void __init omap2420_init_early(void)
        omap242x_clockdomains_init();
        omap2420_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = omap2420_clk_init;
+       omap_clk_soc_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -448,7 +448,7 @@ void __init omap2430_init_early(void)
        omap243x_clockdomains_init();
        omap2430_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = omap2430_clk_init;
+       omap_clk_soc_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -482,27 +482,35 @@ void __init omap3_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = omap3xxx_clk_init;
+       omap_clk_soc_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
 {
        omap3_init_early();
+       if (of_have_populated_dt())
+               omap_clk_soc_init = omap3430_dt_clk_init;
 }
 
 void __init omap35xx_init_early(void)
 {
        omap3_init_early();
+       if (of_have_populated_dt())
+               omap_clk_soc_init = omap3430_dt_clk_init;
 }
 
 void __init omap3630_init_early(void)
 {
        omap3_init_early();
+       if (of_have_populated_dt())
+               omap_clk_soc_init = omap3630_dt_clk_init;
 }
 
 void __init am35xx_init_early(void)
 {
        omap3_init_early();
+       if (of_have_populated_dt())
+               omap_clk_soc_init = am35xx_dt_clk_init;
 }
 
 void __init ti81xx_init_early(void)
@@ -520,7 +528,10 @@ void __init ti81xx_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = omap3xxx_clk_init;
+       if (of_have_populated_dt())
+               omap_clk_soc_init = ti81xx_dt_clk_init;
+       else
+               omap_clk_soc_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -581,7 +592,7 @@ void __init am33xx_init_early(void)
        am33xx_clockdomains_init();
        am33xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = am33xx_clk_init;
+       omap_clk_soc_init = am33xx_dt_clk_init;
 }
 
 void __init am33xx_init_late(void)
@@ -606,6 +617,7 @@ void __init am43xx_init_early(void)
        am43xx_clockdomains_init();
        am43xx_hwmod_init();
        omap_hwmod_init_postsetup();
+       omap_clk_soc_init = am43xx_dt_clk_init;
 }
 
 void __init am43xx_init_late(void)
@@ -635,7 +647,7 @@ void __init omap4430_init_early(void)
        omap44xx_clockdomains_init();
        omap44xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap_clk_init = omap4xxx_clk_init;
+       omap_clk_soc_init = omap4xxx_dt_clk_init;
 }
 
 void __init omap4430_init_late(void)
@@ -666,6 +678,7 @@ void __init omap5_init_early(void)
        omap54xx_clockdomains_init();
        omap54xx_hwmod_init();
        omap_hwmod_init_postsetup();
+       omap_clk_soc_init = omap5xxx_dt_clk_init;
 }
 
 void __init omap5_init_late(void)
@@ -691,6 +704,7 @@ void __init dra7xx_init_early(void)
        dra7xx_clockdomains_init();
        dra7xx_hwmod_init();
        omap_hwmod_init_postsetup();
+       omap_clk_soc_init = dra7xx_dt_clk_init;
 }
 
 void __init dra7xx_init_late(void)
@@ -710,3 +724,17 @@ void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                _omap2_init_reprogram_sdrc();
        }
 }
+
+int __init omap_clk_init(void)
+{
+       int ret = 0;
+
+       if (!omap_clk_soc_init)
+               return 0;
+
+       ret = of_prcm_init();
+       if (!ret)
+               ret = omap_clk_soc_init();
+
+       return ret;
+}
index f7a6fd35b1e43f6dc9d36256508928b9ba135ea9..42d81885c700c498babd2dd2e5d322e3af2c3f19 100644 (file)
@@ -686,6 +686,8 @@ static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
        if (oh->clkdm) {
                return oh->clkdm;
        } else if (oh->_clk) {
+               if (__clk_get_flags(oh->_clk) & CLK_IS_BASIC)
+                       return NULL;
                clk = to_clk_hw_omap(__clk_get_hw(oh->_clk));
                return  clk->clkdm;
        }
@@ -1576,7 +1578,7 @@ static int _init_clkdm(struct omap_hwmod *oh)
        if (!oh->clkdm) {
                pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
                        oh->name, oh->clkdm_name);
-               return -EINVAL;
+               return 0;
        }
 
        pr_debug("omap_hwmod: %s: associated to clkdm %s\n",
@@ -4231,6 +4233,7 @@ void __init omap_hwmod_init(void)
                soc_ops.assert_hardreset = _omap2_assert_hardreset;
                soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
                soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
+               soc_ops.init_clkdm = _init_clkdm;
        } else if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx()) {
                soc_ops.enable_module = _omap4_enable_module;
                soc_ops.disable_module = _omap4_disable_module;
index ac25ae6667cf92c448d37a9fc25058d69f26be19..623db40fdbbda48c50888d620b6a8a28b8a27c17 100644 (file)
@@ -18,6 +18,7 @@
 # ifndef __ASSEMBLER__
 extern void __iomem *prm_base;
 extern void omap2_set_globals_prm(void __iomem *prm);
+int of_prcm_init(void);
 # endif
 
 
index a2e1174ad1b6a6632ad904e4a0b8c5f37dea1e79..b4c4ab9c8044476d0777ed04cb8c9595d2f29f83 100644 (file)
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
 
 #include "soc.h"
 #include "prm2xxx_3xxx.h"
@@ -30,6 +34,7 @@
 #include "prm3xxx.h"
 #include "prm44xx.h"
 #include "common.h"
+#include "clock.h"
 
 /*
  * OMAP_PRCM_MAX_NR_PENDING_REG: maximum number of PRM_IRQ*_MPU regs
@@ -464,3 +469,64 @@ int prm_unregister(struct prm_ll_data *pld)
 
        return 0;
 }
+
+static struct of_device_id omap_prcm_dt_match_table[] = {
+       { .compatible = "ti,am3-prcm" },
+       { .compatible = "ti,am3-scrm" },
+       { .compatible = "ti,am4-prcm" },
+       { .compatible = "ti,am4-scrm" },
+       { .compatible = "ti,omap3-prm" },
+       { .compatible = "ti,omap3-cm" },
+       { .compatible = "ti,omap3-scrm" },
+       { .compatible = "ti,omap4-cm1" },
+       { .compatible = "ti,omap4-prm" },
+       { .compatible = "ti,omap4-cm2" },
+       { .compatible = "ti,omap4-scrm" },
+       { .compatible = "ti,omap5-prm" },
+       { .compatible = "ti,omap5-cm-core-aon" },
+       { .compatible = "ti,omap5-scrm" },
+       { .compatible = "ti,omap5-cm-core" },
+       { .compatible = "ti,dra7-prm" },
+       { .compatible = "ti,dra7-cm-core-aon" },
+       { .compatible = "ti,dra7-cm-core" },
+       { }
+};
+
+static struct clk_hw_omap memmap_dummy_ck = {
+       .flags = MEMMAP_ADDRESSING,
+};
+
+static u32 prm_clk_readl(void __iomem *reg)
+{
+       return omap2_clk_readl(&memmap_dummy_ck, reg);
+}
+
+static void prm_clk_writel(u32 val, void __iomem *reg)
+{
+       omap2_clk_writel(val, &memmap_dummy_ck, reg);
+}
+
+static struct ti_clk_ll_ops omap_clk_ll_ops = {
+       .clk_readl = prm_clk_readl,
+       .clk_writel = prm_clk_writel,
+};
+
+int __init of_prcm_init(void)
+{
+       struct device_node *np;
+       void __iomem *mem;
+       int memmap_index = 0;
+
+       ti_clk_ll_ops = &omap_clk_ll_ops;
+
+       for_each_matching_node(np, omap_prcm_dt_match_table) {
+               mem = of_iomap(np, 0);
+               clk_memmaps[memmap_index] = mem;
+               ti_dt_clk_init_provider(np, memmap_index);
+               memmap_index++;
+       }
+
+       ti_dt_clockdomains_setup();
+
+       return 0;
+}
index ec084d158f642b3cf919adbbb0c6fd97e64f6317..74044aaf438b6f2c5fa9c093d40e15077b06f153 100644 (file)
@@ -570,8 +570,7 @@ static inline void __init realtime_counter_init(void)
                               clksrc_nr, clksrc_src, clksrc_prop)      \
 void __init omap##name##_gptimer_timer_init(void)                      \
 {                                                                      \
-       if (omap_clk_init)                                              \
-               omap_clk_init();                                        \
+       omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
        omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src,         \
@@ -582,8 +581,7 @@ void __init omap##name##_gptimer_timer_init(void)                   \
                                clksrc_nr, clksrc_src, clksrc_prop)     \
 void __init omap##name##_sync32k_timer_init(void)              \
 {                                                                      \
-       if (omap_clk_init)                                              \
-               omap_clk_init();                                        \
+       omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
        /* Enable the use of clocksource="gp_timer" kernel parameter */ \
diff --git a/arch/arm/plat-samsung/include/plat/regs-nand.h b/arch/arm/plat-samsung/include/plat/regs-nand.h
deleted file mode 100644 (file)
index 238efea..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-nand.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics <linux@simtec.co.uk>
- *     http://www.simtec.co.uk/products/SWLINUX/
- *
- * 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.
- *
- * S3C2410 NAND register definitions
-*/
-
-#ifndef __ASM_ARM_REGS_NAND
-#define __ASM_ARM_REGS_NAND
-
-
-#define S3C2410_NFREG(x) (x)
-
-#define S3C2410_NFCONF  S3C2410_NFREG(0x00)
-#define S3C2410_NFCMD   S3C2410_NFREG(0x04)
-#define S3C2410_NFADDR  S3C2410_NFREG(0x08)
-#define S3C2410_NFDATA  S3C2410_NFREG(0x0C)
-#define S3C2410_NFSTAT  S3C2410_NFREG(0x10)
-#define S3C2410_NFECC   S3C2410_NFREG(0x14)
-
-#define S3C2440_NFCONT   S3C2410_NFREG(0x04)
-#define S3C2440_NFCMD    S3C2410_NFREG(0x08)
-#define S3C2440_NFADDR   S3C2410_NFREG(0x0C)
-#define S3C2440_NFDATA   S3C2410_NFREG(0x10)
-#define S3C2440_NFECCD0  S3C2410_NFREG(0x14)
-#define S3C2440_NFECCD1  S3C2410_NFREG(0x18)
-#define S3C2440_NFECCD   S3C2410_NFREG(0x1C)
-#define S3C2440_NFSTAT   S3C2410_NFREG(0x20)
-#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
-#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
-#define S3C2440_NFMECC0  S3C2410_NFREG(0x2C)
-#define S3C2440_NFMECC1  S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC   S3C2410_NFREG(0x34)
-#define S3C2440_NFSBLK   S3C2410_NFREG(0x38)
-#define S3C2440_NFEBLK   S3C2410_NFREG(0x3C)
-
-#define S3C2412_NFSBLK         S3C2410_NFREG(0x20)
-#define S3C2412_NFEBLK         S3C2410_NFREG(0x24)
-#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
-#define S3C2412_NFMECC_ERR0    S3C2410_NFREG(0x2C)
-#define S3C2412_NFMECC_ERR1    S3C2410_NFREG(0x30)
-#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
-#define S3C2412_NFMECC1                S3C2410_NFREG(0x38)
-#define S3C2412_NFSECC         S3C2410_NFREG(0x3C)
-
-#define S3C2410_NFCONF_EN          (1<<15)
-#define S3C2410_NFCONF_512BYTE     (1<<14)
-#define S3C2410_NFCONF_4STEP       (1<<13)
-#define S3C2410_NFCONF_INITECC     (1<<12)
-#define S3C2410_NFCONF_nFCE        (1<<11)
-#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
-#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
-#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)
-
-#define S3C2410_NFSTAT_BUSY        (1<<0)
-
-#define S3C2440_NFCONF_BUSWIDTH_8      (0<<0)
-#define S3C2440_NFCONF_BUSWIDTH_16     (1<<0)
-#define S3C2440_NFCONF_ADVFLASH                (1<<3)
-#define S3C2440_NFCONF_TACLS(x)                ((x)<<12)
-#define S3C2440_NFCONF_TWRPH0(x)       ((x)<<8)
-#define S3C2440_NFCONF_TWRPH1(x)       ((x)<<4)
-
-#define S3C2440_NFCONT_LOCKTIGHT       (1<<13)
-#define S3C2440_NFCONT_SOFTLOCK                (1<<12)
-#define S3C2440_NFCONT_ILLEGALACC_EN   (1<<10)
-#define S3C2440_NFCONT_RNBINT_EN       (1<<9)
-#define S3C2440_NFCONT_RN_FALLING      (1<<8)
-#define S3C2440_NFCONT_SPARE_ECCLOCK   (1<<6)
-#define S3C2440_NFCONT_MAIN_ECCLOCK    (1<<5)
-#define S3C2440_NFCONT_INITECC         (1<<4)
-#define S3C2440_NFCONT_nFCE            (1<<1)
-#define S3C2440_NFCONT_ENABLE          (1<<0)
-
-#define S3C2440_NFSTAT_READY           (1<<0)
-#define S3C2440_NFSTAT_nCE             (1<<1)
-#define S3C2440_NFSTAT_RnB_CHANGE      (1<<2)
-#define S3C2440_NFSTAT_ILLEGAL_ACCESS  (1<<3)
-
-#define S3C2412_NFCONF_NANDBOOT                (1<<31)
-#define S3C2412_NFCONF_ECCCLKCON       (1<<30)
-#define S3C2412_NFCONF_ECC_MLC         (1<<24)
-#define S3C2412_NFCONF_TACLS_MASK      (7<<12) /* 1 extra bit of Tacls */
-
-#define S3C2412_NFCONT_ECC4_DIRWR      (1<<18)
-#define S3C2412_NFCONT_LOCKTIGHT       (1<<17)
-#define S3C2412_NFCONT_SOFTLOCK                (1<<16)
-#define S3C2412_NFCONT_ECC4_ENCINT     (1<<13)
-#define S3C2412_NFCONT_ECC4_DECINT     (1<<12)
-#define S3C2412_NFCONT_MAIN_ECC_LOCK   (1<<7)
-#define S3C2412_NFCONT_INIT_MAIN_ECC   (1<<5)
-#define S3C2412_NFCONT_nFCE1           (1<<2)
-#define S3C2412_NFCONT_nFCE0           (1<<1)
-
-#define S3C2412_NFSTAT_ECC_ENCDONE     (1<<7)
-#define S3C2412_NFSTAT_ECC_DECDONE     (1<<6)
-#define S3C2412_NFSTAT_ILLEGAL_ACCESS  (1<<5)
-#define S3C2412_NFSTAT_RnB_CHANGE      (1<<4)
-#define S3C2412_NFSTAT_nFCE1           (1<<3)
-#define S3C2412_NFSTAT_nFCE0           (1<<2)
-#define S3C2412_NFSTAT_Res1            (1<<1)
-#define S3C2412_NFSTAT_READY           (1<<0)
-
-#define S3C2412_NFECCERR_SERRDATA(x)   (((x) >> 21) & 0xf)
-#define S3C2412_NFECCERR_SERRBIT(x)    (((x) >> 18) & 0x7)
-#define S3C2412_NFECCERR_MERRDATA(x)   (((x) >> 7) & 0x3ff)
-#define S3C2412_NFECCERR_MERRBIT(x)    (((x) >> 4) & 0x7)
-#define S3C2412_NFECCERR_SPARE_ERR(x)  (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_MAIN_ERR(x)   (((x) >> 2) & 0x3)
-#define S3C2412_NFECCERR_NONE          (0)
-#define S3C2412_NFECCERR_1BIT          (1)
-#define S3C2412_NFECCERR_MULTIBIT      (2)
-#define S3C2412_NFECCERR_ECCAREA       (3)
-
-
-
-#endif /* __ASM_ARM_REGS_NAND */
-
index 3961930421274b9f89e47f691554c6dbad61ecb6..4f424ae3b36de8225e5bee3977bde03a82548bb4 100644 (file)
@@ -17,7 +17,7 @@
 #ifdef CONFIG_MTD_UCLINUX
 #include <linux/mtd/map.h>
 #include <linux/ext2_fs.h>
-#include <linux/cramfs_fs.h>
+#include <uapi/linux/cramfs_fs.h>
 #include <linux/romfs_fs.h>
 #endif
 
index 9c957c81c6885acd595c42d1c470a1390cef6feb..ed0fcdf7e9905cb3050b50c6d467b2a5c8ba5f74 100644 (file)
@@ -122,12 +122,6 @@ config ETRAX100LX_V2
        help
          Support version 2 of the ETRAX 100LX.
 
-config SVINTO_SIM
-       bool "ETRAX-100LX-for-xsim-simulator"
-       select ARCH_USES_GETTIMEOFFSET
-       help
-         Support the xsim ETRAX Simulator.
-
 config ETRAXFS
        bool "ETRAX-FS-V32"
        help
index 609d5510410e06e869567268a20edf133c588853..f4374bae4fb4e632a5f81102514efa4ec1477ed0 100644 (file)
@@ -838,13 +838,13 @@ static int __init gpio_init(void)
         * in some tests.
         */
        res = request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
-               IRQF_SHARED | IRQF_DISABLED, "gpio poll", gpio_name);
+               IRQF_SHARED, "gpio poll", gpio_name);
        if (res) {
                printk(KERN_CRIT "err: timer0 irq for gpio\n");
                return res;
        }
        res = request_irq(PA_IRQ_NBR, gpio_interrupt,
-               IRQF_SHARED | IRQF_DISABLED, "gpio PA", gpio_name);
+               IRQF_SHARED, "gpio PA", gpio_name);
        if (res)
                printk(KERN_CRIT "err: PA irq for gpio\n");
 
index a1c498d18d3184d196fa184e7bfe890c982ca53e..29eb02ab3f259fa0317986400f25c3ede747a6c1 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/timer.h>
+#include <linux/wait.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/io.h>
@@ -580,7 +581,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
                        if (port == &ports[0]) {
                                if (request_irq(8,
                                                manual_interrupt,
-                                               IRQF_SHARED | IRQF_DISABLED,
+                                               IRQF_SHARED,
                                                "synchronous serial manual irq",
                                                &ports[0])) {
                                        printk(KERN_CRIT "Can't alloc "
@@ -590,7 +591,7 @@ static int sync_serial_open(struct inode *inode, struct file *file)
                        } else if (port == &ports[1]) {
                                if (request_irq(8,
                                                manual_interrupt,
-                                               IRQF_SHARED | IRQF_DISABLED,
+                                               IRQF_SHARED,
                                                "synchronous serial manual irq",
                                                &ports[1])) {
                                        printk(KERN_CRIT "Can't alloc "
@@ -1136,7 +1137,8 @@ static ssize_t sync_serial_read(struct file *file, char *buf,
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
-               interruptible_sleep_on(&port->in_wait_q);
+               wait_event_interruptible(port->in_wait_q,
+                                        !(start == end && !port->full));
                if (signal_pending(current))
                        return -EINTR;
 
index dcfec41d353300b59656fc6ad7c8bd288d84d5d6..4841e822cdd1aec04d38e7c23d63bb360e767b5e 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $
 #
 # Makefile for the linux kernel.
 #
index f932c85fbde48403f11b9056994411d1d50cbccc..7d307cce8bd8f63a4d1928ed82501ef99cee4bd0 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/tty.h>
 #include <arch/svinto.h>
-#include <asm/io.h>             /* Get SIMCOUT. */
 
 extern void reset_watchdog(void);
 
@@ -318,12 +317,6 @@ console_write(struct console *co, const char *buf, unsigned int len)
        if (!port)
                return;
 
-#ifdef CONFIG_SVINTO_SIM
-       /* no use to simulate the serial debug output */
-       SIMCOUT(buf, len);
-       return;
-#endif
-
         console_write_direct(co, buf, len);
 }
 
index 897bba67bf7afed9a0b392db5d652349ae352f6c..81570fcd0412815917617ee4a3063c2a76c32976 100644 (file)
@@ -13,8 +13,8 @@
  * after a timer-interrupt and after each system call.
  *
  * Stack layout in 'ret_from_system_call':
- *     ptrace needs to have all regs on the stack.
- *     if the order here is changed, it needs to be 
+ *     ptrace needs to have all regs on the stack.
+ *     if the order here is changed, it needs to be
  *     updated in fork.c:copy_process, signal.c:do_signal,
  *     ptrace.c and ptrace.h
  *
@@ -31,7 +31,7 @@
 #include <asm/pgtable.h>
 
        ;; functions exported from this file
-       
+
        .globl system_call
        .globl ret_from_intr
        .globl ret_from_fork
        .globl do_sigtrap
        .globl gdb_handle_breakpoint
        .globl sys_call_table
-       
+
        ;; below are various parts of system_call which are not in the fast-path
-       
-#ifdef CONFIG_PREEMPT  
+
+#ifdef CONFIG_PREEMPT
        ; Check if preemptive kernel scheduling should be done
 _resume_kernel:
        di
@@ -74,7 +74,7 @@ _need_resched:
        nop
 #else
 #define _resume_kernel _Rexit
-#endif 
+#endif
 
        ; Called at exit from fork. schedule_tail must be called to drop
        ; spinlock if CONFIG_PREEMPT
@@ -91,16 +91,16 @@ ret_from_kernel_thread:
        ba  ret_from_sys_call
 
 ret_from_intr:
-       ;; check for resched if preemptive kernel or if we're going back to user-mode 
+       ;; check for resched if preemptive kernel or if we're going back to user-mode
        ;; this test matches the user_regs(regs) macro
        ;; we cannot simply test $dccr, because that does not necessarily
        ;; reflect what mode we'll return into.
-       
+
        move.d  [$sp + PT_dccr], $r0; regs->dccr
        btstq   8, $r0          ; U-flag
        bpl     _resume_kernel
-       ; Note that di below is in delay slot 
-       
+       ; Note that di below is in delay slot
+
 _resume_userspace:
        di                      ; so need_resched and sigpending don't change
 
@@ -113,7 +113,7 @@ _resume_userspace:
        nop
        ba      _Rexit
        nop
-       
+
        ;; The system_call is called by a BREAK instruction, which works like
        ;; an interrupt call but it stores the return PC in BRP instead of IRP.
        ;; Since we dont really want to have two epilogues (one for system calls
@@ -123,7 +123,7 @@ _resume_userspace:
        ;;
        ;; Since we can't have system calls inside interrupts, it should not matter
        ;; that we don't stack IRP.
-       ;; 
+       ;;
        ;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp
        ;;
        ;; This function looks on the _surface_ like spaghetti programming, but it's
@@ -140,7 +140,7 @@ system_call:
        movem   $r13, [$sp]     ; push r0-r13
        push    $r10            ; push orig_r10
        clear.d [$sp=$sp-4]     ; frametype == 0, normal stackframe
-       
+
        movs.w  -ENOSYS, $r0
        move.d  $r0, [$sp+PT_r10]       ; put the default return value in r10 in the frame
 
@@ -148,17 +148,17 @@ system_call:
 
        movs.w  -8192, $r0      ; THREAD_SIZE == 8192
        and.d   $sp, $r0
-       
+
        move.d  [$r0+TI_flags], $r0
        btstq   TIF_SYSCALL_TRACE, $r0
        bmi     _syscall_trace_entry
-       nop     
+       nop
 
-_syscall_traced:       
+_syscall_traced:
 
        ;; check for sanity in the requested syscall number
-       
-       cmpu.w  NR_syscalls, $r9        
+
+       cmpu.w  NR_syscalls, $r9
        bcc     ret_from_sys_call
        lslq    2, $r9          ;  multiply by 4, in the delay slot
 
@@ -166,28 +166,28 @@ _syscall_traced:
        ;; of the register structure itself. some syscalls need this.
 
        push    $sp
-       
+
        ;; the parameter carrying registers r10, r11, r12 and 13 are intact.
-       ;; the fifth and sixth parameters (if any) was in mof and srp 
+       ;; the fifth and sixth parameters (if any) was in mof and srp
        ;; respectively, and we need to put them on the stack.
 
        push    $srp
        push    $mof
-       
+
        jsr     [$r9+sys_call_table]    ; actually do the system call
        addq    3*4, $sp                ; pop the mof, srp and regs parameters
        move.d  $r10, [$sp+PT_r10]      ; save the return value
 
        moveq   1, $r9          ; "parameter" to ret_from_sys_call to show it was a sys call
-       
+
        ;; fall through into ret_from_sys_call to return
-       
+
 ret_from_sys_call:
        ;; r9 is a parameter - if >=1 we came from a syscall, if 0, from an irq
-               
+
        ;; get the current task-struct pointer (see top for defs)
 
-       movs.w  -8192, $r0      ; THREAD_SIZE == 8192 
+       movs.w  -8192, $r0      ; THREAD_SIZE == 8192
        and.d   $sp, $r0
 
        di                      ; make sure need_resched and sigpending don't change
@@ -202,7 +202,7 @@ _Rexit:
        bne     _RBFexit        ; was not CRIS_FRAME_NORMAL, handle otherwise
        addq    4, $sp          ; skip orig_r10, in delayslot
        movem   [$sp+], $r13    ; registers r0-r13
-       pop     $mof            ; multiply overflow register 
+       pop     $mof            ; multiply overflow register
        pop     $dccr           ; condition codes
        pop     $srp            ; subroutine return pointer
        ;; now we have a 4-word SBFS frame which we do not want to restore
@@ -216,14 +216,14 @@ _Rexit:
 
 _RBFexit:
        movem   [$sp+], $r13    ; registers r0-r13, in delay slot
-       pop     $mof            ; multiply overflow register 
+       pop     $mof            ; multiply overflow register
        pop     $dccr           ; condition codes
        pop     $srp            ; subroutine return pointer
        rbf     [$sp+]          ; return by popping the CPU status
 
        ;; We get here after doing a syscall if extra work might need to be done
        ;; perform syscall exit tracing if needed
-       
+
 _syscall_exit_work:
        ;; $r0 contains current at this point and irq's are disabled
 
@@ -231,22 +231,22 @@ _syscall_exit_work:
        btstq   TIF_SYSCALL_TRACE, $r1
        bpl     _work_pending
        nop
-       
+
        ei
 
        move.d  $r9, $r1        ; preserve r9
        jsr     do_syscall_trace
        move.d  $r1, $r9
-       
+
        ba      _resume_userspace
        nop
-       
+
 _work_pending:
        move.d  [$r0+TI_flags], $r1
        btstq   TIF_NEED_RESCHED, $r1
        bpl     _work_notifysig ; was neither trace nor sched, must be signal/notify
        nop
-       
+
 _work_resched:
        move.d  $r9, $r1        ; preserve r9
        jsr     schedule
@@ -268,17 +268,17 @@ _work_notifysig:
        move.d  $sp, $r11       ; the regs param
        move.d  $r1, $r12       ; the thread_info_flags parameter
        jsr     do_notify_resume
-       
+
        ba _Rexit
        nop
 
        ;; We get here as a sidetrack when we've entered a syscall with the
        ;; trace-bit set. We need to call do_syscall_trace and then continue
        ;; with the call.
-       
+
 _syscall_trace_entry:
        ;; PT_r10 in the frame contains -ENOSYS as required, at this point
-       
+
        jsr     do_syscall_trace
 
        ;; now re-enter the syscall code to do the syscall itself
@@ -292,10 +292,10 @@ _syscall_trace_entry:
        move.d  [$sp+PT_r13],      $r13
        move    [$sp+PT_mof],      $mof
        move    [$sp+PT_srp],      $srp
-       
+
        ba      _syscall_traced
        nop
-       
+
        ;; resume performs the actual task-switching, by switching stack pointers
        ;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct
        ;; returns old current in r10
@@ -303,29 +303,29 @@ _syscall_trace_entry:
        ;; TODO:  see the i386 version. The switch_to which calls resume in our version
        ;;        could really be an inline asm of this.
 
-resume:        
-       push    $srp                     ; we keep the old/new PC on the stack 
+resume:
+       push    $srp                     ; we keep the old/new PC on the stack
        add.d   $r12, $r10               ; r10 = current tasks tss
        move    $dccr, [$r10+THREAD_dccr]; save irq enable state
        di
 
        move    $usp, [$r10+ THREAD_usp] ; save user-mode stackpointer
-       
+
        ;; See copy_thread for the reason why register R9 is saved.
        subq    10*4, $sp
        movem   $r9, [$sp]               ; save non-scratch registers and R9.
-       
+
        move.d  $sp, [$r10+THREAD_ksp]   ; save the kernel stack pointer for the old task
        move.d  $sp, $r10                ; return last running task in r10
        and.d   -8192, $r10              ; get thread_info from stackpointer
-       move.d  [$r10+TI_task], $r10     ; get task  
+       move.d  [$r10+TI_task], $r10     ; get task
        add.d   $r12, $r11               ; find the new tasks tss
        move.d  [$r11+THREAD_ksp], $sp   ; switch into the new stackframe by restoring kernel sp
 
        movem   [$sp+], $r9              ; restore non-scratch registers and R9.
 
        move    [$r11+THREAD_usp], $usp ; restore user-mode stackpointer
-       
+
        move    [$r11+THREAD_dccr], $dccr ; restore irq enable status
        jump    [$sp+]                   ; restore PC
 
@@ -401,7 +401,7 @@ mmu_bus_fault:
        push    $r10            ; frametype == 1, BUSFAULT frame type
 
        move.d  $sp, $r10       ; pt_regs argument to handle_mmu_bus_fault
-               
+
        jsr     handle_mmu_bus_fault  ; in arch/cris/arch-v10/mm/fault.c
 
        ;; now we need to return through the normal path, we cannot just
@@ -410,10 +410,10 @@ mmu_bus_fault:
        ;; whatever.
 
        moveq   0, $r9          ; busfault is equivalent to an irq
-               
+
        ba      ret_from_intr
        nop
-               
+
        ;; special handlers for breakpoint and NMI
 hwbreakpoint:
        push    $dccr
@@ -429,7 +429,7 @@ hwbreakpoint:
        pop     $dccr
        retb
        nop
-       
+
 IRQ1_interrupt:
        ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
        move    $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
@@ -457,7 +457,7 @@ IRQ1_interrupt:
        ba      _Rexit          ; Return the standard way
        nop
 wdog:
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_WATCHDOG)
 ;; Check if we're waiting for reset to happen, as signalled by
 ;; hard_reset_now setting cause_of_death to a magic value.  If so, just
 ;; get stuck until reset happens.
@@ -500,7 +500,7 @@ Watchdog_bite:
        move.d  $r10, [$r11]
 
 #endif
-       
+
 ;; Note that we don't do "setf m" here (or after two necessary NOPs),
 ;; since *not* doing that saves us from re-entrancy checks.  We don't want
 ;; to get here again due to possible subsequent NMIs; we want the watchdog
@@ -523,16 +523,16 @@ _watchdogmsg:
        .ascii  "Oops: bitten by watchdog\n\0"
        .previous
 
-#endif /* CONFIG_ETRAX_WATCHDOG and not CONFIG_SVINTO_SIM */
+#endif /* CONFIG_ETRAX_WATCHDOG */
 
-spurious_interrupt:    
+spurious_interrupt:
        di
        jump hard_reset_now
 
        ;; this handles the case when multiple interrupts arrive at the same time
        ;; we jump to the first set interrupt bit in a priority fashion
        ;; the hardware will call the unserved interrupts after the handler finishes
-       
+
 multiple_interrupt:
        ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
        move    $irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame
@@ -551,7 +551,7 @@ multiple_interrupt:
        jump    ret_from_intr
 
 do_sigtrap:
-       ;; 
+       ;;
        ;; SIGTRAP the process that executed the break instruction.
        ;; Make a frame that Rexit in entry.S expects.
        ;;
@@ -568,30 +568,30 @@ do_sigtrap:
        movs.w  -8192,$r9               ; THREAD_SIZE == 8192
        and.d   $sp, $r9
        move.d  [$r9+TI_task], $r10
-       move.d  [$r10+TASK_pid], $r10   ; current->pid as arg1. 
+       move.d  [$r10+TASK_pid], $r10   ; current->pid as arg1.
        moveq   5, $r11                 ; SIGTRAP as arg2.
-       jsr     sys_kill       
+       jsr     sys_kill
        jump    ret_from_intr           ; Use the return routine for interrupts.
 
-gdb_handle_breakpoint: 
+gdb_handle_breakpoint:
        push    $dccr
        push    $r0
 #ifdef CONFIG_ETRAX_KGDB
-       move    $dccr, $r0              ; U-flag not affected by previous insns. 
+       move    $dccr, $r0              ; U-flag not affected by previous insns.
        btstq   8, $r0                  ; Test the U-flag.
-       bmi     _ugdb_handle_breakpoint ; Go to user mode debugging. 
-       nop                             ; Empty delay slot (cannot pop r0 here). 
+       bmi     _ugdb_handle_breakpoint ; Go to user mode debugging.
+       nop                             ; Empty delay slot (cannot pop r0 here).
        pop     $r0                     ; Restore r0.
-       ba      kgdb_handle_breakpoint  ; Go to kernel debugging. 
+       ba      kgdb_handle_breakpoint  ; Go to kernel debugging.
        pop     $dccr                   ; Restore dccr in delay slot.
 #endif
-       
-_ugdb_handle_breakpoint:       
+
+_ugdb_handle_breakpoint:
        move    $brp, $r0               ; Use r0 temporarily for calculation.
        subq    2, $r0                  ; Set to address of previous instruction.
        move    $r0, $brp
-       pop     $r0                     ; Restore r0. 
-       ba      do_sigtrap              ; SIGTRAP the offending process. 
+       pop     $r0                     ; Restore r0.
+       ba      do_sigtrap              ; SIGTRAP the offending process.
        pop     $dccr                   ; Restore dccr in delay slot.
 
        .data
@@ -602,7 +602,7 @@ hw_bp_trig_ptr:
        .dword hw_bp_trigs
 
        .section .rodata,"a"
-sys_call_table:        
+sys_call_table:
        .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
        .long sys_exit
        .long sys_fork
@@ -713,7 +713,7 @@ sys_call_table:
        .long sys_newlstat
        .long sys_newfstat
        .long sys_ni_syscall    /* old sys_uname holder */
-       .long sys_ni_syscall    /* sys_iopl in i386 */
+       .long sys_ni_syscall    /* 110 */ /* sys_iopl in i386 */
        .long sys_vhangup
        .long sys_ni_syscall    /* old "idle" system call */
        .long sys_ni_syscall    /* vm86old in i386 */
@@ -730,7 +730,7 @@ sys_call_table:
        .long sys_adjtimex
        .long sys_mprotect      /* 125 */
        .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "create_module" */ 
+       .long sys_ni_syscall    /* old "create_module" */
        .long sys_init_module
        .long sys_delete_module
        .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
@@ -795,7 +795,7 @@ sys_call_table:
        .long sys_ni_syscall    /* streams2 */
        .long sys_vfork         /* 190 */
        .long sys_getrlimit
-       .long sys_mmap2
+       .long sys_mmap2         /* mmap_pgoff */
        .long sys_truncate64
        .long sys_ftruncate64
        .long sys_stat64        /* 195 */
@@ -861,21 +861,21 @@ sys_call_table:
        .long sys_epoll_ctl     /* 255 */
        .long sys_epoll_wait
        .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime         /* 260 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime         /* 265 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
        .long sys_statfs64
-       .long sys_fstatfs64     
-       .long sys_tgkill        /* 270 */
+       .long sys_fstatfs64
+       .long sys_tgkill                /* 270 */
        .long sys_utimes
-       .long sys_fadvise64_64
+       .long sys_fadvise64_64
        .long sys_ni_syscall    /* sys_vserver */
        .long sys_ni_syscall    /* sys_mbind */
        .long sys_ni_syscall    /* 275 sys_get_mempolicy */
@@ -886,7 +886,7 @@ sys_call_table:
        .long sys_mq_timedreceive       /* 280 */
        .long sys_mq_notify
        .long sys_mq_getsetattr
-       .long sys_ni_syscall            /* reserved for kexec */
+       .long sys_ni_syscall
        .long sys_waitid
        .long sys_ni_syscall            /* 285 */ /* available */
        .long sys_add_key
@@ -939,6 +939,22 @@ sys_call_table:
        .long sys_preadv
        .long sys_pwritev
        .long sys_setns                 /* 335 */
+       .long sys_name_to_handle_at
+       .long sys_open_by_handle_at
+       .long sys_rt_tgsigqueueinfo
+       .long sys_perf_event_open
+       .long sys_recvmmsg              /* 340 */
+       .long sys_accept4
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
+       .long sys_clock_adjtime         /* 345 */
+       .long sys_syncfs
+       .long sys_sendmmsg
+       .long sys_process_vm_readv
+       .long sys_process_vm_writev
+       .long sys_kcmp                  /* 350 */
+       .long sys_finit_module
 
         /*
          * NOTE!! This doesn't have to be exact - we just have
@@ -950,4 +966,4 @@ sys_call_table:
        .rept NR_syscalls-(.-sys_call_table)/4
                .long sys_ni_syscall
        .endr
-       
+
index a1f2014b4e3b3cae8006c75215f34ecc74688290..4a146e1749c93ce2b2e9d35cec6c167bf4815232 100644 (file)
@@ -1,12 +1,10 @@
 /*
  * Head of the kernel - alter with care
  *
- * Copyright (C) 2000, 2001 Axis Communications AB
+ * Copyright (C) 2000, 2001, 2010 Axis Communications AB
  *
- * Authors:    Bjorn Wesen (bjornw@axis.com)
- * 
  */
-       
+
 #define ASSEMBLER_MACROS_ONLY
 /* The IO_* macros use the ## token concatenation operator, so
    -traditional must not be used when assembling this file.  */
 
 #define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\
                              IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk)
-                               
+
        ;; exported symbols
-               
+
        .globl  etrax_irv
        .globl  romfs_start
        .globl  romfs_length
        .globl  romfs_in_flash
        .globl  swapper_pg_dir
-                                       
+
        .text
 
        ;; This is the entry point of the kernel. We are in supervisor mode.
        ;; put a nop (2 bytes) here first so we dont accidentally skip the di
        ;;
        ;; NOTICE! The registers r8 and r9 are used as parameters carrying
-       ;; information from the decompressor (if the kernel was compressed). 
+       ;; information from the decompressor (if the kernel was compressed).
        ;; They should not be used in the code below until read.
-       
-       nop     
+
+       nop
        di
 
        ;; First setup the kseg_c mapping from where the kernel is linked
 
 #ifdef CONFIG_CRIS_LOW_MAP
        ; kseg mappings, temporary map of 0xc0->0x40
-       move.d    IO_FIELD (R_MMU_KBASE_HI, base_c, 4)          \
+       move.d    IO_FIELD (R_MMU_KBASE_HI, base_c, 4)          \
                | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb)        \
                | IO_FIELD (R_MMU_KBASE_HI, base_9, 9)          \
                | IO_FIELD (R_MMU_KBASE_HI, base_8, 8), $r0
        move.d  $r0, [R_MMU_KBASE_HI]
 
-       ; temporary map of 0x40->0x40 and 0x60->0x40 
-       move.d    IO_FIELD (R_MMU_KBASE_LO, base_6, 4)          \
+       ; temporary map of 0x40->0x40 and 0x60->0x40
+       move.d    IO_FIELD (R_MMU_KBASE_LO, base_6, 4)          \
                | IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0
        move.d  $r0, [R_MMU_KBASE_LO]
 
        ; mmu enable, segs e,c,b,a,6,5,4,0 segment mapped
-       move.d    IO_STATE (R_MMU_CONFIG, mmu_enable, enable)   \
+       move.d    IO_STATE (R_MMU_CONFIG, mmu_enable, enable)   \
                | IO_STATE (R_MMU_CONFIG, inv_excp, enable)     \
                | IO_STATE (R_MMU_CONFIG, acc_excp, enable)     \
                | IO_STATE (R_MMU_CONFIG, we_excp, enable)      \
        move.d  $r0, [R_MMU_CONFIG]
 #else
        ; kseg mappings
-       move.d    IO_FIELD (R_MMU_KBASE_HI, base_e, 8)          \
+       move.d    IO_FIELD (R_MMU_KBASE_HI, base_e, 8)          \
                | IO_FIELD (R_MMU_KBASE_HI, base_c, 4)          \
                | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb), $r0
        move.d  $r0, [R_MMU_KBASE_HI]
 
-       ; temporary map of 0x40->0x40 and 0x00->0x00 
+       ; temporary map of 0x40->0x40 and 0x00->0x00
        move.d    IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0
        move.d  $r0, [R_MMU_KBASE_LO]
 
        ; mmu enable, segs f,e,c,b,4,0 segment mapped
-       move.d    IO_STATE (R_MMU_CONFIG, mmu_enable, enable)   \
+       move.d    IO_STATE (R_MMU_CONFIG, mmu_enable, enable)   \
                | IO_STATE (R_MMU_CONFIG, inv_excp, enable)     \
                | IO_STATE (R_MMU_CONFIG, acc_excp, enable)     \
                | IO_STATE (R_MMU_CONFIG, we_excp, enable)      \
        ;;
        ;; In both cases, we start in un-cached mode, and need to jump into a
        ;; cached PC after we're done fiddling around with the segments.
-       ;; 
+       ;;
        ;; arch/etrax100/etrax100.ld sets some symbols that define the start
        ;; and end of each segment.
 
        ;; Check if we start from DRAM or FLASH by testing PC
-       
+
        move.d  $pc,$r0
        and.d   0x7fffffff,$r0  ; get rid of the non-cache bit
        cmp.d   0x10000,$r0     ; arbitrary... just something above this code
@@ -163,30 +161,28 @@ _inflash0:
        ;; after init.
        .section ".init.text", "ax"
 _inflash:
-#ifdef CONFIG_ETRAX_ETHERNET   
+#ifdef CONFIG_ETRAX_ETHERNET
        ;; Start MII clock to make sure it is running when tranceiver is reset
        move.d START_ETHERNET_CLOCK, $r0
        move.d $r0, [R_NETWORK_GEN_CONFIG]
 #endif
 
        ;; Set up waitstates etc according to kernel configuration.
-#ifndef CONFIG_SVINTO_SIM
        move.d   CONFIG_ETRAX_DEF_R_WAITSTATES, $r0
        move.d   $r0, [R_WAITSTATES]
 
        move.d   CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0
        move.d   $r0, [R_BUS_CONFIG]
-#endif
 
        ;; We need to initialze DRAM registers before we start using the DRAM
 
        cmp.d   RAM_INIT_MAGIC, $r8     ; Already initialized?
        beq     _dram_init_finished
        nop
-       
+
 #include "../lib/dram_init.S"
 
-_dram_init_finished:           
+_dram_init_finished:
        ;; Copy text+data to DRAM
        ;; This is fragile - the calculation of r4 as the image size depends
        ;; on that the labels below actually are the first and last positions
@@ -198,7 +194,7 @@ _dram_init_finished:
        ;; between the physical start of the flash and the flash-image start,
        ;; and when run with compression, the kernel is actually unpacked to
        ;; DRAM and we never get here in the first place :))
-       
+
        moveq   0, $r0                  ; source
        move.d  text_start, $r1         ; destination
        move.d  __vmlinux_end, $r2      ; end destination
@@ -229,10 +225,10 @@ _dram_init_finished:
        add.d   0xf0000000, $r4 ; add flash start in virtual memory (cached)
 #endif
        move.d  $r4, [romfs_start]
-1:     
+1:
        moveq   1, $r0
        move.d  $r0, [romfs_in_flash]
-               
+
        jump    _start_it       ; enter code, cached this time
 
 _inram:
@@ -241,7 +237,7 @@ _inram:
 
        moveq   0, $r0
        move.d  $r0, [romfs_length] ; default if there is no cramfs
-       
+
        ;; The kernel could have been unpacked to DRAM by the loader, but
        ;; the cramfs image could still be in the Flash directly after the
        ;; compressed kernel image. The loader passes the address of the
@@ -251,7 +247,7 @@ _inram:
        ;; (Notice that if this is not booted from the loader, r9 will be
        ;;  garbage but we do sanity checks on it, the chance that it points
        ;;  to a cramfs magic is small.. )
-       
+
        cmp.d   0x0ffffff8, $r9
        bhs     _no_romfs_in_flash      ; r9 points outside the flash area
        nop
@@ -274,7 +270,7 @@ _inram:
        jump    _start_it       ; enter code, cached this time
 
 _no_romfs_in_flash:
-       
+
        ;; Check if there is a cramfs (magic value).
        ;; Notice that we check for cramfs magic value - which is
        ;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does
@@ -286,8 +282,8 @@ _no_romfs_in_flash:
        bne     2f
        nop
 
-       ;; Ok. What is its size ? 
-       
+       ;; Ok. What is its size ?
+
        move.d  [$r0 + 4], $r2  ; cramfs_super.size (again, no need to swapwb)
 
        ;; We want to copy it to the end of the BSS
@@ -303,7 +299,7 @@ _no_romfs_in_flash:
 
        add.d   $r2, $r0
        add.d   $r2, $r1
-               
+
        ;; Go ahead. Make my loop.
 
        lsrq    1, $r2          ; size is in bytes, we copy words
@@ -314,14 +310,14 @@ _no_romfs_in_flash:
        bne     1b
        nop
 
-2:             
+2:
        ;; Dont worry that the BSS is tainted. It will be cleared later.
 
        moveq   0, $r0
        move.d  $r0, [romfs_in_flash]
 
        jump    _start_it       ; better skip the additional cramfs check below
-       
+
 _start_it:
 
        ;; Check if kernel command line is supplied
@@ -348,7 +344,7 @@ no_command_line:
        move.d  ibr_start,$r0   ; this symbol is set by the linker script 
        move    $r0,$ibr
        move.d  $r0,[etrax_irv] ; set the interrupt base register and pointer
-       
+
        ;; Clear BSS region, from _bss_start to _end
 
        move.d  __bss_start, $r0
@@ -357,7 +353,7 @@ no_command_line:
        cmp.d   $r1, $r0
        blo     1b
        nop
-       
+
 #ifdef CONFIG_BLK_DEV_ETRAXIDE
        ;; disable ATA before enabling it in genconfig below
        moveq   0,$r0
@@ -380,7 +376,7 @@ no_command_line:
 
 #ifdef CONFIG_JULIETTE
        ;; configure external DMA channel 0 before enabling it in genconfig
-       
+
        moveq   0,$r0
        move.d  $r0,[R_EXT_DMA_0_ADDR]
        ; cnt enable, word size, output, stop, size 0
@@ -395,7 +391,7 @@ no_command_line:
        move.d  $r0,[R_EXT_DMA_0_CMD]
 
        ;; reset dma4 and wait for completion
-       
+
        moveq   IO_STATE (R_DMA_CH4_CMD, cmd, reset),$r0
        move.b  $r0,[R_DMA_CH4_CMD]
 1:     move.b  [R_DMA_CH4_CMD],$r0
@@ -405,7 +401,7 @@ no_command_line:
        nop
 
        ;; reset dma5 and wait for completion
-       
+
        moveq   IO_STATE (R_DMA_CH5_CMD, cmd, reset),$r0
        move.b  $r0,[R_DMA_CH5_CMD]
 1:     move.b  [R_DMA_CH5_CMD],$r0
@@ -413,8 +409,8 @@ no_command_line:
        cmp.b   IO_STATE (R_DMA_CH5_CMD, cmd, reset),$r0
        beq     1b
        nop
-#endif 
-                       
+#endif
+
        ;; Etrax product HW genconfig setup
 
        moveq   0,$r0
@@ -468,7 +464,6 @@ no_command_line:
 
        move.d  $r0,[genconfig_shadow] ; init a shadow register of R_GEN_CONFIG
 
-#ifndef CONFIG_SVINTO_SIM
        move.d  $r0,[R_GEN_CONFIG]
 
 #if 0
@@ -486,7 +481,7 @@ no_command_line:
        beq     1b
        nop
 #endif
-       
+
        moveq   IO_STATE (R_DMA_CH8_CMD, cmd, reset),$r0
        move.b  $r0,[R_DMA_CH8_CMD]     ; reset (ser1 dma out)
        move.b  $r0,[R_DMA_CH9_CMD]     ; reset (ser1 dma in)
@@ -503,7 +498,7 @@ no_command_line:
 
        ;; setup port PA and PB default initial directions and data
        ;; including their shadow registers
-               
+
        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DIR,$r0
 #if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_PA7)
        or.b    IO_STATE (R_PORT_PA_DIR, dir7, output),$r0
@@ -520,7 +515,7 @@ no_command_line:
 #endif
        move.b  $r0,[port_pa_data_shadow]
        move.b  $r0,[R_PORT_PA_DATA]
-       
+
        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG,$r0
        move.b  $r0,[port_pb_config_shadow]
        move.b  $r0,[R_PORT_PB_CONFIG]
@@ -562,13 +557,13 @@ no_command_line:
 #endif
        move.d  $r0,[port_g_data_shadow]
        move.d  $r0,[R_PORT_G_DATA]
-       
+
        ;; setup the serial port 0 at 115200 baud for debug purposes
-       
+
        moveq     IO_STATE (R_SERIAL0_XOFF, tx_stop, enable)            \
                | IO_STATE (R_SERIAL0_XOFF, auto_xoff, disable)         \
                | IO_FIELD (R_SERIAL0_XOFF, xoff_char, 0),$r0
-       move.d  $r0,[R_SERIAL0_XOFF] 
+       move.d  $r0,[R_SERIAL0_XOFF]
 
        ; 115.2kbaud for both transmit and receive
        move.b    IO_STATE (R_SERIAL0_BAUD, tr_baud, c115k2Hz)          \
@@ -584,8 +579,8 @@ no_command_line:
                | IO_STATE (R_SERIAL0_REC_CTRL, rec_par, even)          \
                | IO_STATE (R_SERIAL0_REC_CTRL, rec_par_en, disable)    \
                | IO_STATE (R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit),$r0
-       move.b  $r0,[R_SERIAL0_REC_CTRL] 
-       
+       move.b  $r0,[R_SERIAL0_REC_CTRL]
+
        ; Set up and enable the serial0 transmitter.
        move.b    IO_FIELD (R_SERIAL0_TR_CTRL, txd, 0)                  \
                | IO_STATE (R_SERIAL0_TR_CTRL, tr_enable, enable)       \
@@ -598,11 +593,11 @@ no_command_line:
        move.b  $r0,[R_SERIAL0_TR_CTRL]
 
        ;; setup the serial port 1 at 115200 baud for debug purposes
-       
+
        moveq     IO_STATE (R_SERIAL1_XOFF, tx_stop, enable)            \
                | IO_STATE (R_SERIAL1_XOFF, auto_xoff, disable)         \
                | IO_FIELD (R_SERIAL1_XOFF, xoff_char, 0),$r0
-       move.d  $r0,[R_SERIAL1_XOFF] 
+       move.d  $r0,[R_SERIAL1_XOFF]
 
        ; 115.2kbaud for both transmit and receive
        move.b    IO_STATE (R_SERIAL1_BAUD, tr_baud, c115k2Hz)          \
@@ -618,8 +613,8 @@ no_command_line:
                | IO_STATE (R_SERIAL1_REC_CTRL, rec_par, even)          \
                | IO_STATE (R_SERIAL1_REC_CTRL, rec_par_en, disable)    \
                | IO_STATE (R_SERIAL1_REC_CTRL, rec_bitnr, rec_8bit),$r0
-       move.b  $r0,[R_SERIAL1_REC_CTRL] 
-       
+       move.b  $r0,[R_SERIAL1_REC_CTRL]
+
        ; Set up and enable the serial1 transmitter.
        move.b    IO_FIELD (R_SERIAL1_TR_CTRL, txd, 0)                  \
                | IO_STATE (R_SERIAL1_TR_CTRL, tr_enable, enable)       \
@@ -666,14 +661,14 @@ no_command_line:
                | IO_STATE (R_SERIAL2_TR_CTRL, tr_bitnr, tr_8bit),$r0
        move.b  $r0,[R_SERIAL2_TR_CTRL]
 #endif
-       
-#ifdef CONFIG_ETRAX_SERIAL_PORT3       
+
+#ifdef CONFIG_ETRAX_SERIAL_PORT3
        ;; setup the serial port 3 at 115200 baud for debug purposes
-       
+
        moveq     IO_STATE (R_SERIAL3_XOFF, tx_stop, enable)            \
                | IO_STATE (R_SERIAL3_XOFF, auto_xoff, disable)         \
                | IO_FIELD (R_SERIAL3_XOFF, xoff_char, 0),$r0
-       move.d  $r0,[R_SERIAL3_XOFF] 
+       move.d  $r0,[R_SERIAL3_XOFF]
 
        ; 115.2kbaud for both transmit and receive
        move.b    IO_STATE (R_SERIAL3_BAUD, tr_baud, c115k2Hz)          \
@@ -689,8 +684,8 @@ no_command_line:
                | IO_STATE (R_SERIAL3_REC_CTRL, rec_par, even)          \
                | IO_STATE (R_SERIAL3_REC_CTRL, rec_par_en, disable)    \
                | IO_STATE (R_SERIAL3_REC_CTRL, rec_bitnr, rec_8bit),$r0
-       move.b  $r0,[R_SERIAL3_REC_CTRL] 
-       
+       move.b  $r0,[R_SERIAL3_REC_CTRL]
+
        ; Set up and enable the serial3 transmitter.
        move.b    IO_FIELD (R_SERIAL3_TR_CTRL, txd, 0)                  \
                | IO_STATE (R_SERIAL3_TR_CTRL, tr_enable, enable)       \
@@ -702,13 +697,11 @@ no_command_line:
                | IO_STATE (R_SERIAL3_TR_CTRL, tr_bitnr, tr_8bit),$r0
        move.b  $r0,[R_SERIAL3_TR_CTRL]
 #endif
-       
-#endif /* CONFIG_SVINTO_SIM */
 
        jump    start_kernel    ; jump into the C-function start_kernel in init/main.c
-               
+
        .data
-etrax_irv:     
+etrax_irv:
        .dword  0
 romfs_start:
        .dword  0
@@ -716,13 +709,13 @@ romfs_length:
        .dword  0
 romfs_in_flash:
        .dword  0
-       
+
        ;; put some special pages at the beginning of the kernel aligned
        ;; to page boundaries - the kernel cannot start until after this
 
 #ifdef CONFIG_CRIS_LOW_MAP
 swapper_pg_dir = 0x60002000
-#else  
+#else
 swapper_pg_dir = 0xc0002000
 #endif
 
index ba0e5965d6e3ed2f901e48cf1c5ee2d52435d960..09cae80a834a341d11c5790d8b267b9cc742be35 100644 (file)
@@ -5,7 +5,7 @@
  *
  *      Authors: Bjorn Wesen (bjornw@axis.com)
  *
- *      This file contains the interrupt vectors and some 
+ *      This file contains the interrupt vectors and some
  *      helper functions
  *
  */
@@ -182,19 +182,14 @@ void do_multiple_IRQ(struct pt_regs* regs)
    setting the irq vector table.
 */
 
-void __init
-init_IRQ(void)
+void __init init_IRQ(void)
 {
        int i;
 
        /* clear all interrupt masks */
-
-#ifndef CONFIG_SVINTO_SIM
        *R_IRQ_MASK0_CLR = 0xffffffff;
        *R_IRQ_MASK1_CLR = 0xffffffff;
        *R_IRQ_MASK2_CLR = 0xffffffff;
-#endif
-
        *R_VECT_MASK_CLR = 0xffffffff;
 
         for (i = 0; i < 256; i++)
@@ -211,25 +206,20 @@ init_IRQ(void)
            executed by the associated break handler, rather than just a jump
            address. therefore we need to setup a default breakpoint handler
            for all breakpoints */
-
        for (i = 0; i < 16; i++)
                 set_break_vector(i, do_sigtrap);
-        
-       /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
 
+       /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
        set_int_vector(15, multiple_interrupt);
-       
-       /* 0 and 1 which are special breakpoint/NMI traps */
 
+       /* 0 and 1 which are special breakpoint/NMI traps */
        set_int_vector(0, hwbreakpoint);
        set_int_vector(1, IRQ1_interrupt);
 
        /* and irq 14 which is the mmu bus fault handler */
-
        set_int_vector(14, mmu_bus_fault);
 
        /* setup the system-call trap, which is reached by BREAK 13 */
-
        set_break_vector(13, system_call);
 
         /* setup a breakpoint handler for debugging used for both user and
index 753e9a03cf870565bb4ba0619a3b529e1b9a430d..02b783457be0a92a0e346f21675f0f06b59b4288 100644 (file)
@@ -56,14 +56,14 @@ void hard_reset_now (void)
         * code to know about it than the watchdog handler in entry.S and
         * this code, implementing hard reset through the watchdog.
         */
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_WATCHDOG)
        extern int cause_of_death;
 #endif
 
        printk("*** HARD RESET ***\n");
        local_irq_disable();
 
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_WATCHDOG)
        cause_of_death = 0xbedead;
 #else
        /* Since we dont plan to keep on resetting the watchdog,
index fce7c541d70de8331b47ccab308a6798b9491bb5..b5eb5cd2f60b1381b990d7ead6cba07d6c72f405 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <arch/svinto.h>
 #include <asm/types.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -34,7 +33,7 @@ unsigned long get_ns_in_jiffie(void)
 
        local_irq_save(flags);
        timer_count = *R_TIMER0_DATA;
-       presc_count = *R_TIM_PRESC_STATUS;  
+       presc_count = *R_TIM_PRESC_STATUS;
        /* presc_count might be wrapped */
        t1 = *R_TIMER0_DATA;
 
@@ -50,7 +49,7 @@ unsigned long get_ns_in_jiffie(void)
                presc_count =  PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;
        }
 
-       ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) + 
+       ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) +
             ( (presc_count) * (1000000000/PRESCALE_FREQ));
        return ns;
 }
@@ -80,7 +79,7 @@ static u32 cris_v10_gettimeoffset(void)
  * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit
  * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is
  * described in the table below:
- * 
+ *
  *   Watchdog    Value written:
  *   state:      To enable:  To key:      Operation:
  *   --------    ----------  -------      ----------
@@ -89,15 +88,15 @@ static u32 cris_v10_gettimeoffset(void)
  *   started         0       ~key         Stop watchdog
  *   started         1       ~key         Restart watchdog with key = ~key.
  *   started         X       new_key_val  Change key to new_key_val.
- * 
+ *
  * Note: '~' is the bitwise NOT operator.
- * 
+ *
  */
 
 /* right now, starting the watchdog is the same as resetting it */
 #define start_watchdog reset_watchdog
 
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#ifdef CONFIG_ETRAX_WATCHDOG
 static int watchdog_key = 0;  /* arbitrary number */
 #endif
 
@@ -107,10 +106,9 @@ static int watchdog_key = 0;  /* arbitrary number */
 
 #define WATCHDOG_MIN_FREE_PAGES 8
 
-void
-reset_watchdog(void)
+void reset_watchdog(void)
 {
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_WATCHDOG)
        /* only keep watchdog happy as long as we have memory left! */
        if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
                /* reset the watchdog with the inverse of the old key */
@@ -123,28 +121,23 @@ reset_watchdog(void)
 
 /* stop the watchdog - we still need the correct key */
 
-void 
-stop_watchdog(void)
+void stop_watchdog(void)
 {
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#ifdef CONFIG_ETRAX_WATCHDOG
        watchdog_key ^= 0x7; /* invert key, which is 3 bits */
        *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
                IO_STATE(R_WATCHDOG, enable, stop);
-#endif 
+#endif
 }
 
 
+extern void cris_do_profile(struct pt_regs *regs);
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "xtime_update()" routine every clocktick
  */
-
-//static unsigned short myjiff; /* used by our debug routine print_timestamp */
-
-extern void cris_do_profile(struct pt_regs *regs);
-
-static inline irqreturn_t
-timer_interrupt(int irq, void *dev_id)
+static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
        struct pt_regs *regs = get_irq_regs();
        /* acknowledge the timer irq */
@@ -160,44 +153,39 @@ timer_interrupt(int irq, void *dev_id)
                IO_STATE( R_TIMER_CTRL, tm0, run) |
                IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
 #else
-       *R_TIMER_CTRL = r_timer_ctrl_shadow | 
-               IO_STATE(R_TIMER_CTRL, i0, clr);
+       *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i0, clr);
 #endif
 
        /* reset watchdog otherwise it resets us! */
        reset_watchdog();
-       
+
        /* Update statistics. */
        update_process_times(user_mode(regs));
 
        /* call the real timer interrupt handler */
-
        xtime_update(1);
-       
+
         cris_do_profile(regs); /* Save profiling information */
         return IRQ_HANDLED;
 }
 
-/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain
- * it needs to be IRQF_DISABLED to make the jiffies update work properly
- */
+/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain */
 
 static struct irqaction irq2  = {
        .handler = timer_interrupt,
-       .flags = IRQF_SHARED | IRQF_DISABLED,
+       .flags = IRQF_SHARED,
        .name = "timer",
 };
 
-void __init
-time_init(void)
-{      
+void __init time_init(void)
+{
        arch_gettimeoffset = cris_v10_gettimeoffset;
 
-       /* probe for the RTC and read it if it exists 
-        * Before the RTC can be probed the loops_per_usec variable needs 
-        * to be initialized to make usleep work. A better value for 
-        * loops_per_usec is calculated by the kernel later once the 
-        * clock has started.  
+       /* probe for the RTC and read it if it exists
+        * Before the RTC can be probed the loops_per_usec variable needs
+        * to be initialized to make usleep work. A better value for
+        * loops_per_usec is calculated by the kernel later once the
+        * clock has started.
         */
        loops_per_usec = 50;
 
@@ -208,7 +196,7 @@ time_init(void)
         * Remember that linux/timex.h contains #defines that rely on the
         * timer settings below (hz and divide factor) !!!
         */
-       
+
 #ifdef USE_CASCADE_TIMERS
        *R_TIMER_CTRL =
                IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
@@ -219,8 +207,8 @@ time_init(void)
                IO_STATE( R_TIMER_CTRL, i0, nop) |
                IO_STATE( R_TIMER_CTRL, tm0, stop_ld) |
                IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
-       
-       *R_TIMER_CTRL = r_timer_ctrl_shadow = 
+
+       *R_TIMER_CTRL = r_timer_ctrl_shadow =
                IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
                IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
                IO_STATE( R_TIMER_CTRL, i1, nop) |
@@ -230,18 +218,18 @@ time_init(void)
                IO_STATE( R_TIMER_CTRL, tm0, run) |
                IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
 #else
-       *R_TIMER_CTRL = 
-               IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      | 
+       *R_TIMER_CTRL =
+               IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      |
                IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV)      |
-               IO_STATE(R_TIMER_CTRL, i1,        nop)      | 
+               IO_STATE(R_TIMER_CTRL, i1,        nop)      |
                IO_STATE(R_TIMER_CTRL, tm1,       stop_ld)  |
                IO_STATE(R_TIMER_CTRL, clksel1,   c19k2Hz)  |
                IO_STATE(R_TIMER_CTRL, i0,        nop)      |
                IO_STATE(R_TIMER_CTRL, tm0,       stop_ld)  |
                IO_STATE(R_TIMER_CTRL, clksel0,   flexible);
-       
+
        *R_TIMER_CTRL = r_timer_ctrl_shadow =
-               IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      | 
+               IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      |
                IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV)      |
                IO_STATE(R_TIMER_CTRL, i1,        nop)      |
                IO_STATE(R_TIMER_CTRL, tm1,       run)      |
@@ -253,16 +241,14 @@ time_init(void)
        *R_TIMER_PRESCALE = PRESCALE_VALUE;
 #endif
 
-       *R_IRQ_MASK0_SET =
-               IO_STATE(R_IRQ_MASK0_SET, timer0, set); /* unmask the timer irq */
-       
-       /* now actually register the timer irq handler that calls timer_interrupt() */
-       
+       /* unmask the timer irq */
+       *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer0, set);
+
+       /* now actually register the irq handler that calls timer_interrupt() */
        setup_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */
 
        /* enable watchdog if we should use one */
-
-#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_WATCHDOG)
        printk("Enabling watchdog...\n");
        start_watchdog();
 
@@ -275,9 +261,7 @@ time_init(void)
           driver or infrastructure support yet.  */
        asm ("setf m");
 
-       *R_IRQ_MASK0_SET =
-               IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set);
-       *R_VECT_MASK_SET =
-               IO_STATE(R_VECT_MASK_SET, nmi, set);
+       *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set);
+       *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, nmi, set);
 #endif
 }
index b9190ff7d0a4debd99f51399f4bedab39805626f..e541d3d8f9223997cc9825510f265c5fb929f96a 100644 (file)
@@ -5,9 +5,7 @@
  * Note: This file may not modify r9 because r9 is used to carry
  *       information from the decompresser to the kernel
  *
- * Copyright (C) 2000, 2001 Axis Communications AB
- *
- * Authors:  Mikael Starvik (starvik@axis.com)
+ * Copyright (C) 2000-2012 Axis Communications AB
  *
  */
 
 
 
        ;; WARNING! The registers r8 and r9 are used as parameters carrying
-       ;; information from the decompressor (if the kernel was compressed). 
+       ;; information from the decompressor (if the kernel was compressed).
        ;; They should not be used in the code below.
 
-#ifndef CONFIG_SVINTO_SIM      
        move.d   CONFIG_ETRAX_DEF_R_WAITSTATES, $r0
        move.d   $r0, [R_WAITSTATES]
 
        move.d   CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0
        move.d   $r0, [R_BUS_CONFIG]
-       
+
 #ifndef CONFIG_ETRAX_SDRAM
        move.d   CONFIG_ETRAX_DEF_R_DRAM_CONFIG, $r0
        move.d   $r0, [R_DRAM_CONFIG]
        ;; Samsung SDRAMs seem to require to be initialized twice to work properly.
        moveq    2, $r6 
 _sdram_init:
-       
+
        ; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization
-       
+
        ; Bank configuration
        move.d   CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, $r0
        move.d   $r0, [R_SDRAM_CONFIG]
 
-       ; Calculate value of mrs_data 
+       ; Calculate value of mrs_data
        ; CAS latency = 2 && bus_width = 32 => 0x40
        ; CAS latency = 3 && bus_width = 32 => 0x60
        ; CAS latency = 2 && bus_width = 16 => 0x20
@@ -56,22 +53,22 @@ _sdram_init:
        and.d    0x00ff0000, $r2
        bne      _set_timing
        lsrq     16, $r2
-       
+
        move.d   0x40, $r2       ; Assume 32 bits and CAS latency = 2
        move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1
        move.d   $r1, $r3
-       and.d    0x03, $r1       ; Get CAS latency
+       and.d    0x03, $r1       ; Get CAS latency
        and.d    0x1000, $r3     ; 50 or 100 MHz?
        beq      _speed_50
        nop
-_speed_100:            
+_speed_100:
        cmp.d    0x00, $r1      ; CAS latency = 2?
        beq      _bw_check
        nop
-       or.d     0x20, $r2      ; CAS latency = 3 
+       or.d     0x20, $r2      ; CAS latency = 3
        ba       _bw_check
        nop
-_speed_50:                     
+_speed_50:
        cmp.d    0x01, $r1      ; CAS latency = 2?
        beq      _bw_check
        nop
@@ -86,19 +83,19 @@ _bw_check:
        ; Set timing parameters. Starts master clock
 _set_timing:
        move.d   CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1
-       and.d    0x8000f9ff, $r1 ; Make sure mrs data and command is 0 
+       and.d    0x8000f9ff, $r1 ; Make sure mrs data and command is 0
        or.d     0x80000000, $r1        ; Make sure sdram enable bit is set
        move.d   $r1, $r5
        or.d     0x0000c000, $r1 ; ref = disable
        lslq     16, $r2                ; mrs data starts at bit 16
-       or.d     $r2, $r1 
-       move.d   $r1, [R_SDRAM_TIMING]  
-               
+       or.d     $r2, $r1
+       move.d   $r1, [R_SDRAM_TIMING]
+
        ; Wait 200us
        move.d   10000, $r2
 1:     bne      1b
        subq     1, $r2
-       
+
        ; Issue initialization command sequence
        move.d   _sdram_commands_start, $r2
        and.d    0x000fffff, $r2 ; Make sure commands are read from flash
@@ -144,7 +141,6 @@ _sdram_commands_start:
        .byte   2       ; refresh
        .byte   0       ; nop
        .byte   1       ; mrs
-       .byte   0       ; nop 
-_sdram_commands_end:           
-#endif
+       .byte   0       ; nop
+_sdram_commands_end:
 #endif
index 1b6ad6247204c0b9d09f63f7e4731aaf70cb83cd..28dd77144e8fe8e24a0ac94cd309b5ac1587aac4 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/mtd/mtdram.h>
 #include <linux/mtd/partitions.h>
 
-#include <linux/cramfs_fs.h>
-
 #include <asm/axisflashmap.h>
 #include <asm/mmu.h>
 
index 0b86deedacb97b9a0e919b79d484a35f43b456cc..74f9fe80940c73cd2d66bf9a8e9d5d23c4e5ab38 100644 (file)
@@ -978,7 +978,7 @@ static int __init gpio_init(void)
        CRIS_LED_DISK_WRITE(0);
 
        int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt,
-               IRQF_SHARED | IRQF_DISABLED, "gpio", &alarmlist);
+               IRQF_SHARED, "gpio", &alarmlist);
        if (res2) {
                printk(KERN_ERR "err: irq for gpio\n");
                return res2;
index a2ac0917f1a615989243bd3c1d0dc091c7f2d552..9e54273af0ca81dd4d95d462cdf869bd1d21e0f4 100644 (file)
@@ -964,11 +964,11 @@ gpio_init(void)
         * in some tests.
         */
        if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
-                       IRQF_SHARED | IRQF_DISABLED, "gpio poll", &alarmlist))
+                       IRQF_SHARED, "gpio poll", &alarmlist))
                printk(KERN_ERR "timer0 irq for gpio\n");
 
        if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt,
-                       IRQF_SHARED | IRQF_DISABLED, "gpio PA", &alarmlist))
+                       IRQF_SHARED, "gpio PA", &alarmlist))
                printk(KERN_ERR "PA irq for gpio\n");
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
index 219f704e3221b9b6998cd12055fc51fb607ad26c..bbb806b68838e074660c830931955ff355502c7e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
+#include <linux/wait.h>
 
 #include <asm/io.h>
 #include <dma.h>
@@ -1144,7 +1145,8 @@ static ssize_t sync_serial_read(struct file * file, char * buf,
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
 
-               interruptible_sleep_on(&port->in_wait_q);
+               wait_event_interruptible(port->in_wait_q,
+                                        !(start == end && !port->full));
                if (signal_pending(current))
                        return -EINTR;
 
index faa644111feb7f4acb1eb87929177fdc3cdc3dc6..2f19ac6217aafd2754d7f423b5441d988aacbae7 100644 (file)
@@ -424,7 +424,7 @@ nmi_interrupt:
        bpl     1f
        nop
        jsr     handle_watchdog_bite    ; In time.c.
-        move.d $sp, $r10               ; Pointer to registers
+       move.d  $sp, $r10               ; Pointer to registers
 1:     btstq   REG_BIT(intr_vect, r_nmi, ext), $r0
        bpl     1f
        nop
@@ -452,7 +452,7 @@ spurious_interrupt:
        nop
 
        ;; This handles the case when multiple interrupts arrive at the same
-       ;; time. Jump to the first set interrupt bit in a priotiry fashion. The
+       ;; time. Jump to the first set interrupt bit in a priority fashion. The
        ;; hardware will call the unserved interrupts after the handler
        ;; finishes.
        .type   multiple_interrupt, @function
@@ -885,13 +885,29 @@ sys_call_table:
        .long sys_preadv
        .long sys_pwritev
        .long sys_setns                 /* 335 */
-
-        /*
-         * NOTE!! This doesn't have to be exact - we just have
-         * to make sure we have _enough_ of the "sys_ni_syscall"
-         * entries. Don't panic if you notice that this hasn't
-         * been shrunk every time we add a new system call.
-         */
+       .long sys_name_to_handle_at
+       .long sys_open_by_handle_at
+       .long sys_rt_tgsigqueueinfo
+       .long sys_perf_event_open
+       .long sys_recvmmsg              /* 340 */
+       .long sys_accept4
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
+       .long sys_clock_adjtime         /* 345 */
+       .long sys_syncfs
+       .long sys_sendmmsg
+       .long sys_process_vm_readv
+       .long sys_process_vm_writev
+       .long sys_kcmp                  /* 350 */
+       .long sys_finit_module
+
+       /*
+        * NOTE!! This doesn't have to be exact - we just have
+        * to make sure we have _enough_ of the "sys_ni_syscall"
+        * entries. Don't panic if you notice that this hasn't
+        * been shrunk every time we add a new system call.
+        */
 
        .rept NR_syscalls - (.-sys_call_table) / 4
                .long sys_ni_syscall
index f6644535b17e199637f810b8fcbea2fcef548b0c..b130c2c5fdd892d389debe80cd0297bb88bae32f 100644 (file)
@@ -786,7 +786,7 @@ int fast_timer_init(void)
     proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops);
 #endif /* PROC_FS */
                if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt,
-                               IRQF_SHARED | IRQF_DISABLED,
+                               IRQF_SHARED,
                                "fast timer int", &fast_timer_list))
                        printk(KERN_ERR "err: fasttimer irq\n");
     fast_timer_is_init = 1;
index 5ebe6e841820ec45a5a653d66993b7b2b5952bef..25437ae2812838ccf0d5e378563588e1de9096a5 100644 (file)
@@ -331,11 +331,11 @@ extern void do_IRQ(int irq, struct pt_regs * regs);
 void
 crisv32_do_IRQ(int irq, int block, struct pt_regs* regs)
 {
-       /* Interrupts that may not be moved to another CPU and
-         * are IRQF_DISABLED may skip blocking. This is currently
-         * only valid for the timer IRQ and the IPI and is used
-         * for the timer interrupt to avoid watchdog starvation.
-         */
+       /* Interrupts that may not be moved to another CPU may
+        * skip blocking. This is currently only valid for the
+        * timer IRQ and the IPI and is used for the timer
+        * interrupt to avoid watchdog starvation.
+        */
        if (!block) {
                do_IRQ(irq, regs);
                return;
index fe8e6039db2a04aa3c133385322fe6573b7b2b11..0698582467ca773c3cf704690fc9b105610b4ab0 100644 (file)
@@ -64,7 +64,7 @@ static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id);
 static int send_ipi(int vector, int wait, cpumask_t cpu_mask);
 static struct irqaction irq_ipi  = {
        .handler = crisv32_ipi_interrupt,
-       .flags = IRQF_DISABLED,
+       .flags = 0,
        .name = "ipi",
 };
 
index 8c4b45efd7b6712f8dc13da94c55bc8ee51ca369..ee66866538f891a7ff574efd4b82d836b4b3f894 100644 (file)
@@ -216,12 +216,10 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
         return IRQ_HANDLED;
 }
 
-/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain.
- * It needs to be IRQF_DISABLED to make the jiffies update work properly.
- */
+/* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */
 static struct irqaction irq_timer = {
        .handler = timer_interrupt,
-       .flags = IRQF_SHARED | IRQF_DISABLED,
+       .flags = IRQF_SHARED,
        .name = "timer"
 };
 
index 15f5c9de26399893e78d8f82e7783aa1cb8b0757..ab5c421a4de86fb3af3614e01ec5bd8ebdb5af8d 100644 (file)
@@ -256,11 +256,11 @@ static void crisv32_arbiter_init(void)
        crisv32_arbiter_config(1, EXT_REGION, 0);
 
        if (request_irq(MEMARB_FOO_INTR_VECT, crisv32_foo_arbiter_irq,
-                       IRQF_DISABLED, "arbiter", NULL))
+                       0, "arbiter", NULL))
                printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
 
        if (request_irq(MEMARB_BAR_INTR_VECT, crisv32_bar_arbiter_irq,
-                       IRQF_DISABLED, "arbiter", NULL))
+                       0, "arbiter", NULL))
                printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
 
 #ifndef CONFIG_ETRAX_KGDB
index 3f8ebb5c14771300e49106f78dc58acaba67d037..c97f4d8120f9e43747b120fd8fc8ef814c0060ed 100644 (file)
@@ -184,7 +184,7 @@ static void crisv32_arbiter_init(void)
        crisv32_arbiter_config(EXT_REGION, 0);
        crisv32_arbiter_config(INT_REGION, 0);
 
-       if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED,
+       if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, 0,
                        "arbiter", NULL))
                printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
 
index 6f7b3e61260bea02079919f2ea2bf32131ab176a..655b511fecf37ff3e9ada767f8a8b06ba488377b 100644 (file)
@@ -50,7 +50,6 @@
 
        nop
        di
-#ifndef CONFIG_SVINTO_SIM
        ;; setup port PA and PB default initial directions and data
        ;; (so we can flash LEDs, and so that DTR and others are set)
 
@@ -67,7 +66,6 @@
        ;; We need to setup the bus registers before we start using the DRAM
 #include "../../lib/dram_init.S"
 
-#endif
        ;; Setup the stack to a suitably high address.
        ;; We assume 8 MB is the minimum DRAM in an eLinux
        ;; product and put the sp at the top for now.
index f627ad0b8a3d6a59a5f27ae660af4afee84a819b..4a724172877f81cd88b2c25dbdcabce144455d0a 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _ASM_ARCH_CRIS_IO_H
 #define _ASM_ARCH_CRIS_IO_H
 
-#include <arch/svinto.h>
-
 /* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
 
 extern unsigned long gen_config_ii_shadow;
@@ -34,7 +32,7 @@ extern volatile unsigned long *port_csp4_addr;
 
 /* The LED's on various Etrax-based products are set differently. */
 
-#if defined(CONFIG_ETRAX_NO_LEDS) || defined(CONFIG_SVINTO_SIM)
+#if defined(CONFIG_ETRAX_NO_LEDS)
 #undef CONFIG_ETRAX_PA_LEDS
 #undef CONFIG_ETRAX_PB_LEDS
 #undef CONFIG_ETRAX_CSP0_LEDS
@@ -171,29 +169,4 @@ extern volatile unsigned long *port_csp4_addr;
 #define SOFT_SHUTDOWN()
 #endif
 
-/* Console I/O for simulated etrax100.  Use #ifdef so erroneous
-   use will be evident. */
-#ifdef CONFIG_SVINTO_SIM
-  /* Let's use the ucsim interface since it lets us do write(2, ...) */
-#define SIMCOUT(s,len)                                                 \
-  asm ("moveq 4,$r9    \n\t"                                           \
-       "moveq 2,$r10   \n\t"                                           \
-       "move.d %0,$r11 \n\t"                                           \
-       "move.d %1,$r12 \n\t"                                           \
-       "push $irp      \n\t"                                           \
-       "move 0f,$irp   \n\t"                                           \
-       "jump -6809     \n"                                             \
-       "0:             \n\t"                                           \
-       "pop $irp"                                                      \
-       : : "rm" (s), "rm" (len) : "r9","r10","r11","r12","memory")
-#define TRACE_ON() __extension__ \
- ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \
-                              (255)); _Foofoo; })
-
-#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0)
-#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0)
-#define CRIS_CYCLES() __extension__ \
- ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;})
-#endif /* ! defined CONFIG_SVINTO_SIM */
-
 #endif
index ca2675ae08ed95d1c3de56ad0a507af390b348e3..6aecb835037d3cf2c02da7c637f7653ce43cd4a5 100644 (file)
@@ -141,9 +141,9 @@ __asm__ ( \
  * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
  * it here, we would not get the multiple_irq at all.
  *
- * The non-blocking here is based on the knowledge that the timer interrupt is 
- * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
- * be an sti() before the timer irq handler is run to acknowledge the interrupt.
+ * The non-blocking here is based on the knowledge that the timer interrupt runs
+ * with interrupts disabled, and therefore there will not be an sti() before the
+ * timer irq handler is run to acknowledge the interrupt.
  */
 
 #define BUILD_TIMER_IRQ(nr,mask) \
index fe3cdd22bed4590315268c156e28076c26cff238..0c1b4d3a34e749b222c1d0ec0af3a56a4b80b952 100644 (file)
@@ -102,9 +102,9 @@ __asm__ (                           \
  * multiple_irq handler is run and it prioritizes the timer interrupt. However
  * if we had BLOCK'edit here, we would not get the multiple_irq at all.
  *
- * The non-blocking here is based on the knowledge that the timer interrupt is
- * registered as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
- * be an sti() before the timer irq handler is run to acknowledge the interrupt.
+ * The non-blocking here is based on the knowledge that the timer interrupt runs
+ * with interrupts disabled, and therefore there will not be an sti() before the
+ * timer irq handler is run to acknowledge the interrupt.
  */
 #define BUILD_TIMER_IRQ(nr, mask)      \
 void IRQ_NAME(nr);                     \
index 0ff3f6889842b7bb0922ec2b777595719556f004..5cc7d1991e482bf0e3eef50e598877595c15b69a 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls 336
+#define NR_syscalls 360
 
 #include <arch/unistd.h>
 
index 48842896f6c2fbe418a42260dc33486b54ff71a8..f3287face443b4094a35231c972912970178e1ec 100644 (file)
 #define __NR_preadv            333
 #define __NR_pwritev           334
 #define __NR_setns             335
+#define __NR_name_to_handle_at 336
+#define __NR_open_by_handle_at 337
+#define __NR_rt_tgsigqueueinfo 338
+#define __NR_perf_event_open   339
+#define __NR_recvmmsg          340
+#define __NR_accept4           341
+#define __NR_fanotify_init     342
+#define __NR_fanotify_mark     343
+#define __NR_prlimit64         344
+#define __NR_clock_adjtime     345
+#define __NR_syncfs            346
+#define __NR_sendmmsg          347
+#define __NR_process_vm_readv  348
+#define __NR_process_vm_writev 349
+#define __NR_kcmp              350
+#define __NR_finit_module      351
 
 #endif /* _UAPI_ASM_CRIS_UNISTD_H_ */
index d36836dbbc0722758f9e116537c5e413a6e4871a..dd0be5de55d5b6ea27a2410b984e3bba0e5b9e72 100644 (file)
@@ -40,9 +40,6 @@
 
 /* called by the assembler IRQ entry functions defined in irq.h
  * to dispatch the interrupts to registered handlers
- * interrupts are disabled upon entry - depending on if the
- * interrupt was registered with IRQF_DISABLED or not, interrupts
- * are re-enabled or not.
  */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
index 8d581ab06c5df6bc1e4d61da48324f65212c7992..79b9bcdfe4982ab433a89a5851b1551d47d7be7e 100644 (file)
@@ -26,6 +26,8 @@ config MICROBLAZE
        select GENERIC_CPU_DEVICES
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
+       select COMMON_CLK
+       select GENERIC_SCHED_CLOCK
        select GENERIC_IDLE_POLL_SETUP
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS3
index 40350a3c24e907f01f3c193018abb6a34ee35541..a69eaf2ab1301466c662e27f37837c86d8193d61 100644 (file)
@@ -1,3 +1,5 @@
+KBUILD_DEFCONFIG := mmu_defconfig
+
 ifeq ($(CONFIG_MMU),y)
 UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\"
 else
index 7d6831ac8a46eec66c4f1fc00ac28aa48000ed64..3337417fcdca3b6794d0e46dd65d150a472c00d6 100644 (file)
@@ -91,15 +91,18 @@ extern struct cpuinfo cpuinfo;
 
 /* fwd declarations of the various CPUinfo populators */
 void setup_cpuinfo(void);
+void setup_cpuinfo_clk(void);
 
 void set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu);
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
 
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
-       const __be32 *val;
-       return (val = of_get_property(cpu, n, NULL)) ?
-                                                       be32_to_cpup(val) : 0;
+       u32 val = 0;
+
+       of_property_read_u32(cpu, n, &val);
+
+       return val;
 }
 
 #endif /* _ASM_MICROBLAZE_CPUINFO_H */
index 2565cb94f32f0857bb4d925527c2ee9c77c7ea89..a2cea72060777a5df8fd1065f80e627d56a29787 100644 (file)
@@ -342,4 +342,12 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 #define iowrite32_rep(p, src, count) \
        outsl((unsigned long) (p), (src), (count))
 
+#define readb_relaxed  readb
+#define readw_relaxed  readw
+#define readl_relaxed  readl
+
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
+
 #endif /* _ASM_MICROBLAZE_IO_H */
index c07ed5d2a82034f11cbadc6e836d4e31761d380f..1b281d3ea734418a0f39d12625e8ac1a749a6b1c 100644 (file)
@@ -16,7 +16,6 @@
 # ifndef __ASSEMBLY__
 extern char _ssbss[], _esbss[];
 extern unsigned long __ivt_start[], __ivt_end[];
-extern char _etext[], _stext[];
 
 extern u32 _fdt_start[], _fdt_end[];
 
index 6d7d7f4aaae8679846945e11c5ab0872c5cfdfb5..1aac99f87df15841b93241f6bfad81733250b183 100644 (file)
@@ -1,6 +1,8 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += types.h
+
 header-y += auxvec.h
 header-y += bitsperlong.h
 header-y += byteorder.h
@@ -31,5 +33,4 @@ header-y += statfs.h
 header-y += swab.h
 header-y += termbits.h
 header-y += termios.h
-header-y += types.h
 header-y += unistd.h
diff --git a/arch/microblaze/include/uapi/asm/types.h b/arch/microblaze/include/uapi/asm/types.h
deleted file mode 100644 (file)
index b9e79bc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/types.h>
index ee46894154101cad22e70e4ccbf91b44172cee2d..93c26cf50de525db0a5bee58baa6b84bf92a53c3 100644 (file)
@@ -112,7 +112,4 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK);
 
        CI(fpga_family_code, TARGET_FAMILY);
-
-       /* take timebase-frequency from DTS */
-       ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
 }
index 592bb2e838c4f5e0d0d25685d59373a73b7a579a..4854285b26e77876121de423b94db2059adcaa1a 100644 (file)
@@ -113,8 +113,6 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->num_rd_brk = fcpu(cpu, "xlnx,number-of-rd-addr-brk");
        ci->num_wr_brk = fcpu(cpu, "xlnx,number-of-wr-addr-brk");
 
-       ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
-
        ci->pvr_user1 = fcpu(cpu, "xlnx,pvr-user1");
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
index c9203b1007aad889a1cb742448b27397ccd83be9..234acad79b9ec482ac8b240f84332ba8f30e2b83 100644 (file)
@@ -8,6 +8,7 @@
  * for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <asm/cpuinfo.h>
 #include <asm/pvr.h>
@@ -39,6 +40,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
        {"8.30.a", 0x17},
        {"8.40.a", 0x18},
        {"8.40.b", 0x19},
+       {"8.50.a", 0x1a},
        {"9.0", 0x1b},
        {"9.1", 0x1d},
        {NULL, 0},
@@ -68,11 +70,10 @@ const struct family_string_key family_string_lookup[] = {
 };
 
 struct cpuinfo cpuinfo;
+static struct device_node *cpu;
 
 void __init setup_cpuinfo(void)
 {
-       struct device_node *cpu = NULL;
-
        cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu");
        if (!cpu)
                pr_err("You don't have cpu!!!\n");
@@ -102,3 +103,22 @@ void __init setup_cpuinfo(void)
                pr_warn("%s: Stream instructions enabled"
                        " - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 }
+
+void __init setup_cpuinfo_clk(void)
+{
+       struct clk *clk;
+
+       clk = of_clk_get(cpu, 0);
+       if (IS_ERR(clk)) {
+               pr_err("ERROR: CPU CCF input clock not found\n");
+               /* take timebase-frequency from DTS */
+               cpuinfo.cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+       } else {
+               cpuinfo.cpu_clock_freq = clk_get_rate(clk);
+       }
+
+       if (!cpuinfo.cpu_clock_freq) {
+               pr_err("ERROR: CPU clock frequency not setup\n");
+               BUG();
+       }
+}
index 817b7eec95b6de981edb751b8d13bd7cb657abd8..b7fb0438458ca8960bd0a730ec9c0da520112136 100644 (file)
@@ -64,6 +64,10 @@ real_start:
 #endif
 
        mts     rmsr, r0
+/* Disable stack protection from bootloader */
+       mts     rslr, r0
+       addi    r8, r0, 0xFFFFFFF
+       mts     rshr, r8
 /*
  * According to Xilinx, msrclr instruction behaves like 'mfs rX,rpc'
  * if the msrclr instruction is not enabled. We use this to detect
index fc6b89f4dd31d2fbd73227535457f395a825b00f..0b11a4469debae739005dcfccd5c92f82da5c5ea 100644 (file)
                or      r3, r0, NUM_TO_REG (regnum);
 
        /* Shift right instruction depending on available configuration */
-       #if CONFIG_XILINX_MICROBLAZE0_USE_BARREL > 0
-       #define BSRLI(rD, rA, imm)      \
-               bsrli rD, rA, imm
-       #else
-       #define BSRLI(rD, rA, imm) BSRLI ## imm (rD, rA)
+       #if CONFIG_XILINX_MICROBLAZE0_USE_BARREL == 0
        /* Only the used shift constants defined here - add more if needed */
        #define BSRLI2(rD, rA)                          \
                srl rD, rA;             /* << 1 */      \
                srl rD, rD;             /* << 2 */
+       #define BSRLI4(rD, rA)          \
+               BSRLI2(rD, rA);         \
+               BSRLI2(rD, rD)
        #define BSRLI10(rD, rA)                         \
                srl rD, rA;             /* << 1 */      \
                srl rD, rD;             /* << 2 */      \
        #define BSRLI20(rD, rA)         \
                BSRLI10(rD, rA);        \
                BSRLI10(rD, rD)
+
+       .macro  bsrli, rD, rA, IMM
+       .if (\IMM) == 2
+               BSRLI2(\rD, \rA)
+       .elseif (\IMM) == 10
+               BSRLI10(\rD, \rA)
+       .elseif (\IMM) == 12
+               BSRLI2(\rD, \rA)
+               BSRLI10(\rD, \rD)
+       .elseif (\IMM) == 14
+               BSRLI4(\rD, \rA)
+               BSRLI10(\rD, \rD)
+       .elseif (\IMM) == 20
+               BSRLI20(\rD, \rA)
+       .elseif (\IMM) == 24
+               BSRLI4(\rD, \rA)
+               BSRLI20(\rD, \rD)
+       .elseif (\IMM) == 28
+               BSRLI4(\rD, \rA)
+               BSRLI4(\rD, \rD)
+               BSRLI20(\rD, \rD)
+       .else
+       .error "BSRLI shift macros \IMM"
+       .endif
+       .endm
        #endif
+
 #endif /* CONFIG_MMU */
 
 .extern other_exception_handler /* Defined in exception.c */
@@ -604,7 +629,7 @@ ex_handler_done:
        ex4:
                tophys(r4,r4)
                /* Create L1 (pgdir/pmd) address */
-               BSRLI(r5,r3, PGDIR_SHIFT - 2)
+               bsrli   r5, r3, PGDIR_SHIFT - 2
                andi    r5, r5, PAGE_SIZE - 4
 /* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
                or      r4, r4, r5
@@ -613,7 +638,7 @@ ex_handler_done:
                beqi    r5, ex2                 /* Bail if no table */
 
                tophys(r5,r5)
-               BSRLI(r6,r3,PTE_SHIFT) /* Compute PTE address */
+               bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
                andi    r6, r6, PAGE_SIZE - 4
                or      r5, r5, r6
                lwi     r4, r5, 0               /* Get Linux PTE */
@@ -705,7 +730,7 @@ ex_handler_done:
        ex6:
                tophys(r4,r4)
                /* Create L1 (pgdir/pmd) address */
-               BSRLI(r5,r3, PGDIR_SHIFT - 2)
+               bsrli   r5, r3, PGDIR_SHIFT - 2
                andi    r5, r5, PAGE_SIZE - 4
 /* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
                or      r4, r4, r5
@@ -714,7 +739,7 @@ ex_handler_done:
                beqi    r5, ex7                 /* Bail if no table */
 
                tophys(r5,r5)
-               BSRLI(r6,r3,PTE_SHIFT) /* Compute PTE address */
+               bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
                andi    r6, r6, PAGE_SIZE - 4
                or      r5, r5, r6
                lwi     r4, r5, 0               /* Get Linux PTE */
@@ -776,7 +801,7 @@ ex_handler_done:
        ex9:
                tophys(r4,r4)
                /* Create L1 (pgdir/pmd) address */
-               BSRLI(r5,r3, PGDIR_SHIFT - 2)
+               bsrli   r5, r3, PGDIR_SHIFT - 2
                andi    r5, r5, PAGE_SIZE - 4
 /* Assume pgdir aligned on 4K boundary, no need for "andi r4,r4,0xfffff003" */
                or      r4, r4, r5
@@ -785,7 +810,7 @@ ex_handler_done:
                beqi    r5, ex10                /* Bail if no table */
 
                tophys(r5,r5)
-               BSRLI(r6,r3,PTE_SHIFT) /* Compute PTE address */
+               bsrli   r6, r3, PTE_SHIFT /* Compute PTE address */
                andi    r6, r6, PAGE_SIZE - 4
                or      r5, r5, r6
                lwi     r4, r5, 0               /* Get Linux PTE */
@@ -922,7 +947,7 @@ ex_handler_done:
 .ent _unaligned_data_exception
 _unaligned_data_exception:
        andi    r8, r3, 0x3E0;  /* Mask and extract the register operand */
-       BSRLI(r8,r8,2);         /* r8 >> 2 = register operand * 8 */
+       bsrli   r8, r8, 2;              /* r8 >> 2 = register operand * 8 */
        andi    r6, r3, 0x400;  /* Extract ESR[S] */
        bneid   r6, ex_sw_vm;
        andi    r6, r3, 0x800;  /* Extract ESR[W] - delay slot */
index 8de8ebc309f15b0ca080cdf6f7c93e54fd168d74..67cc4b282cc127fb48f2847d601adebab5aaf9e1 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/string.h>
 #include <linux/seq_file.h>
@@ -136,7 +137,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        lockdep_init();
 
 /* initialize device tree for usage in early_printk */
-       early_init_devtree((void *)_fdt_start);
+       early_init_devtree(_fdt_start);
 
 #ifdef CONFIG_EARLY_PRINTK
        setup_early_printk(NULL);
@@ -152,8 +153,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        if (fdt)
                pr_info("FDT at 0x%08x\n", fdt);
        else
-               pr_info("Compiled-in FDT at 0x%08x\n",
-                                       (unsigned int)_fdt_start);
+               pr_info("Compiled-in FDT at %p\n", _fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
        pr_info("Found romfs @ 0x%08x (0x%08x)\n",
@@ -175,7 +175,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
 #else
        if (!msr) {
                pr_info("!!!Your kernel not setup MSR instruction but ");
-               pr_cont"CPU have it %x\n", msr);
+               pr_cont("CPU have it %x\n", msr);
        }
 #endif
 
@@ -196,6 +196,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
 
 void __init time_init(void)
 {
+       of_clk_init(NULL);
+       setup_cpuinfo_clk();
        clocksource_of_init();
 }
 
index 3e39b1082fdf8433a030e851dfe37f2b63f8b766..fb0c61443f196ebbe7776e2d88108280bbc80025 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/sched_clock.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <asm/cpuinfo.h>
-#include <linux/cnt32_to_63.h>
 
 static void __iomem *timer_baseaddr;
 
@@ -167,10 +167,15 @@ static __init void xilinx_clockevent_init(void)
        clockevents_register_device(&clockevent_xilinx_timer);
 }
 
+static u64 xilinx_clock_read(void)
+{
+       return in_be32(timer_baseaddr + TCR1);
+}
+
 static cycle_t xilinx_read(struct clocksource *cs)
 {
        /* reading actual value of timer 1 */
-       return (cycle_t) (in_be32(timer_baseaddr + TCR1));
+       return (cycle_t)xilinx_clock_read();
 }
 
 static struct timecounter xilinx_tc = {
@@ -222,17 +227,17 @@ static int __init xilinx_clocksource_init(void)
        return 0;
 }
 
-/*
- * We have to protect accesses before timer initialization
- * and return 0 for sched_clock function below.
- */
-static int timer_initialized;
-
 static void __init xilinx_timer_init(struct device_node *timer)
 {
+       struct clk *clk;
+       static int initialized;
        u32 irq;
        u32 timer_num = 1;
-       int ret;
+
+       if (initialized)
+               return;
+
+       initialized = 1;
 
        timer_baseaddr = of_iomap(timer, 0);
        if (!timer_baseaddr) {
@@ -250,10 +255,20 @@ static void __init xilinx_timer_init(struct device_node *timer)
 
        pr_info("%s: irq=%d\n", timer->full_name, irq);
 
-       /* If there is clock-frequency property than use it */
-       ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq);
-       if (ret < 0)
+       clk = of_clk_get(timer, 0);
+       if (IS_ERR(clk)) {
+               pr_err("ERROR: timer CCF input clock not found\n");
+               /* If there is clock-frequency property than use it */
+               of_property_read_u32(timer, "clock-frequency",
+                                   &timer_clock_freq);
+       } else {
+               timer_clock_freq = clk_get_rate(clk);
+       }
+
+       if (!timer_clock_freq) {
+               pr_err("ERROR: Using CPU clock frequency\n");
                timer_clock_freq = cpuinfo.cpu_clock_freq;
+       }
 
        freq_div_hz = timer_clock_freq / HZ;
 
@@ -263,18 +278,8 @@ static void __init xilinx_timer_init(struct device_node *timer)
 #endif
        xilinx_clocksource_init();
        xilinx_clockevent_init();
-       timer_initialized = 1;
-}
 
-unsigned long long notrace sched_clock(void)
-{
-       if (timer_initialized) {
-               struct clocksource *cs = &clocksource_microblaze;
-
-               cycle_t cyc = cnt32_to_63(cs->read(NULL)) & LLONG_MAX;
-               return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
-       }
-       return 0;
+       sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);
 }
 
 CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",
index 936d01a689d74157f3a63e53eff1de725fa67f9d..be9488d697347c330f9b226d1a5a5c9ba2d97714 100644 (file)
@@ -51,6 +51,7 @@ SECTIONS {
        . = ALIGN(16);
        RODATA
        EXCEPTION_TABLE(16)
+       NOTES
 
        /*
         * sdata2 section can go anywhere, but must be word aligned
index 1695b6ab503d8e1f2763f89e5696bbb9019abfaf..25493a0b174cc3cbff25bfce1dfe02e6992c0b00 100644 (file)
@@ -140,6 +140,7 @@ config PPC
        select OLD_SIGACTION if PPC32
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_IRQ_EXIT_ON_IRQ_STACK
+       select ARCH_USE_CMPXCHG_LOCKREF if PPC64
 
 config GENERIC_CSUM
        def_bool CPU_LITTLE_ENDIAN
@@ -214,9 +215,6 @@ config DEFAULT_UIMAGE
          Used to allow a board to specify it wants a uImage built by default
        default n
 
-config REDBOOT
-       bool
-
 config ARCH_HIBERNATION_POSSIBLE
        bool
        default y
@@ -384,6 +382,12 @@ config ARCH_HAS_WALK_MEMORY
 config ARCH_ENABLE_MEMORY_HOTREMOVE
        def_bool y
 
+config PPC64_SUPPORTS_MEMORY_FAILURE
+       bool "Add support for memory hwpoison"
+       depends on PPC_BOOK3S_64
+       default "y" if PPC_POWERNV
+       select ARCH_SUPPORTS_MEMORY_FAILURE
+
 config KEXEC
        bool "kexec system call"
        depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
@@ -404,8 +408,7 @@ config KEXEC
 config CRASH_DUMP
        bool "Build a kdump crash kernel"
        depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
-       select RELOCATABLE if PPC64 || 44x
-       select DYNAMIC_MEMSTART if FSL_BOOKE
+       select RELOCATABLE if PPC64 || 44x || FSL_BOOKE
        help
          Build a kernel suitable for use as a kdump capture kernel.
          The same kernel binary can be used as production kernel and dump
@@ -886,7 +889,7 @@ config DYNAMIC_MEMSTART
 
 config RELOCATABLE
        bool "Build a relocatable kernel"
-       depends on ADVANCED_OPTIONS && FLATMEM && 44x
+       depends on ADVANCED_OPTIONS && FLATMEM && (44x || FSL_BOOKE)
        select NONSTATIC_KERNEL
        help
          This builds a kernel image that is capable of running at the
index 554734ff302e89234c0d3ae51d1f11a840119c57..d61c03525777ce3cdaeab8a294fb6083e64cfe81 100644 (file)
@@ -16,6 +16,7 @@ mktree
 uImage
 cuImage.*
 dtbImage.*
+*.dtb
 treeImage.*
 zImage
 zImage.initrd
index ca7f08cc4afd770b528931bbab92edc55ad5e8db..90e9d95486603281684c9a06bdbb5029e06b0843 100644 (file)
@@ -71,9 +71,9 @@ src-wlib-y := string.S crt0.S crtsavres.S stdio.c main.c \
                uartlite.c mpc52xx-psc.c
 src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c
 src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c
-src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c
+src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c fsl-soc.c
 src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c
-src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c
+src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c fsl-soc.c
 
 src-plat-y := of.c epapr.c
 src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \
@@ -95,7 +95,7 @@ src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c
 src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \
                                        cuboot-c2k.c gamecube-head.S \
                                        gamecube.c wii-head.S wii.c holly.c \
-                                       prpmc2800.c
+                                       prpmc2800.c fixed-head.S mvme5100.c
 src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
 src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
 src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c
@@ -286,6 +286,7 @@ image-$(CONFIG_MPC7448HPC2)         += cuImage.mpc7448hpc2
 image-$(CONFIG_PPC_C2K)                        += cuImage.c2k
 image-$(CONFIG_GAMECUBE)               += dtbImage.gamecube
 image-$(CONFIG_WII)                    += dtbImage.wii
+image-$(CONFIG_MVME5100)               += dtbImage.mvme5100
 
 # Board port in arch/powerpc/platform/amigaone/Kconfig
 image-$(CONFIG_AMIGAONE)               += cuImage.amigaone
diff --git a/arch/powerpc/boot/dts/fsl/elo3-dma-2.dtsi b/arch/powerpc/boot/dts/fsl/elo3-dma-2.dtsi
new file mode 100644 (file)
index 0000000..d3cc8d0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * QorIQ Elo3 DMA device tree stub [ controller @ offset 0x102300 ]
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+dma2: dma@102300 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "fsl,elo3-dma";
+       reg = <0x102300 0x4>,
+             <0x102600 0x4>;
+       ranges = <0x0 0x102100 0x500>;
+       dma-channel@0 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x0 0x80>;
+               interrupts = <464 2 0 0>;
+       };
+       dma-channel@80 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x80 0x80>;
+               interrupts = <465 2 0 0>;
+       };
+       dma-channel@100 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x100 0x80>;
+               interrupts = <466 2 0 0>;
+       };
+       dma-channel@180 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x180 0x80>;
+               interrupts = <467 2 0 0>;
+       };
+       dma-channel@300 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x300 0x80>;
+               interrupts = <468 2 0 0>;
+       };
+       dma-channel@380 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x380 0x80>;
+               interrupts = <469 2 0 0>;
+       };
+       dma-channel@400 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x400 0x80>;
+               interrupts = <470 2 0 0>;
+       };
+       dma-channel@480 {
+               compatible = "fsl,eloplus-dma-channel";
+               reg = <0x480 0x80>;
+               interrupts = <471 2 0 0>;
+       };
+};
index 68cc5e7f64777c6a1021494dc5826df4a658c83b..642dc3a83d0e352a46583df09dbecddeb46bc091 100644 (file)
@@ -36,7 +36,8 @@
        #address-cells = <2>;
        #size-cells = <1>;
        compatible = "fsl,p1020-elbc", "fsl,elbc", "simple-bus";
-       interrupts = <19 2 0 0>;
+       interrupts = <19 2 0 0>,
+                    <16 2 0 0>;
 };
 
 /* controller at 0x9000 */
index adb82fd9057f3ddba3861b3a1f5928fd7d5844c9..407cb5fd0f5bad533d31e7afc613f83fd36f3e67 100644 (file)
@@ -36,7 +36,8 @@
        #address-cells = <2>;
        #size-cells = <1>;
        compatible = "fsl,p1021-elbc", "fsl,elbc", "simple-bus";
-       interrupts = <19 2 0 0>;
+       interrupts = <19 2 0 0>,
+                    <16 2 0 0>;
 };
 
 /* controller at 0x9000 */
index e179803a81ef88b6c17feeba36a157bbe3a51dbd..ebf2022345498602fdc3a31487631bfd2e556ed8 100644 (file)
@@ -40,7 +40,8 @@
         * pin muxing when the DIU is enabled.
         */
        compatible = "fsl,p1022-elbc", "fsl,elbc";
-       interrupts = <19 2 0 0>;
+       interrupts = <19 2 0 0>,
+                    <16 2 0 0>;
 };
 
 /* controller at 0x9000 */
index f1105bffa915672c2b8d1d65a362c8c0d64d0626..81437fdf1db4f0ba1198487ce6c0dc452c856885 100644 (file)
@@ -36,7 +36,8 @@
        #address-cells = <2>;
        #size-cells = <1>;
        compatible = "fsl,p1023-elbc", "fsl,elbc", "simple-bus";
-       interrupts = <19 2 0 0>;
+       interrupts = <19 2 0 0>,
+                    <16 2 0 0>;
 };
 
 /* controller at 0xa000 */
index 1613d6e4049eb2ba22aeceef97e8e57110620713..5ba7f01e2a297878251001d427bf498bdd94397c 100644 (file)
 
                MSI: ppc4xx-msi@C10000000 {
                        compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
-                       reg = < 0x0 0xEF620000 0x100>;
+                       reg = <0xEF620000 0x100>;
                        sdr-base = <0x4B0>;
                        msi-data = <0x00000000>;
                        msi-mask = <0x44440000>;
diff --git a/arch/powerpc/boot/dts/mvme5100.dts b/arch/powerpc/boot/dts/mvme5100.dts
new file mode 100644 (file)
index 0000000..1ecb341
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Device Tree Source for Motorola/Emerson MVME5100.
+ *
+ * Copyright 2013 CSC Australia Pty. Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "MVME5100";
+       compatible = "MVME5100";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               serial0 = &serial0;
+               pci0 = &pci0;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,7410 {
+                       device_type = "cpu";
+                       reg = <0x0>;
+                       /* Following required by dtc but not used */
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       i-cache-size = <32768>;
+                       d-cache-size = <32768>;
+                       timebase-frequency = <25000000>;
+                       clock-frequency = <500000000>;
+                       bus-frequency = <100000000>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x20000000>;
+       };
+
+       hawk@fef80000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "hawk-bridge", "simple-bus";
+               ranges = <0x0 0xfef80000 0x10000>;
+               reg = <0xfef80000 0x10000>;
+
+               serial0: serial@8000 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x8000 0x80>;
+                       reg-shift = <4>;
+                       clock-frequency = <1843200>;
+                       current-speed = <9600>;
+                       interrupts = <1 1>; // IRQ1 Level Active Low.
+                       interrupt-parent = <&mpic>;
+               };
+
+               serial1: serial@8200 {
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x8200 0x80>;
+                       reg-shift = <4>;
+                       clock-frequency = <1843200>;
+                       current-speed = <9600>;
+                       interrupts = <1 1>; // IRQ1 Level Active Low.
+                       interrupt-parent = <&mpic>;
+               };
+
+               mpic: interrupt-controller@f3f80000 {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       device_type = "open-pic";
+                       compatible = "chrp,open-pic";
+                       interrupt-controller;
+                       reg = <0xf3f80000 0x40000>;
+               };
+       };
+
+       pci0: pci@feff0000 {
+               #address-cells = <3>;
+               #size-cells = <2>;
+               #interrupt-cells = <1>;
+               device_type = "pci";
+               compatible = "hawk-pci";
+               reg = <0xfec00000 0x400000>;
+               8259-interrupt-acknowledge = <0xfeff0030>;
+               ranges = <0x1000000 0x0        0x0 0xfe000000 0x0 0x800000
+                         0x2000000 0x0 0x80000000 0x80000000 0x0 0x74000000>;
+               bus-range = <0 255>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+
+                       /*
+                        * This definition (IDSEL 11) duplicates the
+                        * interrupts definition in the i8259
+                        * interrupt controller below.
+                        *
+                        * Do not change the interrupt sense/polarity from
+                        * 0x2 to anything else, doing so will cause endless
+                        * "spurious" i8259 interrupts to be fielded.
+                        */
+                       // IDSEL 11 - iPMC712 PCI/ISA Bridge
+                       0x5800 0x0 0x0 0x1 &mpic 0x0 0x2
+                       0x5800 0x0 0x0 0x2 &mpic 0x0 0x2
+                       0x5800 0x0 0x0 0x3 &mpic 0x0 0x2
+                       0x5800 0x0 0x0 0x4 &mpic 0x0 0x2
+
+                       /* IDSEL 12 - Not Used */
+
+                       /* IDSEL 13 - Universe VME Bridge */
+                       0x6800 0x0 0x0 0x1 &mpic 0x5 0x1
+                       0x6800 0x0 0x0 0x2 &mpic 0x6 0x1
+                       0x6800 0x0 0x0 0x3 &mpic 0x7 0x1
+                       0x6800 0x0 0x0 0x4 &mpic 0x8 0x1
+
+                       /* IDSEL 14 - ENET 1 */
+                       0x7000 0x0 0x0 0x1 &mpic 0x2 0x1
+
+                       /* IDSEL 15 - Not Used */
+
+                       /* IDSEL 16 - PMC Slot 1 */
+                       0x8000 0x0 0x0 0x1 &mpic 0x9 0x1
+                       0x8000 0x0 0x0 0x2 &mpic 0xa 0x1
+                       0x8000 0x0 0x0 0x3 &mpic 0xb 0x1
+                       0x8000 0x0 0x0 0x4 &mpic 0xc 0x1
+
+                       /* IDSEL 17 - PMC Slot 2 */
+                       0x8800 0x0 0x0 0x1 &mpic 0xc 0x1
+                       0x8800 0x0 0x0 0x2 &mpic 0x9 0x1
+                       0x8800 0x0 0x0 0x3 &mpic 0xa 0x1
+                       0x8800 0x0 0x0 0x4 &mpic 0xb 0x1
+
+                       /* IDSEL 18 - Not Used */
+
+                       /* IDSEL 19 - ENET 2 */
+                       0x9800 0x0 0x0 0x1 &mpic 0xd 0x1
+
+                       /* IDSEL 20 - PMCSPAN (PCI-X) */
+                       0xa000 0x0 0x0 0x1 &mpic 0x9 0x1
+                       0xa000 0x0 0x0 0x2 &mpic 0xa 0x1
+                       0xa000 0x0 0x0 0x3 &mpic 0xb 0x1
+                       0xa000 0x0 0x0 0x4 &mpic 0xc 0x1
+
+               >;
+
+               isa {
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+                       #interrupt-cells = <2>;
+                       device_type = "isa";
+                       compatible = "isa";
+                       ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>;
+                       interrupt-parent = <&i8259>;
+
+                       i8259: interrupt-controller@20 {
+                               #interrupt-cells = <2>;
+                               #address-cells = <0>;
+                               interrupts = <0 2>;
+                               device_type = "interrupt-controller";
+                               compatible = "chrp,iic";
+                               interrupt-controller;
+                               reg = <1 0x00000020 0x00000002
+                                       1 0x000000a0 0x00000002
+                                       1 0x000004d0 0x00000002>;
+                               interrupt-parent = <&mpic>;
+                       };
+
+               };
+
+       };
+
+       chosen {
+               linux,stdout-path = &serial0;
+        };
+
+};
diff --git a/arch/powerpc/boot/dts/p1010rdb-pa.dts b/arch/powerpc/boot/dts/p1010rdb-pa.dts
new file mode 100644 (file)
index 0000000..767d4c0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * P1010 RDB Device Tree Source
+ *
+ * Copyright 2011 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/ "fsl/p1010si-pre.dtsi"
+
+/ {
+       model = "fsl,P1010RDB";
+       compatible = "fsl,P1010RDB";
+
+       /include/ "p1010rdb_32b.dtsi"
+};
+
+/include/ "p1010rdb.dtsi"
+/include/ "p1010rdb-pa.dtsi"
+/include/ "fsl/p1010si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1010rdb-pa.dtsi b/arch/powerpc/boot/dts/p1010rdb-pa.dtsi
new file mode 100644 (file)
index 0000000..434fb2d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&ifc_nand {
+       partition@0 {
+               /* This location must not be altered  */
+               /* 1MB for u-boot Bootloader Image */
+               reg = <0x0 0x00100000>;
+               label = "NAND U-Boot Image";
+               read-only;
+       };
+
+       partition@100000 {
+               /* 1MB for DTB Image */
+               reg = <0x00100000 0x00100000>;
+               label = "NAND DTB Image";
+       };
+
+       partition@200000 {
+               /* 4MB for Linux Kernel Image */
+               reg = <0x00200000 0x00400000>;
+               label = "NAND Linux Kernel Image";
+       };
+
+       partition@600000 {
+               /* 4MB for Compressed Root file System Image */
+               reg = <0x00600000 0x00400000>;
+               label = "NAND Compressed RFS Image";
+       };
+
+       partition@a00000 {
+               /* 15MB for JFFS2 based Root file System */
+               reg = <0x00a00000 0x00f00000>;
+               label = "NAND JFFS2 Root File System";
+       };
+
+       partition@1900000 {
+               /* 7MB for User Area */
+               reg = <0x01900000 0x00700000>;
+               label = "NAND User area";
+       };
+};
+
+&phy0 {
+       interrupts = <1 1 0 0>;
+};
+
+&phy1 {
+       interrupts = <2 1 0 0>;
+};
+
+&phy2 {
+       interrupts = <4 1 0 0>;
+};
similarity index 64%
rename from arch/powerpc/boot/dts/p1010rdb_36b.dts
rename to arch/powerpc/boot/dts/p1010rdb-pa_36b.dts
index 64776f4a4651cca6db3a3b5baf1b821a7eeb7638..3033371bc007ec9f6cd7a4c87e608d6422f46e5f 100644 (file)
        model = "fsl,P1010RDB";
        compatible = "fsl,P1010RDB";
 
-       memory {
-               device_type = "memory";
-       };
-
-       board_ifc: ifc: ifc@fffe1e000 {
-               /* NOR, NAND Flashes and CPLD on board */
-               ranges = <0x0 0x0 0xf 0xee000000 0x02000000
-                         0x1 0x0 0xf 0xff800000 0x00010000
-                         0x3 0x0 0xf 0xffb00000 0x00000020>;
-               reg = <0xf 0xffe1e000 0 0x2000>;
-       };
-
-       board_soc: soc: soc@fffe00000 {
-               ranges = <0x0 0xf 0xffe00000 0x100000>;
-       };
-
-       pci0: pcie@fffe09000 {
-               reg = <0xf 0xffe09000 0 0x1000>;
-               ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xc0000000
-                                 0x2000000 0x0 0xc0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       pci1: pcie@fffe0a000 {
-               reg = <0xf 0xffe0a000 0 0x1000>;
-               ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xc0000000
-                                 0x2000000 0x0 0xc0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
+       /include/ "p1010rdb_36b.dtsi"
 };
 
 /include/ "p1010rdb.dtsi"
+/include/ "p1010rdb-pa.dtsi"
 /include/ "fsl/p1010si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1010rdb-pb.dts b/arch/powerpc/boot/dts/p1010rdb-pb.dts
new file mode 100644 (file)
index 0000000..6eeb7d3
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * P1010 RDB Device Tree Source
+ *
+ * Copyright 2011 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/ "fsl/p1010si-pre.dtsi"
+
+/ {
+       model = "fsl,P1010RDB-PB";
+       compatible = "fsl,P1010RDB-PB";
+
+       /include/ "p1010rdb_32b.dtsi"
+};
+
+/include/ "p1010rdb.dtsi"
+
+&phy0 {
+       interrupts = <0 1 0 0>;
+};
+
+&phy1 {
+       interrupts = <2 1 0 0>;
+};
+
+&phy2 {
+       interrupts = <1 1 0 0>;
+};
+
+/include/ "fsl/p1010si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts b/arch/powerpc/boot/dts/p1010rdb-pb_36b.dts
new file mode 100644 (file)
index 0000000..7ab3c90
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * P1010 RDB Device Tree Source (36-bit address map)
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1010si-pre.dtsi"
+
+/ {
+       model = "fsl,P1010RDB-PB";
+       compatible = "fsl,P1010RDB-PB";
+
+       /include/ "p1010rdb_36b.dtsi"
+};
+
+/include/ "p1010rdb.dtsi"
+
+&phy0 {
+       interrupts = <0 1 0 0>;
+};
+
+&phy1 {
+       interrupts = <2 1 0 0>;
+};
+
+&phy2 {
+       interrupts = <1 1 0 0>;
+};
+
+/include/ "fsl/p1010si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1010rdb.dts b/arch/powerpc/boot/dts/p1010rdb.dts
deleted file mode 100644 (file)
index b868d22..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * P1010 RDB Device Tree Source
- *
- * Copyright 2011 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/ "fsl/p1010si-pre.dtsi"
-
-/ {
-       model = "fsl,P1010RDB";
-       compatible = "fsl,P1010RDB";
-
-       memory {
-               device_type = "memory";
-       };
-
-       board_ifc: ifc: ifc@ffe1e000 {
-               /* NOR, NAND Flashes and CPLD on board */
-               ranges = <0x0 0x0 0x0 0xee000000 0x02000000
-                         0x1 0x0 0x0 0xff800000 0x00010000
-                         0x3 0x0 0x0 0xffb00000 0x00000020>;
-               reg = <0x0 0xffe1e000 0 0x2000>;
-       };
-
-       board_soc: soc: soc@ffe00000 {
-               ranges = <0x0 0x0 0xffe00000 0x100000>;
-       };
-
-       pci0: pcie@ffe09000 {
-               reg = <0 0xffe09000 0 0x1000>;
-               ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xa0000000
-                                 0x2000000 0x0 0xa0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       pci1: pcie@ffe0a000 {
-               reg = <0 0xffe0a000 0 0x1000>;
-               ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0x80000000
-                                 0x2000000 0x0 0x80000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-};
-
-/include/ "p1010rdb.dtsi"
-/include/ "fsl/p1010si-post.dtsi"
index ec7c27a646711c176ba3cd1a51cf5d5e9b9d37b7..ea534efa790d367beade9a27e8a93d27431f208f 100644 (file)
                };
        };
 
-       nand@1,0 {
+       ifc_nand: nand@1,0 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "fsl,ifc-nand";
                reg = <0x1 0x0 0x10000>;
-
-               partition@0 {
-                       /* This location must not be altered  */
-                       /* 1MB for u-boot Bootloader Image */
-                       reg = <0x0 0x00100000>;
-                       label = "NAND U-Boot Image";
-                       read-only;
-               };
-
-               partition@100000 {
-                       /* 1MB for DTB Image */
-                       reg = <0x00100000 0x00100000>;
-                       label = "NAND DTB Image";
-               };
-
-               partition@200000 {
-                       /* 4MB for Linux Kernel Image */
-                       reg = <0x00200000 0x00400000>;
-                       label = "NAND Linux Kernel Image";
-               };
-
-               partition@600000 {
-                       /* 4MB for Compressed Root file System Image */
-                       reg = <0x00600000 0x00400000>;
-                       label = "NAND Compressed RFS Image";
-               };
-
-               partition@a00000 {
-                       /* 15MB for JFFS2 based Root file System */
-                       reg = <0x00a00000 0x00f00000>;
-                       label = "NAND JFFS2 Root File System";
-               };
-
-               partition@1900000 {
-                       /* 7MB for User Area */
-                       reg = <0x01900000 0x00700000>;
-                       label = "NAND User area";
-               };
        };
 
        cpld@3,0 {
 
        mdio@24000 {
                phy0: ethernet-phy@0 {
-                       interrupts = <3 1 0 0>;
                        reg = <0x1>;
                };
 
                phy1: ethernet-phy@1 {
-                       interrupts = <2 1 0 0>;
                        reg = <0x0>;
                };
 
                phy2: ethernet-phy@2 {
-                       interrupts = <2 1 0 0>;
                        reg = <0x2>;
                };
 
diff --git a/arch/powerpc/boot/dts/p1010rdb_32b.dtsi b/arch/powerpc/boot/dts/p1010rdb_32b.dtsi
new file mode 100644 (file)
index 0000000..fdc19aa
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+memory {
+       device_type = "memory";
+};
+
+board_ifc: ifc: ifc@ffe1e000 {
+       /* NOR, NAND Flashes and CPLD on board */
+       ranges = <0x0 0x0 0x0 0xee000000 0x02000000
+                 0x1 0x0 0x0 0xff800000 0x00010000
+                 0x3 0x0 0x0 0xffb00000 0x00000020>;
+       reg = <0x0 0xffe1e000 0 0x2000>;
+};
+
+board_soc: soc: soc@ffe00000 {
+       ranges = <0x0 0x0 0xffe00000 0x100000>;
+};
+
+pci0: pcie@ffe09000 {
+       reg = <0 0xffe09000 0 0x1000>;
+       ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+                 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+       pcie@0 {
+               ranges = <0x2000000 0x0 0xa0000000
+                         0x2000000 0x0 0xa0000000
+                         0x0 0x20000000
+
+                         0x1000000 0x0 0x0
+                         0x1000000 0x0 0x0
+                         0x0 0x100000>;
+       };
+};
+
+pci1: pcie@ffe0a000 {
+       reg = <0 0xffe0a000 0 0x1000>;
+       ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+                 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+       pcie@0 {
+               ranges = <0x2000000 0x0 0x80000000
+                         0x2000000 0x0 0x80000000
+                         0x0 0x20000000
+
+                         0x1000000 0x0 0x0
+                         0x1000000 0x0 0x0
+                         0x0 0x100000>;
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1010rdb_36b.dtsi b/arch/powerpc/boot/dts/p1010rdb_36b.dtsi
new file mode 100644 (file)
index 0000000..de2fcee
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * P1010 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+memory {
+       device_type = "memory";
+};
+
+board_ifc: ifc: ifc@fffe1e000 {
+       /* NOR, NAND Flashes and CPLD on board */
+       ranges = <0x0 0x0 0xf 0xee000000 0x02000000
+                 0x1 0x0 0xf 0xff800000 0x00010000
+                 0x3 0x0 0xf 0xffb00000 0x00000020>;
+       reg = <0xf 0xffe1e000 0 0x2000>;
+};
+
+board_soc: soc: soc@fffe00000 {
+       ranges = <0x0 0xf 0xffe00000 0x100000>;
+};
+
+pci0: pcie@fffe09000 {
+       reg = <0xf 0xffe09000 0 0x1000>;
+       ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+                 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+       pcie@0 {
+               ranges = <0x2000000 0x0 0xc0000000
+                         0x2000000 0x0 0xc0000000
+                         0x0 0x20000000
+
+                         0x1000000 0x0 0x0
+                         0x1000000 0x0 0x0
+                         0x0 0x100000>;
+       };
+};
+
+pci1: pcie@fffe0a000 {
+       reg = <0xf 0xffe0a000 0 0x1000>;
+       ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+                 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+       pcie@0 {
+               ranges = <0x2000000 0x0 0xc0000000
+                         0x2000000 0x0 0xc0000000
+                         0x0 0x20000000
+
+                         0x1000000 0x0 0x0
+                         0x1000000 0x0 0x0
+                         0x0 0x100000>;
+       };
+};
index 873da350d01ba6556b136c99a49ffe2569428fb3..957e0dc1dc0f62ceb8507acf115c76f06e8ea8dd 100644 (file)
                         */
                };
                rtc@68 {
-                       compatible = "dallas,ds1339";
+                       compatible = "dallas,ds3232";
                        reg = <0x68>;
+                       interrupts = <0x1 0x1 0 0>;
                };
                adt7461@4c {
                        compatible = "adi,adt7461";
diff --git a/arch/powerpc/boot/dts/p1025twr.dts b/arch/powerpc/boot/dts/p1025twr.dts
new file mode 100644 (file)
index 0000000..9036a49
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * P1025 TWR Device Tree Source (32-bit address map)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1021si-pre.dtsi"
+/ {
+       model = "fsl,P1025";
+       compatible = "fsl,TWR-P1025";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0 0xffe05000 0 0x1000>;
+
+               /* NOR Flash and SSD1289 */
+               ranges = <0x0 0x0 0x0 0xec000000 0x04000000
+                         0x2 0x0 0x0 0xe0000000 0x00020000>;
+       };
+
+       soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@ffe09000 {
+               ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+               reg = <0 0xffe09000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xa0000000
+                                 0x2000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               reg = <0 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0x80000000
+                                 0x2000000 0x0 0x80000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       qe: qe@ffe80000 {
+               ranges = <0x0 0x0 0xffe80000 0x40000>;
+               reg = <0 0xffe80000 0 0x480>;
+               brg-frequency = <0>;
+               bus-frequency = <0>;
+       };
+};
+
+/include/ "p1025twr.dtsi"
+/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1025twr.dtsi b/arch/powerpc/boot/dts/p1025twr.dtsi
new file mode 100644 (file)
index 0000000..8453501
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * P1025 TWR Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/{
+       aliases {
+               ethernet3 = &enet3;
+               ethernet4 = &enet4;
+       };
+};
+
+&lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x4000000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 256KB for Vitesse 7385 Switch firmware */
+                       reg = <0x0 0x00040000>;
+                       label = "NOR Vitesse-7385 Firmware";
+                       read-only;
+               };
+
+               partition@40000 {
+                       /* 256KB for DTB Image */
+                       reg = <0x00040000 0x00040000>;
+                       label = "NOR DTB Image";
+               };
+
+               partition@80000 {
+                       /* 5.5 MB for Linux Kernel Image */
+                       reg = <0x00080000 0x00580000>;
+                       label = "NOR Linux Kernel Image";
+               };
+
+               partition@400000 {
+                       /* 56.75MB for Root file System */
+                       reg = <0x00600000 0x038c0000>;
+                       label = "NOR Root File System";
+               };
+
+               partition@ec0000 {
+                       /* This location must not be altered  */
+                       /* 256KB for QE ucode firmware*/
+                       reg = <0x03ec0000 0x00040000>;
+                       label = "NOR QE microcode firmware";
+                       read-only;
+               };
+
+               partition@f00000 {
+                       /* This location must not be altered  */
+                       /* 512KB for u-boot Bootloader Image */
+                       /* 512KB for u-boot Environment Variables */
+                       reg = <0x03f00000 0x00100000>;
+                       label = "NOR U-Boot Image";
+                       read-only;
+               };
+       };
+
+       /* CS2 for Display */
+       display@2,0 {
+               compatible = "solomon,ssd1289fb";
+               reg = <0x2 0x0000 0x0004>;
+       };
+
+};
+
+&soc {
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@2 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <1 1 0 0>;
+                       reg = <0x2>;
+               };
+
+               phy1: ethernet-phy@1 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <2 1 0 0>;
+                       reg = <0x1>;
+               };
+
+               tbi0: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@25000 {
+               tbi1: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@26000 {
+               tbi2: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       enet0: ethernet@b0000 {
+               phy-handle = <&phy0>;
+               phy-connection-type = "rgmii-id";
+
+       };
+
+       enet1: ethernet@b1000 {
+               status = "disabled";
+       };
+
+       enet2: ethernet@b2000 {
+               phy-handle = <&phy1>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       par_io@e0100 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               reg = <0xe0100 0x60>;
+               ranges = <0x0 0xe0100 0x60>;
+               device_type = "par_io";
+               num-ports = <3>;
+               pio1: ucc_pin@01 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x1  0x13 0x1  0x0  0x1  0x0    /* QE_MUX_MDC */
+                               0x1  0x14 0x3  0x0  0x1  0x0    /* QE_MUX_MDIO */
+                               0x0  0x17 0x2  0x0  0x2  0x0    /* CLK12 */
+                               0x0  0x18 0x2  0x0  0x1  0x0    /* CLK9 */
+                               0x0  0x7  0x1  0x0  0x2  0x0    /* ENET1_TXD0_SER1_TXD0 */
+                               0x0  0x9  0x1  0x0  0x2  0x0    /* ENET1_TXD1_SER1_TXD1 */
+                               0x0  0xb  0x1  0x0  0x2  0x0    /* ENET1_TXD2_SER1_TXD2 */
+                               0x0  0xc  0x1  0x0  0x2  0x0    /* ENET1_TXD3_SER1_TXD3 */
+                               0x0  0x6  0x2  0x0  0x2  0x0    /* ENET1_RXD0_SER1_RXD0 */
+                               0x0  0xa  0x2  0x0  0x2  0x0    /* ENET1_RXD1_SER1_RXD1 */
+                               0x0  0xe  0x2  0x0  0x2  0x0    /* ENET1_RXD2_SER1_RXD2 */
+                               0x0  0xf  0x2  0x0  0x2  0x0    /* ENET1_RXD3_SER1_RXD3 */
+                               0x0  0x5  0x1  0x0  0x2  0x0    /* ENET1_TX_EN_SER1_RTS_B */
+                               0x0  0xd  0x1  0x0  0x2  0x0    /* ENET1_TX_ER */
+                               0x0  0x4  0x2  0x0  0x2  0x0    /* ENET1_RX_DV_SER1_CTS_B */
+                               0x0  0x8  0x2  0x0  0x2  0x0    /* ENET1_RX_ER_SER1_CD_B */
+                               0x0  0x11 0x2  0x0  0x2  0x0    /* ENET1_CRS */
+                               0x0  0x10 0x2  0x0  0x2  0x0>;    /* ENET1_COL */
+               };
+
+               pio2: ucc_pin@02 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x1  0x13 0x1  0x0  0x1  0x0    /* QE_MUX_MDC */
+                               0x1  0x14 0x3  0x0  0x1  0x0    /* QE_MUX_MDIO */
+                               0x1  0xb  0x2  0x0  0x1  0x0    /* CLK13 */
+                               0x1  0x7  0x1  0x0  0x2  0x0    /* ENET5_TXD0_SER5_TXD0 */
+                               0x1  0xa  0x1  0x0  0x2  0x0    /* ENET5_TXD1_SER5_TXD1 */
+                               0x1  0x6  0x2  0x0  0x2  0x0    /* ENET5_RXD0_SER5_RXD0 */
+                               0x1  0x9  0x2  0x0  0x2  0x0    /* ENET5_RXD1_SER5_RXD1 */
+                               0x1  0x5  0x1  0x0  0x2  0x0    /* ENET5_TX_EN_SER5_RTS_B */
+                               0x1  0x4  0x2  0x0  0x2  0x0    /* ENET5_RX_DV_SER5_CTS_B */
+                               0x1  0x8  0x2  0x0  0x2  0x0>;    /* ENET5_RX_ER_SER5_CD_B */
+               };
+
+               pio3: ucc_pin@03 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x0  0x16 0x2  0x0  0x2  0x0    /* SER7_CD_B*/
+                               0x0  0x12 0x2  0x0  0x2  0x0    /* SER7_CTS_B*/
+                               0x0  0x13 0x1  0x0  0x2  0x0    /* SER7_RTS_B*/
+                               0x0  0x14 0x2  0x0  0x2  0x0    /* SER7_RXD0*/
+                               0x0  0x15 0x1  0x0  0x2  0x0>;    /* SER7_TXD0*/
+               };
+
+               pio4: ucc_pin@04 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x1  0x0  0x2  0x0  0x2  0x0    /* SER3_CD_B*/
+                               0x0  0x1c 0x2  0x0  0x2  0x0    /* SER3_CTS_B*/
+                               0x0  0x1d 0x1  0x0  0x2  0x0    /* SER3_RTS_B*/
+                               0x0  0x1e 0x2  0x0  0x2  0x0    /* SER3_RXD0*/
+                               0x0  0x1f 0x1  0x0  0x2  0x0>;    /* SER3_TXD0*/
+               };
+       };
+};
+
+&qe {
+       enet3: ucc@2000 {
+               device_type = "network";
+               compatible = "ucc_geth";
+               rx-clock-name = "clk12";
+               tx-clock-name = "clk9";
+               pio-handle = <&pio1>;
+               phy-handle = <&qe_phy0>;
+               phy-connection-type = "mii";
+       };
+
+       mdio@2120 {
+               qe_phy0: ethernet-phy@18 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <4 1 0 0>;
+                       reg = <0x18>;
+                       device_type = "ethernet-phy";
+               };
+               qe_phy1: ethernet-phy@19 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <5 1 0 0>;
+                       reg = <0x19>;
+                       device_type = "ethernet-phy";
+               };
+               tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       enet4: ucc@2400 {
+               device_type = "network";
+               compatible = "ucc_geth";
+               rx-clock-name = "none";
+               tx-clock-name = "clk13";
+               pio-handle = <&pio2>;
+               phy-handle = <&qe_phy1>;
+               phy-connection-type = "rmii";
+       };
+
+       serial2: ucc@2600 {
+               device_type = "serial";
+               compatible = "ucc_uart";
+               port-number = <0>;
+               rx-clock-name = "brg6";
+               tx-clock-name = "brg6";
+               pio-handle = <&pio3>;
+       };
+
+       serial3: ucc@2200 {
+               device_type = "serial";
+               compatible = "ucc_uart";
+               port-number = <1>;
+               rx-clock-name = "brg2";
+               tx-clock-name = "brg2";
+               pio-handle = <&pio4>;
+       };
+};
index fc7073bc547efaa4e196a80d08be24155fea9695..391a4e299783d84830002c95535bd9a5c6d9c848 100644 (file)
                        #size-cells = <1>;
                        compatible = "xlnx,compound";
                        ethernet@81c00000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                compatible = "xlnx,xps-ll-temac-1.01.b";
                                device_type = "network";
                                interrupt-parent = <&xps_intc_0>;
diff --git a/arch/powerpc/boot/mvme5100.c b/arch/powerpc/boot/mvme5100.c
new file mode 100644 (file)
index 0000000..cb865f8
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Motorola/Emerson MVME5100 with PPCBug firmware.
+ *
+ * Author: Stephen Chivers <schivers@csc.com>
+ *
+ * Copyright 2013 CSC Australia Pty. Ltd.
+ *
+ * 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 "types.h"
+#include "ops.h"
+#include "io.h"
+
+BSS_STACK(4096);
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
+{
+       u32                     heapsize;
+
+       heapsize = 0x8000000 - (u32)_end; /* 128M */
+       simple_alloc_init(_end, heapsize, 32, 64);
+       fdt_init(_dtb_start);
+       serial_console_init();
+}
index 2e1af74a64bec5ba3a53ccde16350520ed3f532a..d27a25518b018b03df07110919104ff6811e1b00 100755 (executable)
@@ -265,6 +265,10 @@ epapr)
     link_address='0x20000000'
     pie=-pie
     ;;
+mvme5100)
+    platformo="$object/fixed-head.o $object/mvme5100.o"
+    binary=y
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
diff --git a/arch/powerpc/configs/85xx/p1023_defconfig b/arch/powerpc/configs/85xx/p1023_defconfig
deleted file mode 100644 (file)
index b06d37d..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-CONFIG_PPC_85xx=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_RCU_FANOUT=32
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_EMBEDDED=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_PHYSICAL_START=0x00000000
-CONFIG_P1023_RDB=y
-CONFIG_P1023_RDS=y
-CONFIG_QUICC_ENGINE=y
-CONFIG_QE_GPIO=y
-CONFIG_CPM2=y
-CONFIG_HIGHMEM=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_BINFMT_MISC=m
-CONFIG_MATH_EMULATION=y
-CONFIG_SWIOTLB=y
-CONFIG_PCI=y
-CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEAER is not set
-# CONFIG_PCIEASPM is not set
-CONFIG_PCI_MSI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-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_ARPD=y
-CONFIG_INET_ESP=y
-# 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_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=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_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_EEPROM_AT24=y
-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_MULTI_LUN=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_ATA=y
-CONFIG_SATA_FSL=y
-CONFIG_SATA_SIL24=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_FS_ENET=y
-CONFIG_FSL_PQ_MDIO=y
-CONFIG_E1000E=y
-CONFIG_PHYLIB=y
-CONFIG_AT803X_PHY=y
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_FIXED_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=y
-CONFIG_NVRAM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_CPM=m
-CONFIG_I2C_MPC=y
-CONFIG_GPIO_MPC8XXX=y
-# CONFIG_HWMON is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=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_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_FSL=y
-CONFIG_USB_STORAGE=y
-CONFIG_EDAC=y
-CONFIG_EDAC_MM_EDAC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_DS1307=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_DMADEVICES=y
-CONFIG_FSL_DMA=y
-# CONFIG_NET_DMA is not set
-CONFIG_STAGING=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_FRAME_WARN=8092
-CONFIG_DEBUG_FS=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-CONFIG_STRICT_DEVMEM=y
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_AES=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DEV_FSL_CAAM=y
index 69128740c14dcd2c693e2d5d71d713016d15da10..15b1ff5d96e76378bf9e80d93b2e85ecf6f25607 100644 (file)
@@ -70,3 +70,4 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRC32_SLICEBY4=y
index 219fd470ed22d402deae87a12ea3ca6333d29384..b8a79d7ee89fae62a28ecad510920bb36916f3f2 100644 (file)
@@ -72,3 +72,4 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRC32_SLICEBY4=y
index d2e0fab5ee5b3ec5ac315fe1e9af261cc24ab567..83d3550fdb5400b26f2508ef9e862346e1c004ae 100644 (file)
@@ -31,6 +31,7 @@ CONFIG_C293_PCIE=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
 CONFIG_P1022_RDK=y
+CONFIG_P1023_RDB=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
@@ -113,6 +114,7 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -211,6 +213,7 @@ CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1307=y
 CONFIG_DMADEVICES=y
 CONFIG_FSL_DMA=y
 # CONFIG_NET_DMA is not set
index 4cb7b59e98bd84259aefb48d8515fd3a4d8da32d..4b686294feb49592594f91c04abaea8377dca52d 100644 (file)
@@ -34,6 +34,7 @@ CONFIG_C293_PCIE=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
 CONFIG_P1022_RDK=y
+CONFIG_P1023_RDB=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
@@ -116,6 +117,7 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -212,6 +214,7 @@ CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1307=y
 CONFIG_DMADEVICES=y
 CONFIG_FSL_DMA=y
 # CONFIG_NET_DMA is not set
index 5c258823e694814a0c7c3e07b0391b919aa29fd9..d954e80c286a92fe1be2b8402fa8f77e114da0ba 100644 (file)
@@ -55,3 +55,4 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_CRC_CCITT=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC32_SLICEBY4=y
index 9e146cdf63ded05591f572fa3b98d1b8400fafa0..3f47d00a10c0d9e8557d26e78f62598f6d629d4d 100644 (file)
@@ -78,3 +78,4 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRC32_SLICEBY4=y
diff --git a/arch/powerpc/configs/mvme5100_defconfig b/arch/powerpc/configs/mvme5100_defconfig
new file mode 100644 (file)
index 0000000..93c7752
--- /dev/null
@@ -0,0 +1,144 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_COMPAT_BRK is not set
+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_EMBEDDED6xx=y
+CONFIG_MVME5100=y
+CONFIG_KVM_GUEST=y
+CONFIG_HZ_100=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 ip=dhcp root=/dev/nfs"
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=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_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_LAPB=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_EEPROM_LEGACY=m
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_E100=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# 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_NR_UARTS=10
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MPC=y
+# CONFIG_HWMON is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_VME_BUS=m
+CONFIG_VME_CA91CX42=m
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_XFS_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_CIFS=m
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=20
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 581a3bcae7283607bed819cb9d26f7a2b6c6b96f..e015896b7e5cebacaf46bb713ab16e2fe2128747 100644 (file)
@@ -186,6 +186,7 @@ CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
+CONFIG_SATA_MV=y
 CONFIG_SATA_SVW=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
index 8616fde0896f41ba81eb32b1c5261aed3892cfa6..4b6f8bf104e0687eb331c9c7d383855966ec5143 100644 (file)
@@ -84,3 +84,4 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRC32_SLICEBY4=y
index 910194e9a1e2a2eab5f64d05be6cf9a522cb33a0..a5e9a7d494d8bd685104397bff26d0265dc15e54 100644 (file)
 #include <asm/asm-compat.h>
 #include <asm/synch.h>
 
+/* PPC bit number conversion */
+#define PPC_BITLSHIFT(be)      (BITS_PER_LONG - 1 - (be))
+#define PPC_BIT(bit)           (1UL << PPC_BITLSHIFT(bit))
+#define PPC_BITMASK(bs, be)    ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+
 /*
  * clear_bit doesn't imply a memory barrier
  */
index 9e495c9a6a889d68bca11e1575ee82c3422b7348..ed0afc1e44a43324a31fb59994b42a768ecb8e33 100644 (file)
@@ -41,8 +41,20 @@ struct ppc64_caches {
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
-#if !defined(__ASSEMBLY__)
+#if defined(__ASSEMBLY__)
+/*
+ * For a snooping icache, we still need a dummy icbi to purge all the
+ * prefetched instructions from the ifetch buffers. We also need a sync
+ * before the icbi to order the the actual stores to memory that might
+ * have modified instructions with the icbi.
+ */
+#define PURGE_PREFETCHED_INS   \
+       sync;                   \
+       icbi    0,r3;           \
+       sync;                   \
+       isync
 
+#else
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifdef CONFIG_6xx
index e245aab7f191cc98bea0e6f8868fb7fb67d3cffe..d463c68fe7f05fa798a151ea179a5f88a842ddee 100644 (file)
@@ -300,6 +300,7 @@ __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
 #else
 #include <asm-generic/cmpxchg-local.h>
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
index a6f8c7a5cbb74f61925243a1ca42bc183d80361a..97e02f985df8e47946438ecc1b0ba2f040ee7bf5 100644 (file)
@@ -34,6 +34,13 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
 unsigned long branch_target(const unsigned int *instr);
 unsigned int translate_branch(const unsigned int *dest,
                              const unsigned int *src);
+#ifdef CONFIG_PPC_BOOK3E_64
+void __patch_exception(int exc, unsigned long addr);
+#define patch_exception(exc, name) do { \
+       extern unsigned int name; \
+       __patch_exception((exc), (unsigned long)&name); \
+} while (0)
+#endif
 
 static inline unsigned long ppc_function_entry(void *func)
 {
index 0d4939ba48e72167a9a496f4f10a805d0badd3eb..617cc767c07681b109c5acd54f667cc3274956b5 100644 (file)
@@ -90,6 +90,18 @@ struct cpu_spec {
         * if the error is fatal, 1 if it was fully recovered and 0 to
         * pass up (not CPU originated) */
        int             (*machine_check)(struct pt_regs *regs);
+
+       /*
+        * Processor specific early machine check handler which is
+        * called in real mode to handle SLB and TLB errors.
+        */
+       long            (*machine_check_early)(struct pt_regs *regs);
+
+       /*
+        * Processor specific routine to flush tlbs.
+        */
+       void            (*flush_tlb)(unsigned long inval_selector);
+
 };
 
 extern struct cpu_spec         *cur_cpu_spec;
index d3e5e9bc8f946fa3fd7158a3ecc931561c71c1a3..9e39ceb1d19fd706014794a6918f671ef12a5a58 100644 (file)
@@ -90,7 +90,8 @@ struct eeh_pe {
 #define EEH_DEV_IRQ_DISABLED   (1 << 3)        /* Interrupt disabled   */
 #define EEH_DEV_DISCONNECTED   (1 << 4)        /* Removing from PE     */
 
-#define EEH_DEV_SYSFS          (1 << 8)        /* Sysfs created        */
+#define EEH_DEV_NO_HANDLER     (1 << 8)        /* No error handler     */
+#define EEH_DEV_SYSFS          (1 << 9)        /* Sysfs created        */
 
 struct eeh_dev {
        int mode;                       /* EEH mode                     */
@@ -117,6 +118,16 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
        return edev ? edev->pdev : NULL;
 }
 
+/* Return values from eeh_ops::next_error */
+enum {
+       EEH_NEXT_ERR_NONE = 0,
+       EEH_NEXT_ERR_INF,
+       EEH_NEXT_ERR_FROZEN_PE,
+       EEH_NEXT_ERR_FENCED_PHB,
+       EEH_NEXT_ERR_DEAD_PHB,
+       EEH_NEXT_ERR_DEAD_IOC
+};
+
 /*
  * The struct is used to trace the registered EEH operation
  * callback functions. Actually, those operation callback
@@ -157,6 +168,7 @@ struct eeh_ops {
        int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
        int (*write_config)(struct device_node *dn, int where, int size, u32 val);
        int (*next_error)(struct eeh_pe **pe);
+       int (*restore_config)(struct device_node *dn);
 };
 
 extern struct eeh_ops *eeh_ops;
index 243ce69ad685ffd335041537e6f0b33b0aafe3df..66830618cc19b2f4b12a5b6cefa8d1663425187e 100644 (file)
@@ -301,9 +301,12 @@ do_kvm_##n:                                                                \
        beq     4f;                     /* if from kernel mode          */ \
        ACCOUNT_CPU_USER_ENTRY(r9, r10);                                   \
        SAVE_PPR(area, r9, r10);                                           \
-4:     std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
-       SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
-       SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe    */ \
+4:     EXCEPTION_PROLOG_COMMON_2(area)                                    \
+       EXCEPTION_PROLOG_COMMON_3(n)                                       \
+       ACCOUNT_STOLEN_TIME
+
+/* Save original regs values from save area to stack frame. */
+#define EXCEPTION_PROLOG_COMMON_2(area)                                           \
        ld      r9,area+EX_R9(r13);     /* move r9, r10 to stackframe   */ \
        ld      r10,area+EX_R10(r13);                                      \
        std     r9,GPR9(r1);                                               \
@@ -318,11 +321,16 @@ do_kvm_##n:                                                               \
        ld      r10,area+EX_CFAR(r13);                                     \
        std     r10,ORIG_GPR3(r1);                                         \
        END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);            \
+       GET_CTR(r10, area);                                                \
+       std     r10,_CTR(r1);
+
+#define EXCEPTION_PROLOG_COMMON_3(n)                                      \
+       std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
+       SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
+       SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe    */ \
        mflr    r9;                     /* Get LR, later save to stack  */ \
        ld      r2,PACATOC(r13);        /* get kernel TOC into r2       */ \
        std     r9,_LINK(r1);                                              \
-       GET_CTR(r10, area);                                                \
-       std     r10,_CTR(r1);                                              \
        lbz     r10,PACASOFTIRQEN(r13);                            \
        mfspr   r11,SPRN_XER;           /* save XER in stackframe       */ \
        std     r10,SOFTE(r1);                                             \
@@ -332,8 +340,7 @@ do_kvm_##n:                                                         \
        li      r10,0;                                                     \
        ld      r11,exception_marker@toc(r2);                              \
        std     r10,RESULT(r1);         /* clear regs->result           */ \
-       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */ \
-       ACCOUNT_STOLEN_TIME
+       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */
 
 /*
  * Exception vectors.
index 420b45368fcff05b5534a3f9bbcb396279bc1cb5..067fb0dca549b86fc4ad02cca3b180718c2a9593 100644 (file)
@@ -285,7 +285,7 @@ struct fsl_lbc_ctrl {
        /* device info */
        struct device                   *dev;
        struct fsl_lbc_regs __iomem     *regs;
-       int                             irq;
+       int                             irq[2];
        wait_queue_head_t               irq_wait;
        spinlock_t                      lock;
        void                            *nand;
index 3bdcfce2c42a926bebc7c2f580ee720f96350818..418fb654370d09c70837943fe399dba75a10cfd2 100644 (file)
@@ -6,7 +6,8 @@
 
 typedef struct {
        unsigned int __softirq_pending;
-       unsigned int timer_irqs;
+       unsigned int timer_irqs_event;
+       unsigned int timer_irqs_others;
        unsigned int pmu_irqs;
        unsigned int mce_exceptions;
        unsigned int spurious_irqs;
index 575fbf81fad02dcd8e946cecfa9c5d5c35e11810..97d3869991ca691ebf0342b496ebe767aee7492a 100644 (file)
@@ -191,8 +191,24 @@ DEF_MMIO_OUT_D(out_le32, 32, stw);
 
 #endif /* __BIG_ENDIAN */
 
+/*
+ * Cache inhibitied accessors for use in real mode, you don't want to use these
+ * unless you know what you're doing.
+ *
+ * NB. These use the cpu byte ordering.
+ */
+DEF_MMIO_OUT_X(out_rm8,   8, stbcix);
+DEF_MMIO_OUT_X(out_rm16, 16, sthcix);
+DEF_MMIO_OUT_X(out_rm32, 32, stwcix);
+DEF_MMIO_IN_X(in_rm8,   8, lbzcix);
+DEF_MMIO_IN_X(in_rm16, 16, lhzcix);
+DEF_MMIO_IN_X(in_rm32, 32, lwzcix);
+
 #ifdef __powerpc64__
 
+DEF_MMIO_OUT_X(out_rm64, 64, stdcix);
+DEF_MMIO_IN_X(in_rm64, 64, ldcix);
+
 #ifdef __BIG_ENDIAN__
 DEF_MMIO_OUT_D(out_be64, 64, std);
 DEF_MMIO_IN_D(in_be64, 64, ld);
index c34656a8925e2f8c3d64d42f7f4efd79dbe36872..f7a8036579b5a43d19ea0730b7e541b61272ab13 100644 (file)
 #include <asm/machdep.h>
 #include <asm/types.h>
 
-#define IOMMU_PAGE_SHIFT      12
-#define IOMMU_PAGE_SIZE       (ASM_CONST(1) << IOMMU_PAGE_SHIFT)
-#define IOMMU_PAGE_MASK       (~((1 << IOMMU_PAGE_SHIFT) - 1))
-#define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE)
+#define IOMMU_PAGE_SHIFT_4K      12
+#define IOMMU_PAGE_SIZE_4K       (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K)
+#define IOMMU_PAGE_MASK_4K       (~((1 << IOMMU_PAGE_SHIFT_4K) - 1))
+#define IOMMU_PAGE_ALIGN_4K(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE_4K)
+
+#define IOMMU_PAGE_SIZE(tblptr) (ASM_CONST(1) << (tblptr)->it_page_shift)
+#define IOMMU_PAGE_MASK(tblptr) (~((1 << (tblptr)->it_page_shift) - 1))
+#define IOMMU_PAGE_ALIGN(addr, tblptr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE(tblptr))
 
 /* Boot time flags */
 extern int iommu_is_off;
 extern int iommu_force_on;
 
-/* Pure 2^n version of get_order */
-static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)
-{
-       return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1;
-}
-
-
 /*
  * IOMAP_MAX_ORDER defines the largest contiguous block
  * of dma space we can get.  IOMAP_MAX_ORDER = 13
@@ -76,11 +73,20 @@ struct iommu_table {
        struct iommu_pool large_pool;
        struct iommu_pool pools[IOMMU_NR_POOLS];
        unsigned long *it_map;       /* A simple allocation bitmap for now */
+       unsigned long  it_page_shift;/* table iommu page size */
 #ifdef CONFIG_IOMMU_API
        struct iommu_group *it_group;
 #endif
 };
 
+/* Pure 2^n version of get_order */
+static inline __attribute_const__
+int get_iommu_order(unsigned long size, struct iommu_table *tbl)
+{
+       return __ilog2((size - 1) >> tbl->it_page_shift) + 1;
+}
+
+
 struct scatterlist;
 
 static inline void set_iommu_table_base(struct device *dev, void *base)
@@ -101,8 +107,34 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
  */
 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
                                            int nid);
+#ifdef CONFIG_IOMMU_API
 extern void iommu_register_group(struct iommu_table *tbl,
                                 int pci_domain_number, unsigned long pe_num);
+extern int iommu_add_device(struct device *dev);
+extern void iommu_del_device(struct device *dev);
+#else
+static inline void iommu_register_group(struct iommu_table *tbl,
+                                       int pci_domain_number,
+                                       unsigned long pe_num)
+{
+}
+
+static inline int iommu_add_device(struct device *dev)
+{
+       return 0;
+}
+
+static inline void iommu_del_device(struct device *dev)
+{
+}
+#endif /* !CONFIG_IOMMU_API */
+
+static inline void set_iommu_table_base_and_group(struct device *dev,
+                                                 void *base)
+{
+       set_iommu_table_base(dev, base);
+       iommu_add_device(dev);
+}
 
 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                        struct scatterlist *sglist, int nelems,
index 1bd92fd43cfb7fc8a14f0bfeeaed62f50700f07d..1503d8c7c41b9f139e9d69d60d4006ee35f8c3ca 100644 (file)
@@ -74,6 +74,7 @@
 #define BOOKE_INTERRUPT_GUEST_DBELL_CRIT 39
 #define BOOKE_INTERRUPT_HV_SYSCALL 40
 #define BOOKE_INTERRUPT_HV_PRIV 41
+#define BOOKE_INTERRUPT_LRAT_ERROR 42
 
 /* book3s */
 
index 844c28de7ec05e96f4578701a9d46c6dda6d2ecb..d0a2a2f9956471362e13093272955f42c0e4121b 100644 (file)
@@ -132,8 +132,6 @@ struct slb_shadow {
        } save_area[SLB_NUM_BOLTED];
 } ____cacheline_aligned;
 
-extern struct slb_shadow slb_shadow[];
-
 /*
  * Layout of entries in the hypervisor's dispatch trace log buffer.
  */
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
new file mode 100644 (file)
index 0000000..8e99edf
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Machine check exception header file.
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#ifndef __ASM_PPC64_MCE_H__
+#define __ASM_PPC64_MCE_H__
+
+#include <linux/bitops.h>
+
+/*
+ * Machine Check bits on power7 and power8
+ */
+#define P7_SRR1_MC_LOADSTORE(srr1)     ((srr1) & PPC_BIT(42)) /* P8 too */
+
+/* SRR1 bits for machine check (On Power7 and Power8) */
+#define P7_SRR1_MC_IFETCH(srr1)        ((srr1) & PPC_BITMASK(43, 45)) /* P8 too */
+
+#define P7_SRR1_MC_IFETCH_UE           (0x1 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_PARITY   (0x2 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_MULTIHIT (0x3 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_BOTH     (0x4 << PPC_BITLSHIFT(45))
+#define P7_SRR1_MC_IFETCH_TLB_MULTIHIT (0x5 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_UE_TLB_RELOAD        (0x6 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL      (0x7 << PPC_BITLSHIFT(45))
+
+/* SRR1 bits for machine check (On Power8) */
+#define P8_SRR1_MC_IFETCH_ERAT_MULTIHIT        (0x4 << PPC_BITLSHIFT(45))
+
+/* DSISR bits for machine check (On Power7 and Power8) */
+#define P7_DSISR_MC_UE                 (PPC_BIT(48))   /* P8 too */
+#define P7_DSISR_MC_UE_TABLEWALK       (PPC_BIT(49))   /* P8 too */
+#define P7_DSISR_MC_ERAT_MULTIHIT      (PPC_BIT(52))   /* P8 too */
+#define P7_DSISR_MC_TLB_MULTIHIT_MFTLB (PPC_BIT(53))   /* P8 too */
+#define P7_DSISR_MC_SLB_PARITY_MFSLB   (PPC_BIT(55))   /* P8 too */
+#define P7_DSISR_MC_SLB_MULTIHIT       (PPC_BIT(56))   /* P8 too */
+#define P7_DSISR_MC_SLB_MULTIHIT_PARITY        (PPC_BIT(57))   /* P8 too */
+
+/*
+ * DSISR bits for machine check (Power8) in addition to above.
+ * Secondary DERAT Multihit
+ */
+#define P8_DSISR_MC_ERAT_MULTIHIT_SEC  (PPC_BIT(54))
+
+/* SLB error bits */
+#define P7_DSISR_MC_SLB_ERRORS         (P7_DSISR_MC_ERAT_MULTIHIT | \
+                                        P7_DSISR_MC_SLB_PARITY_MFSLB | \
+                                        P7_DSISR_MC_SLB_MULTIHIT | \
+                                        P7_DSISR_MC_SLB_MULTIHIT_PARITY)
+
+#define P8_DSISR_MC_SLB_ERRORS         (P7_DSISR_MC_SLB_ERRORS | \
+                                        P8_DSISR_MC_ERAT_MULTIHIT_SEC)
+enum MCE_Version {
+       MCE_V1 = 1,
+};
+
+enum MCE_Severity {
+       MCE_SEV_NO_ERROR = 0,
+       MCE_SEV_WARNING = 1,
+       MCE_SEV_ERROR_SYNC = 2,
+       MCE_SEV_FATAL = 3,
+};
+
+enum MCE_Disposition {
+       MCE_DISPOSITION_RECOVERED = 0,
+       MCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum MCE_Initiator {
+       MCE_INITIATOR_UNKNOWN = 0,
+       MCE_INITIATOR_CPU = 1,
+};
+
+enum MCE_ErrorType {
+       MCE_ERROR_TYPE_UNKNOWN = 0,
+       MCE_ERROR_TYPE_UE = 1,
+       MCE_ERROR_TYPE_SLB = 2,
+       MCE_ERROR_TYPE_ERAT = 3,
+       MCE_ERROR_TYPE_TLB = 4,
+};
+
+enum MCE_UeErrorType {
+       MCE_UE_ERROR_INDETERMINATE = 0,
+       MCE_UE_ERROR_IFETCH = 1,
+       MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+       MCE_UE_ERROR_LOAD_STORE = 3,
+       MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum MCE_SlbErrorType {
+       MCE_SLB_ERROR_INDETERMINATE = 0,
+       MCE_SLB_ERROR_PARITY = 1,
+       MCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_EratErrorType {
+       MCE_ERAT_ERROR_INDETERMINATE = 0,
+       MCE_ERAT_ERROR_PARITY = 1,
+       MCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_TlbErrorType {
+       MCE_TLB_ERROR_INDETERMINATE = 0,
+       MCE_TLB_ERROR_PARITY = 1,
+       MCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+struct machine_check_event {
+       enum MCE_Version        version:8;      /* 0x00 */
+       uint8_t                 in_use;         /* 0x01 */
+       enum MCE_Severity       severity:8;     /* 0x02 */
+       enum MCE_Initiator      initiator:8;    /* 0x03 */
+       enum MCE_ErrorType      error_type:8;   /* 0x04 */
+       enum MCE_Disposition    disposition:8;  /* 0x05 */
+       uint8_t                 reserved_1[2];  /* 0x06 */
+       uint64_t                gpr3;           /* 0x08 */
+       uint64_t                srr0;           /* 0x10 */
+       uint64_t                srr1;           /* 0x18 */
+       union {                                 /* 0x20 */
+               struct {
+                       enum MCE_UeErrorType ue_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         physical_address_provided;
+                       uint8_t         reserved_1[5];
+                       uint64_t        effective_address;
+                       uint64_t        physical_address;
+                       uint8_t         reserved_2[8];
+               } ue_error;
+
+               struct {
+                       enum MCE_SlbErrorType slb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } slb_error;
+
+               struct {
+                       enum MCE_EratErrorType erat_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } erat_error;
+
+               struct {
+                       enum MCE_TlbErrorType tlb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } tlb_error;
+       } u;
+};
+
+struct mce_error_info {
+       enum MCE_ErrorType error_type:8;
+       union {
+               enum MCE_UeErrorType ue_error_type:8;
+               enum MCE_SlbErrorType slb_error_type:8;
+               enum MCE_EratErrorType erat_error_type:8;
+               enum MCE_TlbErrorType tlb_error_type:8;
+       } u;
+       uint8_t         reserved[2];
+};
+
+#define MAX_MC_EVT     100
+
+/* Release flags for get_mce_event() */
+#define MCE_EVENT_RELEASE      true
+#define MCE_EVENT_DONTRELEASE  false
+
+extern void save_mce_event(struct pt_regs *regs, long handled,
+                          struct mce_error_info *mce_err, uint64_t addr);
+extern int get_mce_event(struct machine_check_event *mce, bool release);
+extern void release_mce_event(void);
+extern void machine_check_queue_event(void);
+extern void machine_check_print_event_info(struct machine_check_event *evt);
+extern uint64_t get_mce_fault_addr(struct machine_check_event *evt);
+
+#endif /* __ASM_PPC64_MCE_H__ */
index 936db360790adcf213e263da9bea0aeb259c4be2..89b785d1684673d0e00b7a75c132a345547f2e33 100644 (file)
@@ -286,8 +286,21 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
 extern int mmu_linear_psize;
 extern int mmu_vmemmap_psize;
 
+struct tlb_core_data {
+       /* For software way selection, as on Freescale TLB1 */
+       u8 esel_next, esel_max, esel_first;
+
+       /* Per-core spinlock for e6500 TLB handlers (no tlbsrx.) */
+       u8 lock;
+};
+
 #ifdef CONFIG_PPC64
 extern unsigned long linear_map_top;
+extern int book3e_htw_mode;
+
+#define PPC_HTW_NONE   0
+#define PPC_HTW_IBM    1
+#define PPC_HTW_E6500  2
 
 /*
  * 64-bit booke platforms don't load the tlb in the tlb miss handler code.
index 691fd8aca939f8762257de6423a9ea193fb96c8f..f8d1d6dcf7db63c5947aa2be4fa22564187d9953 100644 (file)
@@ -180,16 +180,17 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 #define MMU_PAGE_64K_AP        3       /* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K  4
 #define MMU_PAGE_1M    5
-#define MMU_PAGE_4M    6
-#define MMU_PAGE_8M    7
-#define MMU_PAGE_16M   8
-#define MMU_PAGE_64M   9
-#define MMU_PAGE_256M  10
-#define MMU_PAGE_1G    11
-#define MMU_PAGE_16G   12
-#define MMU_PAGE_64G   13
-
-#define MMU_PAGE_COUNT 14
+#define MMU_PAGE_2M    6
+#define MMU_PAGE_4M    7
+#define MMU_PAGE_8M    8
+#define MMU_PAGE_16M   9
+#define MMU_PAGE_64M   10
+#define MMU_PAGE_256M  11
+#define MMU_PAGE_1G    12
+#define MMU_PAGE_16G   13
+#define MMU_PAGE_64G   14
+
+#define MMU_PAGE_COUNT 15
 
 #if defined(CONFIG_PPC_STD_MMU_64)
 /* 64-bit classic hash table MMU */
index 7bdcf340016c412285df77ac56162aaa94982416..40157e2ca6914467cddae0225070d8582ad0861c 100644 (file)
@@ -33,6 +33,28 @@ struct opal_takeover_args {
        u64     rd_loc;                 /* r11 */
 };
 
+/*
+ * SG entry
+ *
+ * WARNING: The current implementation requires each entry
+ * to represent a block that is 4k aligned *and* each block
+ * size except the last one in the list to be as well.
+ */
+struct opal_sg_entry {
+       void    *data;
+       long    length;
+};
+
+/* sg list */
+struct opal_sg_list {
+       unsigned long num_entries;
+       struct opal_sg_list *next;
+       struct opal_sg_entry entry[];
+};
+
+/* We calculate number of sg entries based on PAGE_SIZE */
+#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
+
 extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
 
 extern long opal_do_takeover(struct opal_takeover_args *args);
@@ -132,6 +154,9 @@ extern int opal_enter_rtas(struct rtas_args *args,
 #define OPAL_FLASH_VALIDATE                    76
 #define OPAL_FLASH_MANAGE                      77
 #define OPAL_FLASH_UPDATE                      78
+#define OPAL_GET_MSG                           85
+#define OPAL_CHECK_ASYNC_COMPLETION            86
+#define OPAL_SYNC_HOST_REBOOT                  87
 
 #ifndef __ASSEMBLY__
 
@@ -211,7 +236,16 @@ enum OpalPendingState {
        OPAL_EVENT_ERROR_LOG            = 0x40,
        OPAL_EVENT_EPOW                 = 0x80,
        OPAL_EVENT_LED_STATUS           = 0x100,
-       OPAL_EVENT_PCI_ERROR            = 0x200
+       OPAL_EVENT_PCI_ERROR            = 0x200,
+       OPAL_EVENT_MSG_PENDING          = 0x800,
+};
+
+enum OpalMessageType {
+       OPAL_MSG_ASYNC_COMP             = 0,
+       OPAL_MSG_MEM_ERR,
+       OPAL_MSG_EPOW,
+       OPAL_MSG_SHUTDOWN,
+       OPAL_MSG_TYPE_MAX,
 };
 
 /* Machine check related definitions */
@@ -311,12 +345,16 @@ enum OpalMveEnableAction {
        OPAL_ENABLE_MVE = 1
 };
 
-enum OpalPciResetAndReinitScope {
+enum OpalPciResetScope {
        OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
        OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
        OPAL_PCI_IODA_TABLE_RESET = 6,
 };
 
+enum OpalPciReinitScope {
+       OPAL_REINIT_PCI_DEV = 1000
+};
+
 enum OpalPciResetState {
        OPAL_DEASSERT_RESET = 0,
        OPAL_ASSERT_RESET = 1
@@ -356,6 +394,12 @@ enum OpalLPCAddressType {
        OPAL_LPC_FW     = 2,
 };
 
+struct opal_msg {
+       uint32_t msg_type;
+       uint32_t reserved;
+       uint64_t params[8];
+};
+
 struct opal_machine_check_event {
        enum OpalMCE_Version    version:8;      /* 0x00 */
        uint8_t                 in_use;         /* 0x01 */
@@ -404,6 +448,58 @@ struct opal_machine_check_event {
        } u;
 };
 
+/* FSP memory errors handling */
+enum OpalMemErr_Version {
+       OpalMemErr_V1 = 1,
+};
+
+enum OpalMemErrType {
+       OPAL_MEM_ERR_TYPE_RESILIENCE    = 0,
+       OPAL_MEM_ERR_TYPE_DYN_DALLOC,
+       OPAL_MEM_ERR_TYPE_SCRUB,
+};
+
+/* Memory Reilience error type */
+enum OpalMemErr_ResilErrType {
+       OPAL_MEM_RESILIENCE_CE          = 0,
+       OPAL_MEM_RESILIENCE_UE,
+       OPAL_MEM_RESILIENCE_UE_SCRUB,
+};
+
+/* Dynamic Memory Deallocation type */
+enum OpalMemErr_DynErrType {
+       OPAL_MEM_DYNAMIC_DEALLOC        = 0,
+};
+
+/* OpalMemoryErrorData->flags */
+#define OPAL_MEM_CORRECTED_ERROR       0x0001
+#define OPAL_MEM_THRESHOLD_EXCEEDED    0x0002
+#define OPAL_MEM_ACK_REQUIRED          0x8000
+
+struct OpalMemoryErrorData {
+       enum OpalMemErr_Version version:8;      /* 0x00 */
+       enum OpalMemErrType     type:8;         /* 0x01 */
+       uint16_t                flags;          /* 0x02 */
+       uint8_t                 reserved_1[4];  /* 0x04 */
+
+       union {
+               /* Memory Resilience corrected/uncorrected error info */
+               struct {
+                       enum OpalMemErr_ResilErrType resil_err_type:8;
+                       uint8_t         reserved_1[7];
+                       uint64_t        physical_address_start;
+                       uint64_t        physical_address_end;
+               } resilience;
+               /* Dynamic memory deallocation error info */
+               struct {
+                       enum OpalMemErr_DynErrType dyn_err_type:8;
+                       uint8_t         reserved_1[7];
+                       uint64_t        physical_address_start;
+                       uint64_t        physical_address_end;
+               } dyn_dealloc;
+       } u;
+};
+
 enum {
        OPAL_P7IOC_DIAG_TYPE_NONE       = 0,
        OPAL_P7IOC_DIAG_TYPE_RGC        = 1,
@@ -710,7 +806,7 @@ int64_t opal_pci_get_phb_diag_data(uint64_t phb_id, void *diag_buffer,
 int64_t opal_pci_get_phb_diag_data2(uint64_t phb_id, void *diag_buffer,
                                    uint64_t diag_buffer_len);
 int64_t opal_pci_fence_phb(uint64_t phb_id);
-int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope);
+int64_t opal_pci_reinit(uint64_t phb_id, uint64_t reinit_scope, uint64_t data);
 int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action);
 int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action);
 int64_t opal_get_epow_status(__be64 *status);
@@ -731,6 +827,10 @@ int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
 
+int64_t opal_get_msg(uint64_t buffer, size_t size);
+int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
+int64_t opal_sync_host_reboot(void);
+
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
 
@@ -744,6 +844,8 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
                                   int depth, void *data);
 
 extern int opal_notifier_register(struct notifier_block *nb);
+extern int opal_message_notifier_register(enum OpalMessageType msg_type,
+                                               struct notifier_block *nb);
 extern void opal_notifier_enable(void);
 extern void opal_notifier_disable(void);
 extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
index b6ea9e068c13dd483033a9f8aea2251d45084cac..9c5dbc3833fbc65976ba17e60eec04f234f8e631 100644 (file)
@@ -16,7 +16,6 @@
 
 #ifdef CONFIG_PPC64
 
-#include <linux/init.h>
 #include <asm/types.h>
 #include <asm/lppaca.h>
 #include <asm/mmu.h>
@@ -113,6 +112,10 @@ struct paca_struct {
        /* Keep pgd in the same cacheline as the start of extlb */
        pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */
        pgd_t *kernel_pgd;              /* Kernel PGD */
+
+       /* Shared by all threads of a core -- points to tcd of first thread */
+       struct tlb_core_data *tcd_ptr;
+
        /* We can have up to 3 levels of reentrancy in the TLB miss handler */
        u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
        u64 exmc[8];            /* used for machine checks */
@@ -123,6 +126,8 @@ struct paca_struct {
        void *mc_kstack;
        void *crit_kstack;
        void *dbg_kstack;
+
+       struct tlb_core_data tcd;
 #endif /* CONFIG_PPC_BOOK3E */
 
        mm_context_t context;
@@ -152,6 +157,15 @@ struct paca_struct {
         */
        struct opal_machine_check_event *opal_mc_evt;
 #endif
+#ifdef CONFIG_PPC_BOOK3S_64
+       /* Exclusive emergency stack pointer for machine check exception. */
+       void *mc_emergency_sp;
+       /*
+        * Flag to check whether we are in machine check early handler
+        * and already using emergency stack.
+        */
+       u16 in_mce;
+#endif
 
        /* Stuff for accurate time accounting */
        u64 user_time;                  /* accumulated usermode TB ticks */
index 4a191c47286748c65cf2e7eb8753239af4c3b5d5..d27960c89a7131cac93b8549e6326ce3b6a9ea5e 100644 (file)
@@ -558,5 +558,19 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
 #define __HAVE_ARCH_PMDP_INVALIDATE
 extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
                            pmd_t *pmdp);
+
+#define pmd_move_must_withdraw pmd_move_must_withdraw
+typedef struct spinlock spinlock_t;
+static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl,
+                                        spinlock_t *old_pmd_ptl)
+{
+       /*
+        * Archs like ppc64 use pgtable to store per pmd
+        * specific information. So when we switch the pmd,
+        * we should also withdraw and deposit the pgtable
+        */
+       return true;
+}
+
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */
index 7d6eacf249cf420a3e6d0a6f5ef108c76e663e80..b999ca3189858e05b75c855de000003f3cafcbe6 100644 (file)
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
+#include <linux/mmdebug.h>
 #include <asm/processor.h>             /* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
@@ -33,10 +34,73 @@ static inline int pte_dirty(pte_t pte)              { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)          { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_special(pte_t pte)       { return pte_val(pte) & _PAGE_SPECIAL; }
-static inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
 static inline int pte_none(pte_t pte)          { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
 static inline pgprot_t pte_pgprot(pte_t pte)   { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
 
+#ifdef CONFIG_NUMA_BALANCING
+
+static inline int pte_present(pte_t pte)
+{
+       return pte_val(pte) & (_PAGE_PRESENT | _PAGE_NUMA);
+}
+
+#define pte_numa pte_numa
+static inline int pte_numa(pte_t pte)
+{
+       return (pte_val(pte) &
+               (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA;
+}
+
+#define pte_mknonnuma pte_mknonnuma
+static inline pte_t pte_mknonnuma(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_NUMA;
+       pte_val(pte) |=  _PAGE_PRESENT | _PAGE_ACCESSED;
+       return pte;
+}
+
+#define pte_mknuma pte_mknuma
+static inline pte_t pte_mknuma(pte_t pte)
+{
+       /*
+        * We should not set _PAGE_NUMA on non present ptes. Also clear the
+        * present bit so that hash_page will return 1 and we collect this
+        * as numa fault.
+        */
+       if (pte_present(pte)) {
+               pte_val(pte) |= _PAGE_NUMA;
+               pte_val(pte) &= ~_PAGE_PRESENT;
+       } else
+               VM_BUG_ON(1);
+       return pte;
+}
+
+#define pmd_numa pmd_numa
+static inline int pmd_numa(pmd_t pmd)
+{
+       return pte_numa(pmd_pte(pmd));
+}
+
+#define pmd_mknonnuma pmd_mknonnuma
+static inline pmd_t pmd_mknonnuma(pmd_t pmd)
+{
+       return pte_pmd(pte_mknonnuma(pmd_pte(pmd)));
+}
+
+#define pmd_mknuma pmd_mknuma
+static inline pmd_t pmd_mknuma(pmd_t pmd)
+{
+       return pte_pmd(pte_mknuma(pmd_pte(pmd)));
+}
+
+# else
+
+static inline int pte_present(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_PRESENT;
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 /* Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  *
index f595b98079ee1ec75064640001998a407524ad59..6586a40a46ce161f9f654a57d0222db3bc06d611 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef _ASM_POWERPC_PPC_ASM_H
 #define _ASM_POWERPC_PPC_ASM_H
 
-#include <linux/init.h>
 #include <linux/stringify.h>
 #include <asm/asm-compat.h>
 #include <asm/processor.h>
@@ -295,6 +294,11 @@ n:
  *   you want to access various offsets within it).  On ppc32 this is
  *   identical to LOAD_REG_IMMEDIATE.
  *
+ * LOAD_REG_ADDR_PIC(rn, name)
+ *   Loads the address of label 'name' into register 'run'. Use this when
+ *   the kernel doesn't run at the linked or relocated address. Please
+ *   note that this macro will clobber the lr register.
+ *
  * LOAD_REG_ADDRBASE(rn, name)
  * ADDROFF(name)
  *   LOAD_REG_ADDRBASE loads part of the address of label 'name' into
@@ -305,6 +309,14 @@ n:
  *      LOAD_REG_ADDRBASE(rX, name)
  *      ld     rY,ADDROFF(name)(rX)
  */
+
+/* Be careful, this will clobber the lr register. */
+#define LOAD_REG_ADDR_PIC(reg, name)           \
+       bl      0f;                             \
+0:     mflr    reg;                            \
+       addis   reg,reg,(name - 0b)@ha;         \
+       addi    reg,reg,(name - 0b)@l;
+
 #ifdef __powerpc64__
 #define LOAD_REG_IMMEDIATE(reg,expr)           \
        lis     reg,(expr)@highest;             \
index fc14a38c7ccffae6c8f7c233e2710462ef621e7d..8ca20ac28dc2db097b8c7641e8b36b2c480ea71c 100644 (file)
@@ -256,6 +256,8 @@ struct thread_struct {
        unsigned long   evr[32];        /* upper 32-bits of SPE regs */
        u64             acc;            /* Accumulator */
        unsigned long   spefscr;        /* SPE & eFP status */
+       unsigned long   spefscr_last;   /* SPEFSCR value on last prctl
+                                          call or trap return */
        int             used_spe;       /* set if process has used spe */
 #endif /* CONFIG_SPE */
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
@@ -317,7 +319,9 @@ struct thread_struct {
        (_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
 
 #ifdef CONFIG_SPE
-#define SPEFSCR_INIT .spefscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE,
+#define SPEFSCR_INIT \
+       .spefscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE, \
+       .spefscr_last = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE,
 #else
 #define SPEFSCR_INIT
 #endif
@@ -373,6 +377,8 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
 extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
 extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
 
+extern void fp_enable(void);
+extern void vec_enable(void);
 extern void load_fp_state(struct thread_fp_state *fp);
 extern void store_fp_state(struct thread_fp_state *fp);
 extern void load_vr_state(struct thread_vr_state *vr);
index 678a7c1d9cb8ef32ea4da754fb72ac9f6d7f7f47..a1bc7e7584228a9e02215aeb2ee96e21194752c5 100644 (file)
@@ -21,7 +21,6 @@
 #if !defined(_ASM_POWERPC_PS3_H)
 #define _ASM_POWERPC_PS3_H
 
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/device.h>
 #include <asm/cell-pmu.h>
index 0419eeb53274c64891c87f1c573e712e6167d62b..2505d8eab15cb94da40aea90b9986aa853c0aecb 100644 (file)
@@ -19,7 +19,7 @@
 #define _PAGE_FILE             0x0002 /* (!present only) software: pte holds file offset */
 #define _PAGE_EXEC             0x0004 /* No execute on POWER4 and newer (we invert) */
 #define _PAGE_GUARDED          0x0008
-#define _PAGE_COHERENT         0x0010 /* M: enforce memory coherence (SMP systems) */
+/* We can derive Memory coherence from _PAGE_NO_CACHE */
 #define _PAGE_NO_CACHE         0x0020 /* I: cache inhibit */
 #define _PAGE_WRITETHRU                0x0040 /* W: cache write-through */
 #define _PAGE_DIRTY            0x0080 /* C: page changed */
 #define _PAGE_RW               0x0200 /* software: user write access allowed */
 #define _PAGE_BUSY             0x0800 /* software: PTE & hash are busy */
 
+/*
+ * Used for tracking numa faults
+ */
+#define _PAGE_NUMA     0x00000010 /* Gather numa placement stats */
+
+
 /* No separate kernel read-only */
 #define _PAGE_KERNEL_RW                (_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
 #define _PAGE_KERNEL_RO                 _PAGE_KERNEL_RW
index fa8388ed94c52e6086110bc382c7196ea32f1ad0..62b114e079cff69f5f9d48a8a5e6af99dc6b76a1 100644 (file)
 #define PVR_8560       0x80200000
 #define PVR_VER_E500V1 0x8020
 #define PVR_VER_E500V2 0x8021
+#define PVR_VER_E6500  0x8040
+
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * the PowerPC core. The various versions of these processors must be
index 2e31aacd8accaf4bf7742d7a708766a63e1f07d8..163c3b05a76e9d42f1a2067f510fd44cc7232dde 100644 (file)
 #define SPRN_IVOR39    0x1B1   /* Interrupt Vector Offset Register 39 */
 #define SPRN_IVOR40    0x1B2   /* Interrupt Vector Offset Register 40 */
 #define SPRN_IVOR41    0x1B3   /* Interrupt Vector Offset Register 41 */
+#define SPRN_IVOR42    0x1B4   /* Interrupt Vector Offset Register 42 */
 #define SPRN_GIVOR2    0x1B8   /* Guest IVOR2 */
 #define SPRN_GIVOR3    0x1B9   /* Guest IVOR3 */
 #define SPRN_GIVOR4    0x1BA   /* Guest IVOR4 */
 #define SPRN_L2CSR1    0x3FA   /* L2 Data Cache Control and Status Register 1 */
 #define SPRN_DCCR      0x3FA   /* Data Cache Cacheability Register */
 #define SPRN_ICCR      0x3FB   /* Instruction Cache Cacheability Register */
+#define SPRN_PWRMGTCR0 0x3FB   /* Power management control register 0 */
 #define SPRN_SVR       0x3FF   /* System Version Register */
 
 /*
 #define        CCR1_DPC        0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */
 #define        CCR1_TCS        0x00000080 /* Timer Clock Select */
 
+/* Bit definitions for PWRMGTCR0. */
+#define PWRMGTCR0_PW20_WAIT            (1 << 14) /* PW20 state enable bit */
+#define PWRMGTCR0_PW20_ENT_SHIFT       8
+#define PWRMGTCR0_PW20_ENT             0x3F00
+#define PWRMGTCR0_AV_IDLE_PD_EN                (1 << 22) /* Altivec idle enable */
+#define PWRMGTCR0_AV_IDLE_CNT_SHIFT    16
+#define PWRMGTCR0_AV_IDLE_CNT          0x3F0000
+
 /* Bit definitions for the MCSR. */
 #define MCSR_MCS       0x80000000 /* Machine Check Summary */
 #define MCSR_IB                0x40000000 /* Instruction PLB Error */
index f6e78d63fb6accd584e71cd5ebe7b26c5dae2916..35aa339410bdaef7d50decc76bda487677323e78 100644 (file)
@@ -30,8 +30,6 @@
 
 #define smp_mb__after_unlock_lock()    smp_mb()  /* Full ordering for lock. */
 
-#define arch_spin_is_locked(x)         ((x)->slock != 0)
-
 #ifdef CONFIG_PPC64
 /* use 0x800000yy when locked, where yy == CPU number */
 #ifdef __BIG_ENDIAN__
 #define SYNC_IO
 #endif
 
+static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.slock == 0;
+}
+
+static inline int arch_spin_is_locked(arch_spinlock_t *lock)
+{
+       return !arch_spin_value_unlocked(*lock);
+}
+
 /*
  * This returns the old value in the lock, so we succeeded
  * in getting the lock if the return value is 0.
index 9854c564ac525b02b9f81c363a1cd4477cd76d4b..b034ecdb7c74f219b311ac4ad1d58f1c56f3f929 100644 (file)
@@ -91,8 +91,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
                                           TIF_NEED_RESCHED */
 #define TIF_32BIT              4       /* 32 bit binary */
-#define TIF_PERFMON_WORK       5       /* work for pfm_handle_work() */
-#define TIF_PERFMON_CTXSW      6       /* perfmon needs ctxsw calls */
+#define TIF_RESTORE_TM         5       /* need to restore TM FP/VEC/VSX */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SINGLESTEP         8       /* singlestepping active */
 #define TIF_NOHZ               9       /* in adaptive nohz mode */
@@ -115,8 +114,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1<<TIF_32BIT)
-#define _TIF_PERFMON_WORK      (1<<TIF_PERFMON_WORK)
-#define _TIF_PERFMON_CTXSW     (1<<TIF_PERFMON_CTXSW)
+#define _TIF_RESTORE_TM                (1<<TIF_RESTORE_TM)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
@@ -132,7 +130,8 @@ static inline struct thread_info *current_thread_info(void)
                                 _TIF_NOHZ)
 
 #define _TIF_USER_WORK_MASK    (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
-                                _TIF_NOTIFY_RESUME | _TIF_UPROBE)
+                                _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+                                _TIF_RESTORE_TM)
 #define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR)
 
 /* Bits in local_flags */
index 9dfbc34bdbf5e7e86eda005d4e974f5fe3ebd12a..0c9f8b74dd9743ecd1977281c9365d6d1381fdf2 100644 (file)
@@ -15,6 +15,7 @@ extern void do_load_up_transact_altivec(struct thread_struct *thread);
 extern void tm_enable(void);
 extern void tm_reclaim(struct thread_struct *thread,
                       unsigned long orig_msr, uint8_t cause);
+extern void tm_reclaim_current(uint8_t cause);
 extern void tm_recheckpoint(struct thread_struct *thread,
                            unsigned long orig_msr);
 extern void tm_abort(uint8_t cause);
index 89e3ef2496ac72c4e03d17657833930de22f6b8e..d0b5fca6b0776fc8ef220483b91b1557c73a0835 100644 (file)
@@ -22,7 +22,15 @@ struct device_node;
 
 static inline int cpu_to_node(int cpu)
 {
-       return numa_cpu_lookup_table[cpu];
+       int nid;
+
+       nid = numa_cpu_lookup_table[cpu];
+
+       /*
+        * During early boot, the numa-cpu lookup table might not have been
+        * setup for all CPUs yet. In such cases, default to node 0.
+        */
+       return (nid < 0) ? 0 : nid;
 }
 
 #define parent_node(node)      (node)
index 68d0cc998b1baa5cee49b2a735f394354819492c..4f9b7ca0710fc5935de9d7963aeeedbb33159f90 100644 (file)
@@ -15,7 +15,6 @@
 #define _ASM_POWERPC_VIO_H
 #ifdef __KERNEL__
 
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
index 445cb6e39d5b0bb3058caaefe6af61f3f5ba2618..904d713366ff7643f19c198f447af4d056bf2de4 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_PPC64)           += setup_64.o sys_ppc32.o \
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 obj-$(CONFIG_PPC_BOOK3S_64)    += cpu_setup_ppc970.o cpu_setup_pa6t.o
 obj-$(CONFIG_PPC_BOOK3S_64)    += cpu_setup_power.o
+obj-$(CONFIG_PPC_BOOK3S_64)    += mce.o mce_power.o
 obj64-$(CONFIG_RELOCATABLE)    += reloc_64.o
 obj-$(CONFIG_PPC_BOOK3E_64)    += exceptions-64e.o idle_book3e.o
 obj-$(CONFIG_PPC_A2)           += cpu_setup_a2.o
index d3de01066f7dd786cd531614046b801ff7ebb18f..8d1d94d9c64927f97eb6d301c195a4d879c6aa5b 100644 (file)
@@ -203,6 +203,15 @@ int main(void)
        DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack));
        DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack));
        DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack));
+       DEFINE(PACA_TCD_PTR, offsetof(struct paca_struct, tcd_ptr));
+
+       DEFINE(TCD_ESEL_NEXT,
+               offsetof(struct tlb_core_data, esel_next));
+       DEFINE(TCD_ESEL_MAX,
+               offsetof(struct tlb_core_data, esel_max));
+       DEFINE(TCD_ESEL_FIRST,
+               offsetof(struct tlb_core_data, esel_first));
+       DEFINE(TCD_LOCK, offsetof(struct tlb_core_data, lock));
 #endif /* CONFIG_PPC_BOOK3E */
 
 #ifdef CONFIG_PPC_STD_MMU_64
@@ -232,6 +241,10 @@ int main(void)
        DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
 #endif /* CONFIG_PPC_STD_MMU_64 */
        DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
+#ifdef CONFIG_PPC_BOOK3S_64
+       DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp));
+       DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce));
+#endif
        DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
        DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
        DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
index 654932727873da2ed0073d70d77efb271713a28a..abfa011344d922ee345ef564d469b00fc382f6c9 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/list.h>
index bfb18c7290b7a13fccd520f064228b876430d807..cc2d8962e0906b78b4fe9f0c6e18a6991b66b60e 100644 (file)
@@ -53,11 +53,57 @@ _GLOBAL(__e500_dcache_setup)
        isync
        blr
 
+/*
+ * FIXME - we haven't yet done testing to determine a reasonable default
+ * value for PW20_WAIT_IDLE_BIT.
+ */
+#define PW20_WAIT_IDLE_BIT             50 /* 1ms, TB frequency is 41.66MHZ */
+_GLOBAL(setup_pw20_idle)
+       mfspr   r3, SPRN_PWRMGTCR0
+
+       /* Set PW20_WAIT bit, enable pw20 state*/
+       ori     r3, r3, PWRMGTCR0_PW20_WAIT
+       li      r11, PW20_WAIT_IDLE_BIT
+
+       /* Set Automatic PW20 Core Idle Count */
+       rlwimi  r3, r11, PWRMGTCR0_PW20_ENT_SHIFT, PWRMGTCR0_PW20_ENT
+
+       mtspr   SPRN_PWRMGTCR0, r3
+
+       blr
+
+/*
+ * FIXME - we haven't yet done testing to determine a reasonable default
+ * value for AV_WAIT_IDLE_BIT.
+ */
+#define AV_WAIT_IDLE_BIT               50 /* 1ms, TB frequency is 41.66MHZ */
+_GLOBAL(setup_altivec_idle)
+       mfspr   r3, SPRN_PWRMGTCR0
+
+       /* Enable Altivec Idle */
+       oris    r3, r3, PWRMGTCR0_AV_IDLE_PD_EN@h
+       li      r11, AV_WAIT_IDLE_BIT
+
+       /* Set Automatic AltiVec Idle Count */
+       rlwimi  r3, r11, PWRMGTCR0_AV_IDLE_CNT_SHIFT, PWRMGTCR0_AV_IDLE_CNT
+
+       mtspr   SPRN_PWRMGTCR0, r3
+
+       blr
+
 _GLOBAL(__setup_cpu_e6500)
        mflr    r6
 #ifdef CONFIG_PPC64
        bl      .setup_altivec_ivors
+       /* Touch IVOR42 only if the CPU supports E.HV category */
+       mfspr   r10,SPRN_MMUCFG
+       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
+       beq     1f
+       bl      .setup_lrat_ivor
+1:
 #endif
+       bl      setup_pw20_idle
+       bl      setup_altivec_idle
        bl      __setup_cpu_e5500
        mtlr    r6
        blr
@@ -119,6 +165,14 @@ _GLOBAL(__setup_cpu_e5500)
 _GLOBAL(__restore_cpu_e6500)
        mflr    r5
        bl      .setup_altivec_ivors
+       /* Touch IVOR42 only if the CPU supports E.HV category */
+       mfspr   r10,SPRN_MMUCFG
+       rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
+       beq     1f
+       bl      .setup_lrat_ivor
+1:
+       bl      .setup_pw20_idle
+       bl      .setup_altivec_idle
        bl      __restore_cpu_e5500
        mtlr    r5
        blr
index 18b5b9cf8e3730f4608ca6ff997810d5cc47df9a..37d1bb002aa97bbd3ea52b19304f746521e30bff 100644 (file)
@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7)
        mtspr   SPRN_LPID,r0
        mfspr   r3,SPRN_LPCR
        bl      __init_LPCR
-       bl      __init_TLB
+       bl      __init_tlb_power7
        mtlr    r11
        blr
 
@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7)
        mtspr   SPRN_LPID,r0
        mfspr   r3,SPRN_LPCR
        bl      __init_LPCR
-       bl      __init_TLB
+       bl      __init_tlb_power7
        mtlr    r11
        blr
 
@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8)
        oris    r3, r3, LPCR_AIL_3@h
        bl      __init_LPCR
        bl      __init_HFSCR
-       bl      __init_TLB
+       bl      __init_tlb_power8
        bl      __init_PMU_HV
        mtlr    r11
        blr
@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8)
        oris    r3, r3, LPCR_AIL_3@h
        bl      __init_LPCR
        bl      __init_HFSCR
-       bl      __init_TLB
+       bl      __init_tlb_power8
        bl      __init_PMU_HV
        mtlr    r11
        blr
@@ -134,15 +134,31 @@ __init_HFSCR:
        mtspr   SPRN_HFSCR,r3
        blr
 
-__init_TLB:
-       /*
-        * Clear the TLB using the "IS 3" form of tlbiel instruction
-        * (invalidate by congruence class). P7 has 128 CCs, P8 has 512
-        * so we just always do 512
-        */
+/*
+ * Clear the TLB using the specified IS form of tlbiel instruction
+ * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
+ *
+ * r3 = IS field
+ */
+__init_tlb_power7:
+       li      r3,0xc00        /* IS field = 0b11 */
+_GLOBAL(__flush_tlb_power7)
+       li      r6,128
+       mtctr   r6
+       mr      r7,r3           /* IS field */
+       ptesync
+2:     tlbiel  r7
+       addi    r7,r7,0x1000
+       bdnz    2b
+       ptesync
+1:     blr
+
+__init_tlb_power8:
+       li      r3,0xc00        /* IS field = 0b11 */
+_GLOBAL(__flush_tlb_power8)
        li      r6,512
        mtctr   r6
-       li      r7,0xc00        /* IS field = 0b11 */
+       mr      r7,r3           /* IS field */
        ptesync
 2:     tlbiel  r7
        addi    r7,r7,0x1000
index 597d954e58601b36f376953898faf9178b818239..6c8dd5da4de5ea0b8b88196b773d2e39fca1c732 100644 (file)
@@ -71,6 +71,10 @@ 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 __restore_cpu_a2(void);
+extern void __flush_tlb_power7(unsigned long inval_selector);
+extern void __flush_tlb_power8(unsigned long inval_selector);
+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 */
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -440,6 +444,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc64/ibm-compat-v1",
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7",
        },
        {       /* 2.07-compliant processor, i.e. Power8 "architected" mode */
@@ -456,6 +462,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc64/ibm-compat-v1",
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Power7 */
@@ -474,6 +482,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7",
        },
        {       /* Power7+ */
@@ -492,6 +502,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7+",
        },
        {       /* Power8E */
@@ -510,6 +522,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_INVALID,
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Power8 */
@@ -528,6 +542,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_INVALID,
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Cell Broadband Engine */
index fdcd8f551affe3225f8f7da271a4b630c99bd5f5..18d7c80ddeb98c0b9569ca039a630ac5bd5ba7c2 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/export.h>
 #include <linux/crash_dump.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/types.h>
 
index e4897523de41e45476bf002a64a3ab68d3e85e22..54d0116256f752247abd63d6619068c4d619d24d 100644 (file)
@@ -83,10 +83,10 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 0;
        }
 
-       if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) {
+       if (tbl->it_offset > (mask >> tbl->it_page_shift)) {
                dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
                dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
-                               mask, tbl->it_offset << IOMMU_PAGE_SHIFT);
+                               mask, tbl->it_offset << tbl->it_page_shift);
                return 0;
        } else
                return 1;
index 4bd687d5e7aa3f80e1b33912b5451bd34a3187b1..148db72a8c4371e69f79009683eb8b3baf12c3d6 100644 (file)
@@ -84,7 +84,7 @@
 #define EEH_MAX_FAILS  2100000
 
 /* Time to wait for a PCI slot to report status, in milliseconds */
-#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
+#define PCI_BUS_RESET_WAIT_MSEC (5*60*1000)
 
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
@@ -921,6 +921,13 @@ void eeh_add_device_late(struct pci_dev *dev)
                eeh_sysfs_remove_device(edev->pdev);
                edev->mode &= ~EEH_DEV_SYSFS;
 
+               /*
+                * We definitely should have the PCI device removed
+                * though it wasn't correctly. So we needn't call
+                * into error handler afterwards.
+                */
+               edev->mode |= EEH_DEV_NO_HANDLER;
+
                edev->pdev = NULL;
                dev->dev.archdata.edev = NULL;
        }
@@ -1023,6 +1030,14 @@ void eeh_remove_device(struct pci_dev *dev)
        else
                edev->mode |= EEH_DEV_DISCONNECTED;
 
+       /*
+        * We're removing from the PCI subsystem, that means
+        * the PCI device driver can't support EEH or not
+        * well. So we rely on hotplug completely to do recovery
+        * for the specific PCI device.
+        */
+       edev->mode |= EEH_DEV_NO_HANDLER;
+
        eeh_addr_cache_rmv_dev(dev);
        eeh_sysfs_remove_device(dev);
        edev->mode &= ~EEH_DEV_SYSFS;
index c17f90d0f73c62a2bcb12bd5445ab53a2ee935f3..7bb30dca4e192f55ca689319eefdc2a50646ff3a 100644 (file)
@@ -217,7 +217,8 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
        if (!driver) return NULL;
 
        if (!driver->err_handler ||
-           !driver->err_handler->mmio_enabled) {
+           !driver->err_handler->mmio_enabled ||
+           (edev->mode & EEH_DEV_NO_HANDLER)) {
                eeh_pcid_put(dev);
                return NULL;
        }
@@ -258,7 +259,8 @@ static void *eeh_report_reset(void *data, void *userdata)
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->slot_reset) {
+           !driver->err_handler->slot_reset ||
+           (edev->mode & EEH_DEV_NO_HANDLER)) {
                eeh_pcid_put(dev);
                return NULL;
        }
@@ -297,7 +299,9 @@ static void *eeh_report_resume(void *data, void *userdata)
        eeh_enable_irq(dev);
 
        if (!driver->err_handler ||
-           !driver->err_handler->resume) {
+           !driver->err_handler->resume ||
+           (edev->mode & EEH_DEV_NO_HANDLER)) {
+               edev->mode &= ~EEH_DEV_NO_HANDLER;
                eeh_pcid_put(dev);
                return NULL;
        }
@@ -476,7 +480,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 /* The longest amount of time to wait for a pci device
  * to come back on line, in seconds.
  */
-#define MAX_WAIT_FOR_RECOVERY 150
+#define MAX_WAIT_FOR_RECOVERY 300
 
 static void eeh_handle_normal_event(struct eeh_pe *pe)
 {
@@ -637,86 +641,92 @@ static void eeh_handle_special_event(void)
 {
        struct eeh_pe *pe, *phb_pe;
        struct pci_bus *bus;
-       struct pci_controller *hose, *tmp;
+       struct pci_controller *hose;
        unsigned long flags;
-       int rc = 0;
+       int rc;
 
-       /*
-        * The return value from next_error() has been classified as follows.
-        * It might be good to enumerate them. However, next_error() is only
-        * supported by PowerNV platform for now. So it would be fine to use
-        * integer directly:
-        *
-        * 4 - Dead IOC           3 - Dead PHB
-        * 2 - Fenced PHB         1 - Frozen PE
-        * 0 - No error found
-        *
-        */
-       rc = eeh_ops->next_error(&pe);
-       if (rc <= 0)
-               return;
 
-       switch (rc) {
-       case 4:
-               /* Mark all PHBs in dead state */
-               eeh_serialize_lock(&flags);
-               list_for_each_entry_safe(hose, tmp,
-                               &hose_list, list_node) {
-                       phb_pe = eeh_phb_pe_get(hose);
-                       if (!phb_pe) continue;
-
-                       eeh_pe_state_mark(phb_pe,
-                               EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+       do {
+               rc = eeh_ops->next_error(&pe);
+
+               switch (rc) {
+               case EEH_NEXT_ERR_DEAD_IOC:
+                       /* Mark all PHBs in dead state */
+                       eeh_serialize_lock(&flags);
+
+                       /* Purge all events */
+                       eeh_remove_event(NULL);
+
+                       list_for_each_entry(hose, &hose_list, list_node) {
+                               phb_pe = eeh_phb_pe_get(hose);
+                               if (!phb_pe) continue;
+
+                               eeh_pe_state_mark(phb_pe,
+                                       EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+                       }
+
+                       eeh_serialize_unlock(flags);
+
+                       break;
+               case EEH_NEXT_ERR_FROZEN_PE:
+               case EEH_NEXT_ERR_FENCED_PHB:
+               case EEH_NEXT_ERR_DEAD_PHB:
+                       /* Mark the PE in fenced state */
+                       eeh_serialize_lock(&flags);
+
+                       /* Purge all events of the PHB */
+                       eeh_remove_event(pe);
+
+                       if (rc == EEH_NEXT_ERR_DEAD_PHB)
+                               eeh_pe_state_mark(pe,
+                                       EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+                       else
+                               eeh_pe_state_mark(pe,
+                                       EEH_PE_ISOLATED | EEH_PE_RECOVERING);
+
+                       eeh_serialize_unlock(flags);
+
+                       break;
+               case EEH_NEXT_ERR_NONE:
+                       return;
+               default:
+                       pr_warn("%s: Invalid value %d from next_error()\n",
+                               __func__, rc);
+                       return;
                }
-               eeh_serialize_unlock(flags);
-
-               /* Purge all events */
-               eeh_remove_event(NULL);
-               break;
-       case 3:
-       case 2:
-       case 1:
-               /* Mark the PE in fenced state */
-               eeh_serialize_lock(&flags);
-               if (rc == 3)
-                       eeh_pe_state_mark(pe,
-                               EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
-               else
-                       eeh_pe_state_mark(pe,
-                               EEH_PE_ISOLATED | EEH_PE_RECOVERING);
-               eeh_serialize_unlock(flags);
-
-               /* Purge all events of the PHB */
-               eeh_remove_event(pe);
-               break;
-       default:
-               pr_err("%s: Invalid value %d from next_error()\n",
-                      __func__, rc);
-               return;
-       }
 
-       /*
-        * For fenced PHB and frozen PE, it's handled as normal
-        * event. We have to remove the affected PHBs for dead
-        * PHB and IOC
-        */
-       if (rc == 2 || rc == 1)
-               eeh_handle_normal_event(pe);
-       else {
-               pci_lock_rescan_remove();
-               list_for_each_entry_safe(hose, tmp,
-                       &hose_list, list_node) {
-                       phb_pe = eeh_phb_pe_get(hose);
-                       if (!phb_pe || !(phb_pe->state & EEH_PE_PHB_DEAD))
-                               continue;
-
-                       bus = eeh_pe_bus_get(phb_pe);
-                       /* Notify all devices that they're about to go down. */
-                       eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
-                       pcibios_remove_pci_devices(bus);
+               /*
+                * For fenced PHB and frozen PE, it's handled as normal
+                * event. We have to remove the affected PHBs for dead
+                * PHB and IOC
+                */
+               if (rc == EEH_NEXT_ERR_FROZEN_PE ||
+                   rc == EEH_NEXT_ERR_FENCED_PHB) {
+                       eeh_handle_normal_event(pe);
+               } else {
+                       pci_lock_rescan_remove();
+                       list_for_each_entry(hose, &hose_list, list_node) {
+                               phb_pe = eeh_phb_pe_get(hose);
+                               if (!phb_pe ||
+                                   !(phb_pe->state & EEH_PE_PHB_DEAD))
+                                       continue;
+
+                               /* Notify all devices to be down */
+                               bus = eeh_pe_bus_get(phb_pe);
+                               eeh_pe_dev_traverse(pe,
+                                       eeh_report_failure, NULL);
+                               pcibios_remove_pci_devices(bus);
+                       }
+                       pci_unlock_rescan_remove();
                }
-               pci_unlock_rescan_remove();
-       }
+
+               /*
+                * If we have detected dead IOC, we needn't proceed
+                * any more since all PHBs would have been removed
+                */
+               if (rc == EEH_NEXT_ERR_DEAD_IOC)
+                       break;
+       } while (rc != EEH_NEXT_ERR_NONE);
 }
 
 /**
index f9450537e335a350354dec35ff5fdf15876ef0a6..f0c353fa655a3a5a742e2de674851ab3ca88006a 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -737,6 +736,9 @@ static void *eeh_restore_one_device_bars(void *data, void *flag)
        else
                eeh_restore_device_bars(edev, dn);
 
+       if (eeh_ops->restore_config)
+               eeh_ops->restore_config(dn);
+
        return NULL;
 }
 
index bbfb0294b3544072ac22b2fcfee486620ae1479e..662c6dd98072e72beabcb1e894cc05999324da81 100644 (file)
@@ -664,8 +664,16 @@ _GLOBAL(ret_from_except_lite)
        bl      .restore_interrupts
        SCHEDULE_USER
        b       .ret_from_except_lite
-
-2:     bl      .save_nvgprs
+2:
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       andi.   r0,r4,_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM
+       bne     3f              /* only restore TM if nothing else to do */
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .restore_tm_state
+       b       restore
+3:
+#endif
+       bl      .save_nvgprs
        bl      .restore_interrupts
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_notify_resume
index e7751561fd1d6cb75f88a703edfb3581a0146d3a..063b65dd4f27a256106d34da4fda70c17859752f 100644 (file)
@@ -308,6 +308,7 @@ interrupt_base_book3e:                                      /* fake trap */
        EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
        EXCEPTION_STUB(0x300, hypercall)
        EXCEPTION_STUB(0x320, ehpriv)
+       EXCEPTION_STUB(0x340, lrat_error)
 
        .globl interrupt_end_book3e
 interrupt_end_book3e:
@@ -677,6 +678,17 @@ kernel_dbg_exc:
        bl      .unknown_exception
        b       .ret_from_except
 
+/* LRAT Error interrupt */
+       START_EXCEPTION(lrat_error);
+       NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
+                               PROLOG_ADDITION_NONE)
+       EXCEPTION_COMMON(0x340, PACA_EXGEN, INTS_KEEP)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .save_nvgprs
+       INTS_RESTORE_HARD
+       bl      .unknown_exception
+       b       .ret_from_except
+
 /*
  * An interrupt came in while soft-disabled; We mark paca->irq_happened
  * accordingly and if the interrupt is level sensitive, we hard disable
@@ -859,6 +871,7 @@ BAD_STACK_TRAMPOLINE(0x2e0)
 BAD_STACK_TRAMPOLINE(0x300)
 BAD_STACK_TRAMPOLINE(0x310)
 BAD_STACK_TRAMPOLINE(0x320)
+BAD_STACK_TRAMPOLINE(0x340)
 BAD_STACK_TRAMPOLINE(0x400)
 BAD_STACK_TRAMPOLINE(0x500)
 BAD_STACK_TRAMPOLINE(0x600)
@@ -1055,12 +1068,9 @@ skpinv:  addi    r6,r6,1                         /* Increment */
        mtspr   SPRN_MAS0,r3
        tlbre
        mfspr   r6,SPRN_MAS1
-       rlwinm  r6,r6,0,2,0     /* clear IPROT */
+       rlwinm  r6,r6,0,2,31    /* clear IPROT and VALID */
        mtspr   SPRN_MAS1,r6
        tlbwe
-
-       /* Invalidate TLB1 */
-       PPC_TLBILX_ALL(0,R0)
        sync
        isync
 
@@ -1114,12 +1124,9 @@ skpinv:  addi    r6,r6,1                         /* Increment */
        mtspr   SPRN_MAS0,r4
        tlbre
        mfspr   r5,SPRN_MAS1
-       rlwinm  r5,r5,0,2,0     /* clear IPROT */
+       rlwinm  r5,r5,0,2,31    /* clear IPROT and VALID */
        mtspr   SPRN_MAS1,r5
        tlbwe
-
-       /* Invalidate TLB1 */
-       PPC_TLBILX_ALL(0,R0)
        sync
        isync
 
@@ -1414,3 +1421,7 @@ _GLOBAL(setup_ehv_ivors)
        SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
        SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
        blr
+
+_GLOBAL(setup_lrat_ivor)
+       SET_IVOR(42, 0x340) /* LRAT Error */
+       blr
index 9f905e40922e41de4eb6f43421290944c5d08567..38d507306a111dc40f06028c90d5014e2fedd817 100644 (file)
@@ -155,8 +155,30 @@ machine_check_pSeries_1:
         */
        HMT_MEDIUM_PPR_DISCARD
        SET_SCRATCH0(r13)               /* save r13 */
+#ifdef CONFIG_PPC_P7_NAP
+BEGIN_FTR_SECTION
+       /* Running native on arch 2.06 or later, check if we are
+        * waking up from nap. We only handle no state loss and
+        * supervisor state loss. We do -not- handle hypervisor
+        * state loss at this time.
+        */
+       mfspr   r13,SPRN_SRR1
+       rlwinm. r13,r13,47-31,30,31
+       beq     9f
+
+       /* waking up from powersave (nap) state */
+       cmpwi   cr1,r13,2
+       /* Total loss of HV state is fatal. let's just stay stuck here */
+       bgt     cr1,.
+9:
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+#endif /* CONFIG_PPC_P7_NAP */
        EXCEPTION_PROLOG_0(PACA_EXMC)
+BEGIN_FTR_SECTION
+       b       machine_check_pSeries_early
+FTR_SECTION_ELSE
        b       machine_check_pSeries_0
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
 
        . = 0x300
        .globl data_access_pSeries
@@ -405,6 +427,64 @@ denorm_exception_hv:
 
        .align  7
        /* moved from 0x200 */
+machine_check_pSeries_early:
+BEGIN_FTR_SECTION
+       EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200)
+       /*
+        * Register contents:
+        * R13          = PACA
+        * R9           = CR
+        * Original R9 to R13 is saved on PACA_EXMC
+        *
+        * Switch to mc_emergency stack and handle re-entrancy (though we
+        * currently don't test for overflow). Save MCE registers srr1,
+        * srr0, dar and dsisr and then set ME=1
+        *
+        * We use paca->in_mce to check whether this is the first entry or
+        * nested machine check. We increment paca->in_mce to track nested
+        * machine checks.
+        *
+        * If this is the first entry then set stack pointer to
+        * paca->mc_emergency_sp, otherwise r1 is already pointing to
+        * stack frame on mc_emergency stack.
+        *
+        * NOTE: We are here with MSR_ME=0 (off), which means we risk a
+        * checkstop if we get another machine check exception before we do
+        * rfid with MSR_ME=1.
+        */
+       mr      r11,r1                  /* Save r1 */
+       lhz     r10,PACA_IN_MCE(r13)
+       cmpwi   r10,0                   /* Are we in nested machine check */
+       bne     0f                      /* Yes, we are. */
+       /* First machine check entry */
+       ld      r1,PACAMCEMERGSP(r13)   /* Use MC emergency stack */
+0:     subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame */
+       addi    r10,r10,1               /* increment paca->in_mce */
+       sth     r10,PACA_IN_MCE(r13)
+       std     r11,GPR1(r1)            /* Save r1 on the stack. */
+       std     r11,0(r1)               /* make stack chain pointer */
+       mfspr   r11,SPRN_SRR0           /* Save SRR0 */
+       std     r11,_NIP(r1)
+       mfspr   r11,SPRN_SRR1           /* Save SRR1 */
+       std     r11,_MSR(r1)
+       mfspr   r11,SPRN_DAR            /* Save DAR */
+       std     r11,_DAR(r1)
+       mfspr   r11,SPRN_DSISR          /* Save DSISR */
+       std     r11,_DSISR(r1)
+       std     r9,_CCR(r1)             /* Save CR in stackframe */
+       /* Save r9 through r13 from EXMC save area to stack frame. */
+       EXCEPTION_PROLOG_COMMON_2(PACA_EXMC)
+       mfmsr   r11                     /* get MSR value */
+       ori     r11,r11,MSR_ME          /* turn on ME bit */
+       ori     r11,r11,MSR_RI          /* turn on RI bit */
+       ld      r12,PACAKBASE(r13)      /* get high part of &label */
+       LOAD_HANDLER(r12, machine_check_handle_early)
+       mtspr   SPRN_SRR0,r12
+       mtspr   SPRN_SRR1,r11
+       rfid
+       b       .       /* prevent speculative execution */
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
 machine_check_pSeries:
        .globl machine_check_fwnmi
 machine_check_fwnmi:
@@ -688,30 +768,6 @@ kvmppc_skip_Hinterrupt:
 
        STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
 
-       /*
-        * Machine check is different because we use a different
-        * save area: PACA_EXMC instead of PACA_EXGEN.
-        */
-       .align  7
-       .globl machine_check_common
-machine_check_common:
-
-       mfspr   r10,SPRN_DAR
-       std     r10,PACA_EXGEN+EX_DAR(r13)
-       mfspr   r10,SPRN_DSISR
-       stw     r10,PACA_EXGEN+EX_DSISR(r13)
-       EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
-       FINISH_NAP
-       DISABLE_INTS
-       ld      r3,PACA_EXGEN+EX_DAR(r13)
-       lwz     r4,PACA_EXGEN+EX_DSISR(r13)
-       std     r3,_DAR(r1)
-       std     r4,_DSISR(r1)
-       bl      .save_nvgprs
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .machine_check_exception
-       b       .ret_from_except
-
        STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
        STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
        STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
@@ -1080,6 +1136,30 @@ unrecov_user_slb:
 #endif /* __DISABLED__ */
 
 
+       /*
+        * Machine check is different because we use a different
+        * save area: PACA_EXMC instead of PACA_EXGEN.
+        */
+       .align  7
+       .globl machine_check_common
+machine_check_common:
+
+       mfspr   r10,SPRN_DAR
+       std     r10,PACA_EXGEN+EX_DAR(r13)
+       mfspr   r10,SPRN_DSISR
+       stw     r10,PACA_EXGEN+EX_DSISR(r13)
+       EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+       FINISH_NAP
+       DISABLE_INTS
+       ld      r3,PACA_EXGEN+EX_DAR(r13)
+       lwz     r4,PACA_EXGEN+EX_DSISR(r13)
+       std     r3,_DAR(r1)
+       std     r4,_DSISR(r1)
+       bl      .save_nvgprs
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .machine_check_exception
+       b       .ret_from_except
+
        .align  7
        .globl alignment_common
 alignment_common:
@@ -1263,6 +1343,120 @@ _GLOBAL(opal_mc_secondary_handler)
 #endif /* CONFIG_PPC_POWERNV */
 
 
+#define MACHINE_CHECK_HANDLER_WINDUP                   \
+       /* Clear MSR_RI before setting SRR0 and SRR1. */\
+       li      r0,MSR_RI;                              \
+       mfmsr   r9;             /* get MSR value */     \
+       andc    r9,r9,r0;                               \
+       mtmsrd  r9,1;           /* Clear MSR_RI */      \
+       /* Move original SRR0 and SRR1 into the respective regs */      \
+       ld      r9,_MSR(r1);                            \
+       mtspr   SPRN_SRR1,r9;                           \
+       ld      r3,_NIP(r1);                            \
+       mtspr   SPRN_SRR0,r3;                           \
+       ld      r9,_CTR(r1);                            \
+       mtctr   r9;                                     \
+       ld      r9,_XER(r1);                            \
+       mtxer   r9;                                     \
+       ld      r9,_LINK(r1);                           \
+       mtlr    r9;                                     \
+       REST_GPR(0, r1);                                \
+       REST_8GPRS(2, r1);                              \
+       REST_GPR(10, r1);                               \
+       ld      r11,_CCR(r1);                           \
+       mtcr    r11;                                    \
+       /* Decrement paca->in_mce. */                   \
+       lhz     r12,PACA_IN_MCE(r13);                   \
+       subi    r12,r12,1;                              \
+       sth     r12,PACA_IN_MCE(r13);                   \
+       REST_GPR(11, r1);                               \
+       REST_2GPRS(12, r1);                             \
+       /* restore original r1. */                      \
+       ld      r1,GPR1(r1)
+
+       /*
+        * Handle machine check early in real mode. We come here with
+        * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
+        */
+       .align  7
+       .globl machine_check_handle_early
+machine_check_handle_early:
+       std     r0,GPR0(r1)     /* Save r0 */
+       EXCEPTION_PROLOG_COMMON_3(0x200)
+       bl      .save_nvgprs
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .machine_check_early
+       ld      r12,_MSR(r1)
+#ifdef CONFIG_PPC_P7_NAP
+       /*
+        * Check if thread was in power saving mode. We come here when any
+        * of the following is true:
+        * a. thread wasn't in power saving mode
+        * b. thread was in power saving mode with no state loss or
+        *    supervisor state loss
+        *
+        * Go back to nap again if (b) is true.
+        */
+       rlwinm. r11,r12,47-31,30,31     /* Was it in power saving mode? */
+       beq     4f                      /* No, it wasn;t */
+       /* Thread was in power saving mode. Go back to nap again. */
+       cmpwi   r11,2
+       bne     3f
+       /* Supervisor state loss */
+       li      r0,1
+       stb     r0,PACA_NAPSTATELOST(r13)
+3:     bl      .machine_check_queue_event
+       MACHINE_CHECK_HANDLER_WINDUP
+       GET_PACA(r13)
+       ld      r1,PACAR1(r13)
+       b       .power7_enter_nap_mode
+4:
+#endif
+       /*
+        * Check if we are coming from hypervisor userspace. If yes then we
+        * continue in host kernel in V mode to deliver the MC event.
+        */
+       rldicl. r11,r12,4,63            /* See if MC hit while in HV mode. */
+       beq     5f
+       andi.   r11,r12,MSR_PR          /* See if coming from user. */
+       bne     9f                      /* continue in V mode if we are. */
+
+5:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+       /*
+        * We are coming from kernel context. Check if we are coming from
+        * guest. if yes, then we can continue. We will fall through
+        * do_kvm_200->kvmppc_interrupt to deliver the MC event to guest.
+        */
+       lbz     r11,HSTATE_IN_GUEST(r13)
+       cmpwi   r11,0                   /* Check if coming from guest */
+       bne     9f                      /* continue if we are. */
+#endif
+       /*
+        * At this point we are not sure about what context we come from.
+        * Queue up the MCE event and return from the interrupt.
+        * But before that, check if this is an un-recoverable exception.
+        * If yes, then stay on emergency stack and panic.
+        */
+       andi.   r11,r12,MSR_RI
+       bne     2f
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .unrecoverable_exception
+       b       1b
+2:
+       /*
+        * Return from MC interrupt.
+        * Queue up the MCE event so that we can log it later, while
+        * returning from kernel or opal call.
+        */
+       bl      .machine_check_queue_event
+       MACHINE_CHECK_HANDLER_WINDUP
+       rfid
+9:
+       /* Deliver the machine check to host kernel in V mode. */
+       MACHINE_CHECK_HANDLER_WINDUP
+       b       machine_check_pSeries
+
 /*
  * r13 points to the PACA, r9 contains the saved CR,
  * r12 contain the saved SRR1, SRR0 is still ready for return
index f7f5b8bed68f59500964f75ff9f7d9b2aa211d0c..9ad236e5d2c9d072540f1167107076e883af9ac3 100644 (file)
@@ -80,6 +80,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        blr
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
+/*
+ * Enable use of the FPU, and VSX if possible, for the caller.
+ */
+_GLOBAL(fp_enable)
+       mfmsr   r3
+       ori     r3,r3,MSR_FP
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+       oris    r3,r3,MSR_VSX@h
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+       SYNC
+       MTMSRD(r3)
+       isync                   /* (not necessary for arch 2.02 and later) */
+       blr
+
 /*
  * Load state from memory into FP registers including FPSCR.
  * Assumes the caller has enabled FP in the MSR.
index a92c79be2728e97bb54433e6c7d49b5917a2dcde..f22e7e44fbf321e9df8140ef55cb73e0b72142b0 100644 (file)
@@ -176,6 +176,8 @@ skpinv:     addi    r6,r6,1                         /* Increment */
 /* 7. Jump to KERNELBASE mapping */
        lis     r6,(KERNELBASE & ~0xfff)@h
        ori     r6,r6,(KERNELBASE & ~0xfff)@l
+       rlwinm  r7,r25,0,0x03ffffff
+       add     r6,r7,r6
 
 #elif defined(ENTRY_MAPPING_KEXEC_SETUP)
 /*
index 4f0946de2d5c917540f6f51a50c13640011fea8c..b7363bd42452848169e3fa5bc58721c1aeb3b08a 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/threads.h>
+#include <linux/init.h>
 #include <asm/reg.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
index f45726a1d963ddae9591fa1210736f124ac6a5b4..b497188a94a1e2f67b71460189f9f225f7f5e1a3 100644 (file)
@@ -65,29 +65,78 @@ _ENTRY(_start);
        nop
 
        /* Translate device tree address to physical, save in r30/r31 */
-       mfmsr   r16
-       mfspr   r17,SPRN_PID
-       rlwinm  r17,r17,16,0x3fff0000   /* turn PID into MAS6[SPID] */
-       rlwimi  r17,r16,28,0x00000001   /* turn MSR[DS] into MAS6[SAS] */
-       mtspr   SPRN_MAS6,r17
-
-       tlbsx   0,r3                    /* must succeed */
-
-       mfspr   r16,SPRN_MAS1
-       mfspr   r20,SPRN_MAS3
-       rlwinm  r17,r16,25,0x1f         /* r17 = log2(page size) */
-       li      r18,1024
-       slw     r18,r18,r17             /* r18 = page size */
-       addi    r18,r18,-1
-       and     r19,r3,r18              /* r19 = page offset */
-       andc    r31,r20,r18             /* r31 = page base */
-       or      r31,r31,r19             /* r31 = devtree phys addr */
-       mfspr   r30,SPRN_MAS7
+       bl      get_phys_addr
+       mr      r30,r3
+       mr      r31,r4
 
        li      r25,0                   /* phys kernel start (low) */
        li      r24,0                   /* CPU number */
        li      r23,0                   /* phys kernel start (high) */
 
+#ifdef CONFIG_RELOCATABLE
+       LOAD_REG_ADDR_PIC(r3, _stext)   /* Get our current runtime base */
+
+       /* Translate _stext address to physical, save in r23/r25 */
+       bl      get_phys_addr
+       mr      r23,r3
+       mr      r25,r4
+
+       bl      0f
+0:     mflr    r8
+       addis   r3,r8,(is_second_reloc - 0b)@ha
+       lwz     r19,(is_second_reloc - 0b)@l(r3)
+
+       /* Check if this is the second relocation. */
+       cmpwi   r19,1
+       bne     1f
+
+       /*
+        * For the second relocation, we already get the real memstart_addr
+        * from device tree. So we will map PAGE_OFFSET to memstart_addr,
+        * then the virtual address of start kernel should be:
+        *          PAGE_OFFSET + (kernstart_addr - memstart_addr)
+        * Since the offset between kernstart_addr and memstart_addr should
+        * never be beyond 1G, so we can just use the lower 32bit of them
+        * for the calculation.
+        */
+       lis     r3,PAGE_OFFSET@h
+
+       addis   r4,r8,(kernstart_addr - 0b)@ha
+       addi    r4,r4,(kernstart_addr - 0b)@l
+       lwz     r5,4(r4)
+
+       addis   r6,r8,(memstart_addr - 0b)@ha
+       addi    r6,r6,(memstart_addr - 0b)@l
+       lwz     r7,4(r6)
+
+       subf    r5,r7,r5
+       add     r3,r3,r5
+       b       2f
+
+1:
+       /*
+        * We have the runtime (virutal) address of our base.
+        * We calculate our shift of offset from a 64M page.
+        * We could map the 64M page we belong to at PAGE_OFFSET and
+        * get going from there.
+        */
+       lis     r4,KERNELBASE@h
+       ori     r4,r4,KERNELBASE@l
+       rlwinm  r6,r25,0,0x3ffffff              /* r6 = PHYS_START % 64M */
+       rlwinm  r5,r4,0,0x3ffffff               /* r5 = KERNELBASE % 64M */
+       subf    r3,r5,r6                        /* r3 = r6 - r5 */
+       add     r3,r4,r3                        /* Required Virtual Address */
+
+2:     bl      relocate
+
+       /*
+        * For the second relocation, we already set the right tlb entries
+        * for the kernel space, so skip the code in fsl_booke_entry_mapping.S
+       */
+       cmpwi   r19,1
+       beq     set_ivor
+#endif
+
 /* We try to not make any assumptions about how the boot loader
  * setup or used the TLBs.  We invalidate all mappings from the
  * boot loader and load a single entry in TLB1[0] to map the
@@ -113,6 +162,7 @@ _ENTRY(__early_start)
 #include "fsl_booke_entry_mapping.S"
 #undef ENTRY_MAPPING_BOOT_SETUP
 
+set_ivor:
        /* Establish the interrupt vector offsets */
        SET_IVOR(0,  CriticalInput);
        SET_IVOR(1,  MachineCheck);
@@ -166,8 +216,7 @@ _ENTRY(__early_start)
        /* Check to see if we're the second processor, and jump
         * to the secondary_start code if so
         */
-       lis     r24, boot_cpuid@h
-       ori     r24, r24, boot_cpuid@l
+       LOAD_REG_ADDR_PIC(r24, boot_cpuid)
        lwz     r24, 0(r24)
        cmpwi   r24, -1
        mfspr   r24,SPRN_PIR
@@ -197,6 +246,18 @@ _ENTRY(__early_start)
 
        bl      early_init
 
+#ifdef CONFIG_RELOCATABLE
+       mr      r3,r30
+       mr      r4,r31
+#ifdef CONFIG_PHYS_64BIT
+       mr      r5,r23
+       mr      r6,r25
+#else
+       mr      r5,r25
+#endif
+       bl      relocate_init
+#endif
+
 #ifdef CONFIG_DYNAMIC_MEMSTART
        lis     r3,kernstart_addr@ha
        la      r3,kernstart_addr@l(r3)
@@ -855,6 +916,33 @@ KernelSPE:
 
 #endif /* CONFIG_SPE */
 
+/*
+ * Translate the effec addr in r3 to phys addr. The phys addr will be put
+ * into r3(higher 32bit) and r4(lower 32bit)
+ */
+get_phys_addr:
+       mfmsr   r8
+       mfspr   r9,SPRN_PID
+       rlwinm  r9,r9,16,0x3fff0000     /* turn PID into MAS6[SPID] */
+       rlwimi  r9,r8,28,0x00000001     /* turn MSR[DS] into MAS6[SAS] */
+       mtspr   SPRN_MAS6,r9
+
+       tlbsx   0,r3                    /* must succeed */
+
+       mfspr   r8,SPRN_MAS1
+       mfspr   r12,SPRN_MAS3
+       rlwinm  r9,r8,25,0x1f           /* r9 = log2(page size) */
+       li      r10,1024
+       slw     r10,r10,r9              /* r10 = page size */
+       addi    r10,r10,-1
+       and     r11,r3,r10              /* r11 = page offset */
+       andc    r4,r12,r10              /* r4 = page base */
+       or      r4,r4,r11               /* r4 = devtree phys addr */
+#ifdef CONFIG_PHYS_64BIT
+       mfspr   r3,SPRN_MAS7
+#endif
+       blr
+
 /*
  * Global functions
  */
@@ -1057,24 +1145,36 @@ _GLOBAL(__flush_disable_L1)
 /* When we get here, r24 needs to hold the CPU # */
        .globl __secondary_start
 __secondary_start:
-       lis     r3,__secondary_hold_acknowledge@h
-       ori     r3,r3,__secondary_hold_acknowledge@l
-       stw     r24,0(r3)
-
-       li      r3,0
-       mr      r4,r24          /* Why? */
-       bl      call_setup_cpu
-
-       lis     r3,tlbcam_index@ha
-       lwz     r3,tlbcam_index@l(r3)
+       LOAD_REG_ADDR_PIC(r3, tlbcam_index)
+       lwz     r3,0(r3)
        mtctr   r3
        li      r26,0           /* r26 safe? */
 
+       bl      switch_to_as1
+       mr      r27,r3          /* tlb entry */
        /* Load each CAM entry */
 1:     mr      r3,r26
        bl      loadcam_entry
        addi    r26,r26,1
        bdnz    1b
+       mr      r3,r27          /* tlb entry */
+       LOAD_REG_ADDR_PIC(r4, memstart_addr)
+       lwz     r4,0(r4)
+       mr      r5,r25          /* phys kernel start */
+       rlwinm  r5,r5,0,~0x3ffffff      /* aligned 64M */
+       subf    r4,r5,r4        /* memstart_addr - phys kernel start */
+       li      r5,0            /* no device tree */
+       li      r6,0            /* not boot cpu */
+       bl      restore_to_as0
+
+
+       lis     r3,__secondary_hold_acknowledge@h
+       ori     r3,r3,__secondary_hold_acknowledge@l
+       stw     r24,0(r3)
+
+       li      r3,0
+       mr      r4,r24          /* Why? */
+       bl      call_setup_cpu
 
        /* get current_thread_info and current */
        lis     r1,secondary_ti@ha
@@ -1110,6 +1210,112 @@ __secondary_hold_acknowledge:
        .long   -1
 #endif
 
+/*
+ * Create a tlb entry with the same effective and physical address as
+ * the tlb entry used by the current running code. But set the TS to 1.
+ * Then switch to the address space 1. It will return with the r3 set to
+ * the ESEL of the new created tlb.
+ */
+_GLOBAL(switch_to_as1)
+       mflr    r5
+
+       /* Find a entry not used */
+       mfspr   r3,SPRN_TLB1CFG
+       andi.   r3,r3,0xfff
+       mfspr   r4,SPRN_PID
+       rlwinm  r4,r4,16,0x3fff0000     /* turn PID into MAS6[SPID] */
+       mtspr   SPRN_MAS6,r4
+1:     lis     r4,0x1000               /* Set MAS0(TLBSEL) = 1 */
+       addi    r3,r3,-1
+       rlwimi  r4,r3,16,4,15           /* Setup MAS0 = TLBSEL | ESEL(r3) */
+       mtspr   SPRN_MAS0,r4
+       tlbre
+       mfspr   r4,SPRN_MAS1
+       andis.  r4,r4,MAS1_VALID@h
+       bne     1b
+
+       /* Get the tlb entry used by the current running code */
+       bl      0f
+0:     mflr    r4
+       tlbsx   0,r4
+
+       mfspr   r4,SPRN_MAS1
+       ori     r4,r4,MAS1_TS           /* Set the TS = 1 */
+       mtspr   SPRN_MAS1,r4
+
+       mfspr   r4,SPRN_MAS0
+       rlwinm  r4,r4,0,~MAS0_ESEL_MASK
+       rlwimi  r4,r3,16,4,15           /* Setup MAS0 = TLBSEL | ESEL(r3) */
+       mtspr   SPRN_MAS0,r4
+       tlbwe
+       isync
+       sync
+
+       mfmsr   r4
+       ori     r4,r4,MSR_IS | MSR_DS
+       mtspr   SPRN_SRR0,r5
+       mtspr   SPRN_SRR1,r4
+       sync
+       rfi
+
+/*
+ * Restore to the address space 0 and also invalidate the tlb entry created
+ * by switch_to_as1.
+ * r3 - the tlb entry which should be invalidated
+ * r4 - __pa(PAGE_OFFSET in AS1) - __pa(PAGE_OFFSET in AS0)
+ * r5 - device tree virtual address. If r4 is 0, r5 is ignored.
+ * r6 - boot cpu
+*/
+_GLOBAL(restore_to_as0)
+       mflr    r0
+
+       bl      0f
+0:     mflr    r9
+       addi    r9,r9,1f - 0b
+
+       /*
+        * We may map the PAGE_OFFSET in AS0 to a different physical address,
+        * so we need calculate the right jump and device tree address based
+        * on the offset passed by r4.
+        */
+       add     r9,r9,r4
+       add     r5,r5,r4
+       add     r0,r0,r4
+
+2:     mfmsr   r7
+       li      r8,(MSR_IS | MSR_DS)
+       andc    r7,r7,r8
+
+       mtspr   SPRN_SRR0,r9
+       mtspr   SPRN_SRR1,r7
+       sync
+       rfi
+
+       /* Invalidate the temporary tlb entry for AS1 */
+1:     lis     r9,0x1000               /* Set MAS0(TLBSEL) = 1 */
+       rlwimi  r9,r3,16,4,15           /* Setup MAS0 = TLBSEL | ESEL(r3) */
+       mtspr   SPRN_MAS0,r9
+       tlbre
+       mfspr   r9,SPRN_MAS1
+       rlwinm  r9,r9,0,2,31            /* Clear MAS1 Valid and IPPROT */
+       mtspr   SPRN_MAS1,r9
+       tlbwe
+       isync
+
+       cmpwi   r4,0
+       cmpwi   cr1,r6,0
+       cror    eq,4*cr1+eq,eq
+       bne     3f                      /* offset != 0 && is_boot_cpu */
+       mtlr    r0
+       blr
+
+       /*
+        * The PAGE_OFFSET will map to a different physical address,
+        * jump to _start to do another relocation again.
+       */
+3:     mr      r3,r5
+       bl      _start
+
 /*
  * We put a few things here that have to be page-aligned. This stuff
  * goes at the beginning of the data segment, which is page-aligned.
index f0b47d1a6b0ebd92dddd3ed49275e40a361c72ea..b0a1792279bbf38e1726a86b6d8cd504c11e15ca 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/percpu.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 
 #include <asm/hw_breakpoint.h>
index 847e40e62fcee8420046e153e5da9354bc80a40e..3fdef0f0c67fa959e631a4ccee2d3a330001fa44 100644 (file)
@@ -84,6 +84,7 @@ _GLOBAL(power7_nap)
        std     r9,_MSR(r1)
        std     r1,PACAR1(r13)
 
+_GLOBAL(power7_enter_nap_mode)
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
        /* Tell KVM we're napping */
        li      r4,KVM_HWTHREAD_IN_NAP
index 97a3715ac8bd83dadfb23555a398260de144ab9e..b82227e7e21bbba3cb22456c0c9248bb65bbd462 100644 (file)
@@ -3,7 +3,6 @@
  *
  * (C) Copyright 2004 Linus Torvalds
  */
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
 #include <linux/export.h>
index 572bb5b95f35d815f6f24fe7b59a67bf420fbe2b..d773dd440a45a32560fed0176120709ff5ea860d 100644 (file)
@@ -251,14 +251,13 @@ again:
 
        if (dev)
                boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
-                                     1 << IOMMU_PAGE_SHIFT);
+                                     1 << tbl->it_page_shift);
        else
-               boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
+               boundary_size = ALIGN(1UL << 32, 1 << tbl->it_page_shift);
        /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
 
-       n = iommu_area_alloc(tbl->it_map, limit, start, npages,
-                            tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
-                            align_mask);
+       n = iommu_area_alloc(tbl->it_map, limit, start, npages, tbl->it_offset,
+                            boundary_size >> tbl->it_page_shift, align_mask);
        if (n == -1) {
                if (likely(pass == 0)) {
                        /* First try the pool from the start */
@@ -320,12 +319,12 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
                return DMA_ERROR_CODE;
 
        entry += tbl->it_offset;        /* Offset into real TCE table */
-       ret = entry << IOMMU_PAGE_SHIFT;        /* Set the return dma address */
+       ret = entry << tbl->it_page_shift;      /* Set the return dma address */
 
        /* Put the TCEs in the HW table */
        build_fail = ppc_md.tce_build(tbl, entry, npages,
-                                     (unsigned long)page & IOMMU_PAGE_MASK,
-                                     direction, attrs);
+                                     (unsigned long)page &
+                                     IOMMU_PAGE_MASK(tbl), direction, attrs);
 
        /* ppc_md.tce_build() only returns non-zero for transient errors.
         * Clean up the table bitmap in this case and return
@@ -352,7 +351,7 @@ static bool iommu_free_check(struct iommu_table *tbl, dma_addr_t dma_addr,
 {
        unsigned long entry, free_entry;
 
-       entry = dma_addr >> IOMMU_PAGE_SHIFT;
+       entry = dma_addr >> tbl->it_page_shift;
        free_entry = entry - tbl->it_offset;
 
        if (((free_entry + npages) > tbl->it_size) ||
@@ -401,7 +400,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
        unsigned long flags;
        struct iommu_pool *pool;
 
-       entry = dma_addr >> IOMMU_PAGE_SHIFT;
+       entry = dma_addr >> tbl->it_page_shift;
        free_entry = entry - tbl->it_offset;
 
        pool = get_pool(tbl, free_entry);
@@ -468,13 +467,13 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                }
                /* Allocate iommu entries for that segment */
                vaddr = (unsigned long) sg_virt(s);
-               npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE);
+               npages = iommu_num_pages(vaddr, slen, IOMMU_PAGE_SIZE(tbl));
                align = 0;
-               if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
+               if (tbl->it_page_shift < PAGE_SHIFT && slen >= PAGE_SIZE &&
                    (vaddr & ~PAGE_MASK) == 0)
-                       align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
+                       align = PAGE_SHIFT - tbl->it_page_shift;
                entry = iommu_range_alloc(dev, tbl, npages, &handle,
-                                         mask >> IOMMU_PAGE_SHIFT, align);
+                                         mask >> tbl->it_page_shift, align);
 
                DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
 
@@ -489,16 +488,16 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
                /* Convert entry to a dma_addr_t */
                entry += tbl->it_offset;
-               dma_addr = entry << IOMMU_PAGE_SHIFT;
-               dma_addr |= (s->offset & ~IOMMU_PAGE_MASK);
+               dma_addr = entry << tbl->it_page_shift;
+               dma_addr |= (s->offset & ~IOMMU_PAGE_MASK(tbl));
 
                DBG("  - %lu pages, entry: %lx, dma_addr: %lx\n",
                            npages, entry, dma_addr);
 
                /* Insert into HW table */
                build_fail = ppc_md.tce_build(tbl, entry, npages,
-                                             vaddr & IOMMU_PAGE_MASK,
-                                             direction, attrs);
+                                             vaddr & IOMMU_PAGE_MASK(tbl),
+                                             direction, attrs);
                if(unlikely(build_fail))
                        goto failure;
 
@@ -559,9 +558,9 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                if (s->dma_length != 0) {
                        unsigned long vaddr, npages;
 
-                       vaddr = s->dma_address & IOMMU_PAGE_MASK;
+                       vaddr = s->dma_address & IOMMU_PAGE_MASK(tbl);
                        npages = iommu_num_pages(s->dma_address, s->dma_length,
-                                                IOMMU_PAGE_SIZE);
+                                                IOMMU_PAGE_SIZE(tbl));
                        __iommu_free(tbl, vaddr, npages);
                        s->dma_address = DMA_ERROR_CODE;
                        s->dma_length = 0;
@@ -592,7 +591,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                if (sg->dma_length == 0)
                        break;
                npages = iommu_num_pages(dma_handle, sg->dma_length,
-                                        IOMMU_PAGE_SIZE);
+                                        IOMMU_PAGE_SIZE(tbl));
                __iommu_free(tbl, dma_handle, npages);
                sg = sg_next(sg);
        }
@@ -676,7 +675,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
                set_bit(0, tbl->it_map);
 
        /* We only split the IOMMU table if we have 1GB or more of space */
-       if ((tbl->it_size << IOMMU_PAGE_SHIFT) >= (1UL * 1024 * 1024 * 1024))
+       if ((tbl->it_size << tbl->it_page_shift) >= (1UL * 1024 * 1024 * 1024))
                tbl->nr_pools = IOMMU_NR_POOLS;
        else
                tbl->nr_pools = 1;
@@ -768,16 +767,16 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
 
        vaddr = page_address(page) + offset;
        uaddr = (unsigned long)vaddr;
-       npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE);
+       npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl));
 
        if (tbl) {
                align = 0;
-               if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && size >= PAGE_SIZE &&
+               if (tbl->it_page_shift < PAGE_SHIFT && size >= PAGE_SIZE &&
                    ((unsigned long)vaddr & ~PAGE_MASK) == 0)
-                       align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
+                       align = PAGE_SHIFT - tbl->it_page_shift;
 
                dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
-                                        mask >> IOMMU_PAGE_SHIFT, align,
+                                        mask >> tbl->it_page_shift, align,
                                         attrs);
                if (dma_handle == DMA_ERROR_CODE) {
                        if (printk_ratelimit())  {
@@ -786,7 +785,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
                                         npages);
                        }
                } else
-                       dma_handle |= (uaddr & ~IOMMU_PAGE_MASK);
+                       dma_handle |= (uaddr & ~IOMMU_PAGE_MASK(tbl));
        }
 
        return dma_handle;
@@ -801,7 +800,8 @@ void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
        BUG_ON(direction == DMA_NONE);
 
        if (tbl) {
-               npages = iommu_num_pages(dma_handle, size, IOMMU_PAGE_SIZE);
+               npages = iommu_num_pages(dma_handle, size,
+                                        IOMMU_PAGE_SIZE(tbl));
                iommu_free(tbl, dma_handle, npages);
        }
 }
@@ -845,10 +845,10 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
        memset(ret, 0, size);
 
        /* Set up tces to cover the allocated range */
-       nio_pages = size >> IOMMU_PAGE_SHIFT;
-       io_order = get_iommu_order(size);
+       nio_pages = size >> tbl->it_page_shift;
+       io_order = get_iommu_order(size, tbl);
        mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
-                             mask >> IOMMU_PAGE_SHIFT, io_order, NULL);
+                             mask >> tbl->it_page_shift, io_order, NULL);
        if (mapping == DMA_ERROR_CODE) {
                free_pages((unsigned long)ret, order);
                return NULL;
@@ -864,7 +864,7 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size,
                unsigned int nio_pages;
 
                size = PAGE_ALIGN(size);
-               nio_pages = size >> IOMMU_PAGE_SHIFT;
+               nio_pages = size >> tbl->it_page_shift;
                iommu_free(tbl, dma_handle, nio_pages);
                size = PAGE_ALIGN(size);
                free_pages((unsigned long)vaddr, get_order(size));
@@ -935,10 +935,10 @@ int iommu_tce_clear_param_check(struct iommu_table *tbl,
        if (tce_value)
                return -EINVAL;
 
-       if (ioba & ~IOMMU_PAGE_MASK)
+       if (ioba & ~IOMMU_PAGE_MASK(tbl))
                return -EINVAL;
 
-       ioba >>= IOMMU_PAGE_SHIFT;
+       ioba >>= tbl->it_page_shift;
        if (ioba < tbl->it_offset)
                return -EINVAL;
 
@@ -955,13 +955,13 @@ int iommu_tce_put_param_check(struct iommu_table *tbl,
        if (!(tce & (TCE_PCI_WRITE | TCE_PCI_READ)))
                return -EINVAL;
 
-       if (tce & ~(IOMMU_PAGE_MASK | TCE_PCI_WRITE | TCE_PCI_READ))
+       if (tce & ~(IOMMU_PAGE_MASK(tbl) | TCE_PCI_WRITE | TCE_PCI_READ))
                return -EINVAL;
 
-       if (ioba & ~IOMMU_PAGE_MASK)
+       if (ioba & ~IOMMU_PAGE_MASK(tbl))
                return -EINVAL;
 
-       ioba >>= IOMMU_PAGE_SHIFT;
+       ioba >>= tbl->it_page_shift;
        if (ioba < tbl->it_offset)
                return -EINVAL;
 
@@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *tbl, unsigned long entry,
 
        /* if (unlikely(ret))
                pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n",
-                               __func__, hwaddr, entry << IOMMU_PAGE_SHIFT,
+                       __func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl),
                                hwaddr, ret); */
 
        return ret;
@@ -1049,14 +1049,14 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry,
 {
        int ret;
        struct page *page = NULL;
-       unsigned long hwaddr, offset = tce & IOMMU_PAGE_MASK & ~PAGE_MASK;
+       unsigned long hwaddr, offset = tce & IOMMU_PAGE_MASK(tbl) & ~PAGE_MASK;
        enum dma_data_direction direction = iommu_tce_direction(tce);
 
        ret = get_user_pages_fast(tce & PAGE_MASK, 1,
                        direction != DMA_TO_DEVICE, &page);
        if (unlikely(ret != 1)) {
                /* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n",
-                               tce, entry << IOMMU_PAGE_SHIFT, ret); */
+                               tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */
                return -EFAULT;
        }
        hwaddr = (unsigned long) page_address(page) + offset;
@@ -1067,7 +1067,7 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry,
 
        if (ret < 0)
                pr_err("iommu_tce: %s failed ioba=%lx, tce=%lx, ret=%d\n",
-                               __func__, entry << IOMMU_PAGE_SHIFT, tce, ret);
+                       __func__, entry << tbl->it_page_shift, tce, ret);
 
        return ret;
 }
@@ -1105,7 +1105,7 @@ void iommu_release_ownership(struct iommu_table *tbl)
 }
 EXPORT_SYMBOL_GPL(iommu_release_ownership);
 
-static int iommu_add_device(struct device *dev)
+int iommu_add_device(struct device *dev)
 {
        struct iommu_table *tbl;
        int ret = 0;
@@ -1127,6 +1127,12 @@ static int iommu_add_device(struct device *dev)
        pr_debug("iommu_tce: adding %s to iommu group %d\n",
                        dev_name(dev), iommu_group_id(tbl->it_group));
 
+       if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
+               pr_err("iommu_tce: unsupported iommu page size.");
+               pr_err("%s has not been added\n", dev_name(dev));
+               return -EINVAL;
+       }
+
        ret = iommu_group_add_device(tbl->it_group, dev);
        if (ret < 0)
                pr_err("iommu_tce: %s has not been added, ret=%d\n",
@@ -1134,52 +1140,23 @@ static int iommu_add_device(struct device *dev)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(iommu_add_device);
 
-static void iommu_del_device(struct device *dev)
-{
-       iommu_group_remove_device(dev);
-}
-
-static int iommu_bus_notifier(struct notifier_block *nb,
-                             unsigned long action, void *data)
+void iommu_del_device(struct device *dev)
 {
-       struct device *dev = data;
-
-       switch (action) {
-       case BUS_NOTIFY_ADD_DEVICE:
-               return iommu_add_device(dev);
-       case BUS_NOTIFY_DEL_DEVICE:
-               iommu_del_device(dev);
-               return 0;
-       default:
-               return 0;
+       /*
+        * Some devices might not have IOMMU table and group
+        * and we needn't detach them from the associated
+        * IOMMU groups
+        */
+       if (!dev->iommu_group) {
+               pr_debug("iommu_tce: skipping device %s with no tbl\n",
+                        dev_name(dev));
+               return;
        }
-}
 
-static struct notifier_block tce_iommu_bus_nb = {
-       .notifier_call = iommu_bus_notifier,
-};
-
-static int __init tce_iommu_init(void)
-{
-       struct pci_dev *pdev = NULL;
-
-       BUILD_BUG_ON(PAGE_SIZE < IOMMU_PAGE_SIZE);
-
-       for_each_pci_dev(pdev)
-               iommu_add_device(&pdev->dev);
-
-       bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
-       return 0;
-}
-
-subsys_initcall_sync(tce_iommu_init);
-
-#else
-
-void iommu_register_group(struct iommu_table *tbl,
-               int pci_domain_number, unsigned long pe_num)
-{
+       iommu_group_remove_device(dev);
 }
+EXPORT_SYMBOL_GPL(iommu_del_device);
 
 #endif /* CONFIG_IOMMU_API */
index ba0165615215577be84a8a576283a5fd6df12e51..9729b23bfb0a2deebf0e5157accb2d68541b6bf0 100644 (file)
@@ -354,8 +354,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 
        seq_printf(p, "%*s: ", prec, "LOC");
        for_each_online_cpu(j)
-               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs);
-        seq_printf(p, "  Local timer interrupts\n");
+               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event);
+        seq_printf(p, "  Local timer interrupts for timer event device\n");
+
+       seq_printf(p, "%*s: ", prec, "LOC");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others);
+        seq_printf(p, "  Local timer interrupts for others\n");
 
        seq_printf(p, "%*s: ", prec, "SPU");
        for_each_online_cpu(j)
@@ -389,11 +394,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
  */
 u64 arch_irq_stat_cpu(unsigned int cpu)
 {
-       u64 sum = per_cpu(irq_stat, cpu).timer_irqs;
+       u64 sum = per_cpu(irq_stat, cpu).timer_irqs_event;
 
        sum += per_cpu(irq_stat, cpu).pmu_irqs;
        sum += per_cpu(irq_stat, cpu).mce_exceptions;
        sum += per_cpu(irq_stat, cpu).spurious_irqs;
+       sum += per_cpu(irq_stat, cpu).timer_irqs_others;
 #ifdef CONFIG_PPC_DOORBELL
        sum += per_cpu(irq_stat, cpu).doorbell_irqs;
 #endif
index 83e89d310734f676274f819f2897777ce9ad3f72..8504657379f13fe7858f08b9f4f61ea4e23ecb92 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/kgdb.h>
 #include <linux/smp.h>
 #include <linux/signal.h>
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
new file mode 100644 (file)
index 0000000..cadef7e
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Machine check exception handling.
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+#define pr_fmt(fmt) "mce: " fmt
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/percpu.h>
+#include <linux/export.h>
+#include <linux/irq_work.h>
+#include <asm/mce.h>
+
+static DEFINE_PER_CPU(int, mce_nest_count);
+static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
+
+/* Queue for delayed MCE events. */
+static DEFINE_PER_CPU(int, mce_queue_count);
+static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
+
+static void machine_check_process_queued_event(struct irq_work *work);
+struct irq_work mce_event_process_work = {
+        .func = machine_check_process_queued_event,
+};
+
+static void mce_set_error_info(struct machine_check_event *mce,
+                              struct mce_error_info *mce_err)
+{
+       mce->error_type = mce_err->error_type;
+       switch (mce_err->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               mce->u.ue_error.ue_error_type = mce_err->u.ue_error_type;
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               mce->u.slb_error.slb_error_type = mce_err->u.slb_error_type;
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               mce->u.erat_error.erat_error_type = mce_err->u.erat_error_type;
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               mce->u.tlb_error.tlb_error_type = mce_err->u.tlb_error_type;
+               break;
+       case MCE_ERROR_TYPE_UNKNOWN:
+       default:
+               break;
+       }
+}
+
+/*
+ * Decode and save high level MCE information into per cpu buffer which
+ * is an array of machine_check_event structure.
+ */
+void save_mce_event(struct pt_regs *regs, long handled,
+                   struct mce_error_info *mce_err,
+                   uint64_t addr)
+{
+       uint64_t srr1;
+       int index = __get_cpu_var(mce_nest_count)++;
+       struct machine_check_event *mce = &__get_cpu_var(mce_event[index]);
+
+       /*
+        * Return if we don't have enough space to log mce event.
+        * mce_nest_count may go beyond MAX_MC_EVT but that's ok,
+        * the check below will stop buffer overrun.
+        */
+       if (index >= MAX_MC_EVT)
+               return;
+
+       /* Populate generic machine check info */
+       mce->version = MCE_V1;
+       mce->srr0 = regs->nip;
+       mce->srr1 = regs->msr;
+       mce->gpr3 = regs->gpr[3];
+       mce->in_use = 1;
+
+       mce->initiator = MCE_INITIATOR_CPU;
+       if (handled)
+               mce->disposition = MCE_DISPOSITION_RECOVERED;
+       else
+               mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
+       mce->severity = MCE_SEV_ERROR_SYNC;
+
+       srr1 = regs->msr;
+
+       /*
+        * Populate the mce error_type and type-specific error_type.
+        */
+       mce_set_error_info(mce, mce_err);
+
+       if (!addr)
+               return;
+
+       if (mce->error_type == MCE_ERROR_TYPE_TLB) {
+               mce->u.tlb_error.effective_address_provided = true;
+               mce->u.tlb_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_SLB) {
+               mce->u.slb_error.effective_address_provided = true;
+               mce->u.slb_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_ERAT) {
+               mce->u.erat_error.effective_address_provided = true;
+               mce->u.erat_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_UE) {
+               mce->u.ue_error.effective_address_provided = true;
+               mce->u.ue_error.effective_address = addr;
+       }
+       return;
+}
+
+/*
+ * get_mce_event:
+ *     mce     Pointer to machine_check_event structure to be filled.
+ *     release Flag to indicate whether to free the event slot or not.
+ *             0 <= do not release the mce event. Caller will invoke
+ *                  release_mce_event() once event has been consumed.
+ *             1 <= release the slot.
+ *
+ *     return  1 = success
+ *             0 = failure
+ *
+ * get_mce_event() will be called by platform specific machine check
+ * handle routine and in KVM.
+ * When we call get_mce_event(), we are still in interrupt context and
+ * preemption will not be scheduled until ret_from_expect() routine
+ * is called.
+ */
+int get_mce_event(struct machine_check_event *mce, bool release)
+{
+       int index = __get_cpu_var(mce_nest_count) - 1;
+       struct machine_check_event *mc_evt;
+       int ret = 0;
+
+       /* Sanity check */
+       if (index < 0)
+               return ret;
+
+       /* Check if we have MCE info to process. */
+       if (index < MAX_MC_EVT) {
+               mc_evt = &__get_cpu_var(mce_event[index]);
+               /* Copy the event structure and release the original */
+               if (mce)
+                       *mce = *mc_evt;
+               if (release)
+                       mc_evt->in_use = 0;
+               ret = 1;
+       }
+       /* Decrement the count to free the slot. */
+       if (release)
+               __get_cpu_var(mce_nest_count)--;
+
+       return ret;
+}
+
+void release_mce_event(void)
+{
+       get_mce_event(NULL, true);
+}
+
+/*
+ * Queue up the MCE event which then can be handled later.
+ */
+void machine_check_queue_event(void)
+{
+       int index;
+       struct machine_check_event evt;
+
+       if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
+               return;
+
+       index = __get_cpu_var(mce_queue_count)++;
+       /* If queue is full, just return for now. */
+       if (index >= MAX_MC_EVT) {
+               __get_cpu_var(mce_queue_count)--;
+               return;
+       }
+       __get_cpu_var(mce_event_queue[index]) = evt;
+
+       /* Queue irq work to process this event later. */
+       irq_work_queue(&mce_event_process_work);
+}
+
+/*
+ * process pending MCE event from the mce event queue. This function will be
+ * called during syscall exit.
+ */
+static void machine_check_process_queued_event(struct irq_work *work)
+{
+       int index;
+
+       /*
+        * For now just print it to console.
+        * TODO: log this error event to FSP or nvram.
+        */
+       while (__get_cpu_var(mce_queue_count) > 0) {
+               index = __get_cpu_var(mce_queue_count) - 1;
+               machine_check_print_event_info(
+                               &__get_cpu_var(mce_event_queue[index]));
+               __get_cpu_var(mce_queue_count)--;
+       }
+}
+
+void machine_check_print_event_info(struct machine_check_event *evt)
+{
+       const char *level, *sevstr, *subtype;
+       static const char *mc_ue_types[] = {
+               "Indeterminate",
+               "Instruction fetch",
+               "Page table walk ifetch",
+               "Load/Store",
+               "Page table walk Load/Store",
+       };
+       static const char *mc_slb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *mc_erat_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *mc_tlb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+
+       /* Print things out */
+       if (evt->version != MCE_V1) {
+               pr_err("Machine Check Exception, Unknown event version %d !\n",
+                      evt->version);
+               return;
+       }
+       switch (evt->severity) {
+       case MCE_SEV_NO_ERROR:
+               level = KERN_INFO;
+               sevstr = "Harmless";
+               break;
+       case MCE_SEV_WARNING:
+               level = KERN_WARNING;
+               sevstr = "";
+               break;
+       case MCE_SEV_ERROR_SYNC:
+               level = KERN_ERR;
+               sevstr = "Severe";
+               break;
+       case MCE_SEV_FATAL:
+       default:
+               level = KERN_ERR;
+               sevstr = "Fatal";
+               break;
+       }
+
+       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+              evt->disposition == MCE_DISPOSITION_RECOVERED ?
+              "Recovered" : "[Not recovered");
+       printk("%s  Initiator: %s\n", level,
+              evt->initiator == MCE_INITIATOR_CPU ? "CPU" : "Unknown");
+       switch (evt->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               subtype = evt->u.ue_error.ue_error_type <
+                       ARRAY_SIZE(mc_ue_types) ?
+                       mc_ue_types[evt->u.ue_error.ue_error_type]
+                       : "Unknown";
+               printk("%s  Error type: UE [%s]\n", level, subtype);
+               if (evt->u.ue_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.ue_error.effective_address);
+               if (evt->u.ue_error.physical_address_provided)
+                       printk("%s      Physial address: %016llx\n",
+                              level, evt->u.ue_error.physical_address);
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               subtype = evt->u.slb_error.slb_error_type <
+                       ARRAY_SIZE(mc_slb_types) ?
+                       mc_slb_types[evt->u.slb_error.slb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: SLB [%s]\n", level, subtype);
+               if (evt->u.slb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.slb_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               subtype = evt->u.erat_error.erat_error_type <
+                       ARRAY_SIZE(mc_erat_types) ?
+                       mc_erat_types[evt->u.erat_error.erat_error_type]
+                       : "Unknown";
+               printk("%s  Error type: ERAT [%s]\n", level, subtype);
+               if (evt->u.erat_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.erat_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               subtype = evt->u.tlb_error.tlb_error_type <
+                       ARRAY_SIZE(mc_tlb_types) ?
+                       mc_tlb_types[evt->u.tlb_error.tlb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: TLB [%s]\n", level, subtype);
+               if (evt->u.tlb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.tlb_error.effective_address);
+               break;
+       default:
+       case MCE_ERROR_TYPE_UNKNOWN:
+               printk("%s  Error type: Unknown\n", level);
+               break;
+       }
+}
+
+uint64_t get_mce_fault_addr(struct machine_check_event *evt)
+{
+       switch (evt->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               if (evt->u.ue_error.effective_address_provided)
+                       return evt->u.ue_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               if (evt->u.slb_error.effective_address_provided)
+                       return evt->u.slb_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               if (evt->u.erat_error.effective_address_provided)
+                       return evt->u.erat_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               if (evt->u.tlb_error.effective_address_provided)
+                       return evt->u.tlb_error.effective_address;
+               break;
+       default:
+       case MCE_ERROR_TYPE_UNKNOWN:
+               break;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(get_mce_fault_addr);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
new file mode 100644 (file)
index 0000000..27c93f4
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Machine check exception handling CPU-side for power7 and power8
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+#define pr_fmt(fmt) "mce_power: " fmt
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/mmu.h>
+#include <asm/mce.h>
+
+/* flush SLBs and reload */
+static void flush_and_reload_slb(void)
+{
+       struct slb_shadow *slb;
+       unsigned long i, n;
+
+       /* Invalidate all SLBs */
+       asm volatile("slbmte %0,%0; slbia" : : "r" (0));
+
+#ifdef CONFIG_KVM_BOOK3S_HANDLER
+       /*
+        * If machine check is hit when in guest or in transition, we will
+        * only flush the SLBs and continue.
+        */
+       if (get_paca()->kvm_hstate.in_guest)
+               return;
+#endif
+
+       /* For host kernel, reload the SLBs from shadow SLB buffer. */
+       slb = get_slb_shadow();
+       if (!slb)
+               return;
+
+       n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE);
+
+       /* Load up the SLB entries from shadow SLB */
+       for (i = 0; i < n; i++) {
+               unsigned long rb = be64_to_cpu(slb->save_area[i].esid);
+               unsigned long rs = be64_to_cpu(slb->save_area[i].vsid);
+
+               rb = (rb & ~0xFFFul) | i;
+               asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
+       }
+}
+
+static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
+{
+       long handled = 1;
+
+       /*
+        * flush and reload SLBs for SLB errors and flush TLBs for TLB errors.
+        * reset the error bits whenever we handle them so that at the end
+        * we can check whether we handled all of them or not.
+        * */
+       if (dsisr & slb_error_bits) {
+               flush_and_reload_slb();
+               /* reset error bits */
+               dsisr &= ~(slb_error_bits);
+       }
+       if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
+               /* reset error bits */
+               dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB;
+       }
+       /* Any other errors we don't understand? */
+       if (dsisr & 0xffffffffUL)
+               handled = 0;
+
+       return handled;
+}
+
+static long mce_handle_derror_p7(uint64_t dsisr)
+{
+       return mce_handle_derror(dsisr, P7_DSISR_MC_SLB_ERRORS);
+}
+
+static long mce_handle_common_ierror(uint64_t srr1)
+{
+       long handled = 0;
+
+       switch (P7_SRR1_MC_IFETCH(srr1)) {
+       case 0:
+               break;
+       case P7_SRR1_MC_IFETCH_SLB_PARITY:
+       case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               /* flush and reload SLBs for SLB errors. */
+               flush_and_reload_slb();
+               handled = 1;
+               break;
+       case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb) {
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
+                       handled = 1;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return handled;
+}
+
+static long mce_handle_ierror_p7(uint64_t srr1)
+{
+       long handled = 0;
+
+       handled = mce_handle_common_ierror(srr1);
+
+       if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
+               flush_and_reload_slb();
+               handled = 1;
+       }
+       return handled;
+}
+
+static void mce_get_common_ierror(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       switch (P7_SRR1_MC_IFETCH(srr1)) {
+       case P7_SRR1_MC_IFETCH_SLB_PARITY:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+               break;
+       case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+               break;
+       case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+               break;
+       case P7_SRR1_MC_IFETCH_UE:
+       case P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_IFETCH;
+               break;
+       case P7_SRR1_MC_IFETCH_UE_TLB_RELOAD:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type =
+                               MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH;
+               break;
+       }
+}
+
+static void mce_get_ierror_p7(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       mce_get_common_ierror(mce_err, srr1);
+       if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
+       }
+}
+
+static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
+{
+       if (dsisr & P7_DSISR_MC_UE) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_LOAD_STORE;
+       } else if (dsisr & P7_DSISR_MC_UE_TABLEWALK) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type =
+                               MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
+       } else if (dsisr & P7_DSISR_MC_ERAT_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_PARITY_MFSLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+       } else if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT_PARITY) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
+       }
+}
+
+long __machine_check_early_realmode_p7(struct pt_regs *regs)
+{
+       uint64_t srr1, addr;
+       long handled = 1;
+       struct mce_error_info mce_error_info = { 0 };
+
+       srr1 = regs->msr;
+
+       /*
+        * Handle memory errors depending whether this was a load/store or
+        * ifetch exception. Also, populate the mce error_type and
+        * type-specific error_type from either SRR1 or DSISR, depending
+        * whether this was a load/store or ifetch exception
+        */
+       if (P7_SRR1_MC_LOADSTORE(srr1)) {
+               handled = mce_handle_derror_p7(regs->dsisr);
+               mce_get_derror_p7(&mce_error_info, regs->dsisr);
+               addr = regs->dar;
+       } else {
+               handled = mce_handle_ierror_p7(srr1);
+               mce_get_ierror_p7(&mce_error_info, srr1);
+               addr = regs->nip;
+       }
+
+       save_mce_event(regs, handled, &mce_error_info, addr);
+       return handled;
+}
+
+static void mce_get_ierror_p8(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       mce_get_common_ierror(mce_err, srr1);
+       if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       }
+}
+
+static void mce_get_derror_p8(struct mce_error_info *mce_err, uint64_t dsisr)
+{
+       mce_get_derror_p7(mce_err, dsisr);
+       if (dsisr & P8_DSISR_MC_ERAT_MULTIHIT_SEC) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       }
+}
+
+static long mce_handle_ierror_p8(uint64_t srr1)
+{
+       long handled = 0;
+
+       handled = mce_handle_common_ierror(srr1);
+
+       if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
+               flush_and_reload_slb();
+               handled = 1;
+       }
+       return handled;
+}
+
+static long mce_handle_derror_p8(uint64_t dsisr)
+{
+       return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
+}
+
+long __machine_check_early_realmode_p8(struct pt_regs *regs)
+{
+       uint64_t srr1, addr;
+       long handled = 1;
+       struct mce_error_info mce_error_info = { 0 };
+
+       srr1 = regs->msr;
+
+       if (P7_SRR1_MC_LOADSTORE(srr1)) {
+               handled = mce_handle_derror_p8(regs->dsisr);
+               mce_get_derror_p8(&mce_error_info, regs->dsisr);
+               addr = regs->dar;
+       } else {
+               handled = mce_handle_ierror_p8(srr1);
+               mce_get_ierror_p8(&mce_error_info, srr1);
+               addr = regs->nip;
+       }
+
+       save_mce_event(regs, handled, &mce_error_info, addr);
+       return handled;
+}
index e47d268727a4a8ed87948a4d3ab5f87ad00793b1..879f09620f8341e27dbfd1ed6be47fe242eab812 100644 (file)
@@ -344,7 +344,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
  */
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
-       isync
+       PURGE_PREFETCHED_INS
        blr                             /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        li      r5,L1_CACHE_BYTES-1
@@ -448,6 +448,7 @@ _GLOBAL(invalidate_dcache_range)
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r3,r3,0,0,31-PAGE_SHIFT         /* Get page base address */
@@ -489,6 +490,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
  */
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr                                     /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        mfmsr   r10
index 64bf8db12b15be3e8dbc903b6c8bb27173940fc1..3d0249599d524af2a8883cacc4df5d44716273b8 100644 (file)
@@ -67,6 +67,7 @@ PPC64_CACHES:
 
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 /*
@@ -211,6 +212,11 @@ _GLOBAL(__flush_dcache_icache)
  * Different systems have different cache line sizes
  */
 
+BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
+       blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
+
 /* Flush the dcache */
        ld      r7,PPC64_CACHES@toc(r2)
        clrrdi  r3,r3,PAGE_SHIFT                    /* Page align */
index 0620eaaaad45b419c70475485a9d052c0ddbe246..bf0aada02fe4798c39e60d84653bef3a51ee4f83 100644 (file)
@@ -99,12 +99,28 @@ static inline void free_lppacas(void) { }
  * 3 persistent SLBs are registered here.  The buffer will be zero
  * initially, hence will all be invaild until we actually write them.
  */
-struct slb_shadow slb_shadow[] __cacheline_aligned = {
-       [0 ... (NR_CPUS-1)] = {
-               .persistent = cpu_to_be32(SLB_NUM_BOLTED),
-               .buffer_length = cpu_to_be32(sizeof(struct slb_shadow)),
-       },
-};
+static struct slb_shadow *slb_shadow;
+
+static void __init allocate_slb_shadows(int nr_cpus, int limit)
+{
+       int size = PAGE_ALIGN(sizeof(struct slb_shadow) * nr_cpus);
+       slb_shadow = __va(memblock_alloc_base(size, PAGE_SIZE, limit));
+       memset(slb_shadow, 0, size);
+}
+
+static struct slb_shadow * __init init_slb_shadow(int cpu)
+{
+       struct slb_shadow *s = &slb_shadow[cpu];
+
+       s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
+       s->buffer_length = cpu_to_be32(sizeof(*s));
+
+       return s;
+}
+
+#else /* CONFIG_PPC_STD_MMU_64 */
+
+static void __init allocate_slb_shadows(int nr_cpus, int limit) { }
 
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
@@ -142,8 +158,13 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
        new_paca->__current = &init_task;
        new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
 #ifdef CONFIG_PPC_STD_MMU_64
-       new_paca->slb_shadow_ptr = &slb_shadow[cpu];
+       new_paca->slb_shadow_ptr = init_slb_shadow(cpu);
 #endif /* CONFIG_PPC_STD_MMU_64 */
+
+#ifdef CONFIG_PPC_BOOK3E
+       /* For now -- if we have threads this will be adjusted later */
+       new_paca->tcd_ptr = &new_paca->tcd;
+#endif
 }
 
 /* Put the paca pointer into r13 and SPRG_PACA */
@@ -190,6 +211,8 @@ void __init allocate_pacas(void)
 
        allocate_lppacas(nr_cpu_ids, limit);
 
+       allocate_slb_shadows(nr_cpu_ids, limit);
+
        /* Can't use for_each_*_cpu, as they aren't functional yet */
        for (cpu = 0; cpu < nr_cpu_ids; cpu++)
                initialise_paca(&paca[cpu], cpu);
index 4a96556fd2d49e484c143ed3643db6c8a24962df..64b7a6e61dd1acd6fa102a6e856da6afb089f136 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/elf.h>
-#include <linux/init.h>
 #include <linux/prctl.h>
 #include <linux/init_task.h>
 #include <linux/export.h>
@@ -74,6 +73,48 @@ struct task_struct *last_task_used_vsx = NULL;
 struct task_struct *last_task_used_spe = NULL;
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void giveup_fpu_maybe_transactional(struct task_struct *tsk)
+{
+       /*
+        * If we are saving the current thread's registers, and the
+        * thread is in a transactional state, set the TIF_RESTORE_TM
+        * bit so that we know to restore the registers before
+        * returning to userspace.
+        */
+       if (tsk == current && tsk->thread.regs &&
+           MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
+           !test_thread_flag(TIF_RESTORE_TM)) {
+               tsk->thread.tm_orig_msr = tsk->thread.regs->msr;
+               set_thread_flag(TIF_RESTORE_TM);
+       }
+
+       giveup_fpu(tsk);
+}
+
+void giveup_altivec_maybe_transactional(struct task_struct *tsk)
+{
+       /*
+        * If we are saving the current thread's registers, and the
+        * thread is in a transactional state, set the TIF_RESTORE_TM
+        * bit so that we know to restore the registers before
+        * returning to userspace.
+        */
+       if (tsk == current && tsk->thread.regs &&
+           MSR_TM_ACTIVE(tsk->thread.regs->msr) &&
+           !test_thread_flag(TIF_RESTORE_TM)) {
+               tsk->thread.tm_orig_msr = tsk->thread.regs->msr;
+               set_thread_flag(TIF_RESTORE_TM);
+       }
+
+       giveup_altivec(tsk);
+}
+
+#else
+#define giveup_fpu_maybe_transactional(tsk)    giveup_fpu(tsk)
+#define giveup_altivec_maybe_transactional(tsk)        giveup_altivec(tsk)
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
 #ifdef CONFIG_PPC_FPU
 /*
  * Make sure the floating-point register state in the
@@ -102,13 +143,13 @@ void flush_fp_to_thread(struct task_struct *tsk)
                         */
                        BUG_ON(tsk != current);
 #endif
-                       giveup_fpu(tsk);
+                       giveup_fpu_maybe_transactional(tsk);
                }
                preempt_enable();
        }
 }
 EXPORT_SYMBOL_GPL(flush_fp_to_thread);
-#endif
+#endif /* CONFIG_PPC_FPU */
 
 void enable_kernel_fp(void)
 {
@@ -116,11 +157,11 @@ void enable_kernel_fp(void)
 
 #ifdef CONFIG_SMP
        if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
-               giveup_fpu(current);
+               giveup_fpu_maybe_transactional(current);
        else
                giveup_fpu(NULL);       /* just enables FP for kernel */
 #else
-       giveup_fpu(last_task_used_math);
+       giveup_fpu_maybe_transactional(last_task_used_math);
 #endif /* CONFIG_SMP */
 }
 EXPORT_SYMBOL(enable_kernel_fp);
@@ -132,11 +173,11 @@ void enable_kernel_altivec(void)
 
 #ifdef CONFIG_SMP
        if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
-               giveup_altivec(current);
+               giveup_altivec_maybe_transactional(current);
        else
                giveup_altivec_notask();
 #else
-       giveup_altivec(last_task_used_altivec);
+       giveup_altivec_maybe_transactional(last_task_used_altivec);
 #endif /* CONFIG_SMP */
 }
 EXPORT_SYMBOL(enable_kernel_altivec);
@@ -153,7 +194,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
 #ifdef CONFIG_SMP
                        BUG_ON(tsk != current);
 #endif
-                       giveup_altivec(tsk);
+                       giveup_altivec_maybe_transactional(tsk);
                }
                preempt_enable();
        }
@@ -182,8 +223,8 @@ EXPORT_SYMBOL(enable_kernel_vsx);
 
 void giveup_vsx(struct task_struct *tsk)
 {
-       giveup_fpu(tsk);
-       giveup_altivec(tsk);
+       giveup_fpu_maybe_transactional(tsk);
+       giveup_altivec_maybe_transactional(tsk);
        __giveup_vsx(tsk);
 }
 
@@ -479,7 +520,48 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a,
                return false;
        return true;
 }
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static void tm_reclaim_thread(struct thread_struct *thr,
+                             struct thread_info *ti, uint8_t cause)
+{
+       unsigned long msr_diff = 0;
+
+       /*
+        * If FP/VSX registers have been already saved to the
+        * thread_struct, move them to the transact_fp array.
+        * We clear the TIF_RESTORE_TM bit since after the reclaim
+        * the thread will no longer be transactional.
+        */
+       if (test_ti_thread_flag(ti, TIF_RESTORE_TM)) {
+               msr_diff = thr->tm_orig_msr & ~thr->regs->msr;
+               if (msr_diff & MSR_FP)
+                       memcpy(&thr->transact_fp, &thr->fp_state,
+                              sizeof(struct thread_fp_state));
+               if (msr_diff & MSR_VEC)
+                       memcpy(&thr->transact_vr, &thr->vr_state,
+                              sizeof(struct thread_vr_state));
+               clear_ti_thread_flag(ti, TIF_RESTORE_TM);
+               msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1;
+       }
+
+       tm_reclaim(thr, thr->regs->msr, cause);
+
+       /* Having done the reclaim, we now have the checkpointed
+        * FP/VSX values in the registers.  These might be valid
+        * even if we have previously called enable_kernel_fp() or
+        * flush_fp_to_thread(), so update thr->regs->msr to
+        * indicate their current validity.
+        */
+       thr->regs->msr |= msr_diff;
+}
+
+void tm_reclaim_current(uint8_t cause)
+{
+       tm_enable();
+       tm_reclaim_thread(&current->thread, current_thread_info(), cause);
+}
+
 static inline void tm_reclaim_task(struct task_struct *tsk)
 {
        /* We have to work out if we're switching from/to a task that's in the
@@ -502,9 +584,11 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
 
        /* Stash the original thread MSR, as giveup_fpu et al will
         * modify it.  We hold onto it to see whether the task used
-        * FP & vector regs.
+        * FP & vector regs.  If the TIF_RESTORE_TM flag is set,
+        * tm_orig_msr is already set.
         */
-       thr->tm_orig_msr = thr->regs->msr;
+       if (!test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_TM))
+               thr->tm_orig_msr = thr->regs->msr;
 
        TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, "
                 "ccr=%lx, msr=%lx, trap=%lx)\n",
@@ -512,7 +596,7 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
                 thr->regs->ccr, thr->regs->msr,
                 thr->regs->trap);
 
-       tm_reclaim(thr, thr->regs->msr, TM_CAUSE_RESCHED);
+       tm_reclaim_thread(thr, task_thread_info(tsk), TM_CAUSE_RESCHED);
 
        TM_DEBUG("--- tm_reclaim on pid %d complete\n",
                 tsk->pid);
@@ -588,6 +672,43 @@ static inline void __switch_to_tm(struct task_struct *prev)
                tm_reclaim_task(prev);
        }
 }
+
+/*
+ * This is called if we are on the way out to userspace and the
+ * TIF_RESTORE_TM flag is set.  It checks if we need to reload
+ * FP and/or vector state and does so if necessary.
+ * If userspace is inside a transaction (whether active or
+ * suspended) and FP/VMX/VSX instructions have ever been enabled
+ * inside that transaction, then we have to keep them enabled
+ * and keep the FP/VMX/VSX state loaded while ever the transaction
+ * continues.  The reason is that if we didn't, and subsequently
+ * got a FP/VMX/VSX unavailable interrupt inside a transaction,
+ * we don't know whether it's the same transaction, and thus we
+ * don't know which of the checkpointed state and the transactional
+ * state to use.
+ */
+void restore_tm_state(struct pt_regs *regs)
+{
+       unsigned long msr_diff;
+
+       clear_thread_flag(TIF_RESTORE_TM);
+       if (!MSR_TM_ACTIVE(regs->msr))
+               return;
+
+       msr_diff = current->thread.tm_orig_msr & ~regs->msr;
+       msr_diff &= MSR_FP | MSR_VEC | MSR_VSX;
+       if (msr_diff & MSR_FP) {
+               fp_enable();
+               load_fp_state(&current->thread.fp_state);
+               regs->msr |= current->thread.fpexc_mode;
+       }
+       if (msr_diff & MSR_VEC) {
+               vec_enable();
+               load_vr_state(&current->thread.vr_state);
+       }
+       regs->msr |= msr_diff;
+}
+
 #else
 #define tm_recheckpoint_new_task(new)
 #define __switch_to_tm(prev)
@@ -1175,6 +1296,19 @@ int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
        if (val & PR_FP_EXC_SW_ENABLE) {
 #ifdef CONFIG_SPE
                if (cpu_has_feature(CPU_FTR_SPE)) {
+                       /*
+                        * When the sticky exception bits are set
+                        * directly by userspace, it must call prctl
+                        * with PR_GET_FPEXC (with PR_FP_EXC_SW_ENABLE
+                        * in the existing prctl settings) or
+                        * PR_SET_FPEXC (with PR_FP_EXC_SW_ENABLE in
+                        * the bits being set).  <fenv.h> functions
+                        * saving and restoring the whole
+                        * floating-point environment need to do so
+                        * anyway to restore the prctl settings from
+                        * the saved environment.
+                        */
+                       tsk->thread.spefscr_last = mfspr(SPRN_SPEFSCR);
                        tsk->thread.fpexc_mode = val &
                                (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
                        return 0;
@@ -1206,9 +1340,22 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
 
        if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
 #ifdef CONFIG_SPE
-               if (cpu_has_feature(CPU_FTR_SPE))
+               if (cpu_has_feature(CPU_FTR_SPE)) {
+                       /*
+                        * When the sticky exception bits are set
+                        * directly by userspace, it must call prctl
+                        * with PR_GET_FPEXC (with PR_FP_EXC_SW_ENABLE
+                        * in the existing prctl settings) or
+                        * PR_SET_FPEXC (with PR_FP_EXC_SW_ENABLE in
+                        * the bits being set).  <fenv.h> functions
+                        * saving and restoring the whole
+                        * floating-point environment need to do so
+                        * anyway to restore the prctl settings from
+                        * the saved environment.
+                        */
+                       tsk->thread.spefscr_last = mfspr(SPRN_SPEFSCR);
                        val = tsk->thread.fpexc_mode;
-               else
+               else
                        return -EINVAL;
 #else
                return -EINVAL;
index fa0ad8aafbccf3950506a96a64f75bc2141f1bd7..f58c0d3aaeb497697aaa7ed75874ddee33146652 100644 (file)
@@ -523,6 +523,20 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node,
        return early_init_dt_scan_memory(node, uname, depth, data);
 }
 
+/*
+ * For a relocatable kernel, we need to get the memstart_addr first,
+ * then use it to calculate the virtual kernel start address. This has
+ * to happen at a very early stage (before machine_init). In this case,
+ * we just want to get the memstart_address and would not like to mess the
+ * memblock at this stage. So introduce a variable to skip the memblock_add()
+ * for this reason.
+ */
+#ifdef CONFIG_RELOCATABLE
+static int add_mem_to_memblock = 1;
+#else
+#define add_mem_to_memblock 1
+#endif
+
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
 #ifdef CONFIG_PPC64
@@ -543,7 +557,8 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
        }
 
        /* Add the chunk to the MEMBLOCK list */
-       memblock_add(base, size);
+       if (add_mem_to_memblock)
+               memblock_add(base, size);
 }
 
 static void __init early_reserve_mem_dt(void)
@@ -740,6 +755,30 @@ void __init early_init_devtree(void *params)
        DBG(" <- early_init_devtree()\n");
 }
 
+#ifdef CONFIG_RELOCATABLE
+/*
+ * This function run before early_init_devtree, so we have to init
+ * initial_boot_params.
+ */
+void __init early_get_first_memblock_info(void *params, phys_addr_t *size)
+{
+       /* Setup flat device-tree pointer */
+       initial_boot_params = params;
+
+       /*
+        * Scan the memory nodes and set add_mem_to_memblock to 0 to avoid
+        * mess the memblock.
+        */
+       add_mem_to_memblock = 0;
+       of_scan_flat_dt(early_init_dt_scan_root, NULL);
+       of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
+       add_mem_to_memblock = 1;
+
+       if (size)
+               *size = first_memblock_size;
+}
+#endif
+
 /*******
  *
  * New implementation of the OF "find" APIs, return a refcounted
index 856dd4e99bfe459cdb430f5cba6fbc0b3229be89..f5f11a7d30e5502637d58656b7c587b37001ea81 100644 (file)
@@ -97,6 +97,36 @@ int dcache_bsize;
 int icache_bsize;
 int ucache_bsize;
 
+#if defined(CONFIG_PPC_BOOK3E) && defined(CONFIG_SMP)
+static void setup_tlb_core_data(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               int first = cpu_first_thread_sibling(cpu);
+
+               paca[cpu].tcd_ptr = &paca[first].tcd;
+
+               /*
+                * If we have threads, we need either tlbsrx.
+                * or e6500 tablewalk mode, or else TLB handlers
+                * will be racy and could produce duplicate entries.
+                */
+               if (smt_enabled_at_boot >= 2 &&
+                   !mmu_has_feature(MMU_FTR_USE_TLBRSRV) &&
+                   book3e_htw_mode != PPC_HTW_E6500) {
+                       /* Should we panic instead? */
+                       WARN_ONCE("%s: unsupported MMU configuration -- expect problems\n",
+                                 __func__);
+               }
+       }
+}
+#else
+static void setup_tlb_core_data(void)
+{
+}
+#endif
+
 #ifdef CONFIG_SMP
 
 static char *smt_enabled_cmdline;
@@ -445,6 +475,7 @@ void __init setup_system(void)
 
        smp_setup_cpu_maps();
        check_smt_enabled();
+       setup_tlb_core_data();
 
 #ifdef CONFIG_SMP
        /* Release secondary cpus out of their spinloops at 0x60 now that
@@ -520,9 +551,6 @@ static void __init irqstack_early_init(void)
 #ifdef CONFIG_PPC_BOOK3E
 static void __init exc_lvl_early_init(void)
 {
-       extern unsigned int interrupt_base_book3e;
-       extern unsigned int exc_debug_debug_book3e;
-
        unsigned int i;
 
        for_each_possible_cpu(i) {
@@ -535,8 +563,7 @@ static void __init exc_lvl_early_init(void)
        }
 
        if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
-               patch_branch(&interrupt_base_book3e + (0x040 / 4) + 1,
-                            (unsigned long)&exc_debug_debug_book3e, 0);
+               patch_exception(0x040, exc_debug_debug_book3e);
 }
 #else
 #define exc_lvl_early_init()
@@ -544,7 +571,8 @@ static void __init exc_lvl_early_init(void)
 
 /*
  * Stack space used when we detect a bad kernel stack pointer, and
- * early in SMP boots before relocation is enabled.
+ * early in SMP boots before relocation is enabled. Exclusive emergency
+ * stack for machine checks.
  */
 static void __init emergency_stack_init(void)
 {
@@ -567,6 +595,13 @@ static void __init emergency_stack_init(void)
                sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
                sp += THREAD_SIZE;
                paca[i].emergency_sp = __va(sp);
+
+#ifdef CONFIG_PPC_BOOK3S_64
+               /* emergency stack for machine check exception handling. */
+               sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
+               sp += THREAD_SIZE;
+               paca[i].mc_emergency_sp = __va(sp);
+#endif
        }
 }
 
index 457e97aa29455e6894257f443f1a223583483685..8fc4177ed65acb6e9b1873f3614fc0457125c783 100644 (file)
@@ -203,8 +203,7 @@ unsigned long get_tm_stackpointer(struct pt_regs *regs)
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        if (MSR_TM_ACTIVE(regs->msr)) {
-               tm_enable();
-               tm_reclaim(&current->thread, regs->msr, TM_CAUSE_SIGNAL);
+               tm_reclaim_current(TM_CAUSE_SIGNAL);
                if (MSR_TM_TRANSACTIONAL(regs->msr))
                        return current->thread.ckpt_regs.gpr[1];
        }
index 68027bfa5f8e3c4a958deeb13db1b6a9fcf89325..6ce69e6f1fcb8c4557bb3e19af8d8111ad51a4ae 100644 (file)
@@ -519,6 +519,13 @@ static int save_tm_user_regs(struct pt_regs *regs,
 {
        unsigned long msr = regs->msr;
 
+       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
+        * just indicates to userland that we were doing a transaction, but we
+        * don't want to return in transactional state.  This also ensures
+        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
+        */
+       regs->msr &= ~MSR_TS_MASK;
+
        /* Make sure floating point registers are stored in regs */
        flush_fp_to_thread(current);
 
@@ -1056,13 +1063,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
        /* enter the signal handler in native-endian mode */
        regs->msr &= ~MSR_LE;
        regs->msr |= (MSR_KERNEL & MSR_LE);
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state:
-        */
-       regs->msr &= ~MSR_TS_MASK;
-#endif
        return 1;
 
 badframe:
@@ -1484,13 +1484,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        regs->nip = (unsigned long) ka->sa.sa_handler;
        /* enter the signal handler in big-endian mode */
        regs->msr &= ~MSR_LE;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state:
-        */
-       regs->msr &= ~MSR_TS_MASK;
-#endif
        return 1;
 
 badframe:
index 42991045349f815e124e18dba78c9a914c8b8b84..e35bf773df7a8d972990374cbb1507db261ccea2 100644 (file)
@@ -192,6 +192,13 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
 
        BUG_ON(!MSR_TM_ACTIVE(regs->msr));
 
+       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
+        * just indicates to userland that we were doing a transaction, but we
+        * don't want to return in transactional state.  This also ensures
+        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
+        */
+       regs->msr &= ~MSR_TS_MASK;
+
        flush_fp_to_thread(current);
 
 #ifdef CONFIG_ALTIVEC
@@ -749,13 +756,6 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
 
        /* Make sure signal handler doesn't get spurious FP exceptions */
        current->thread.fp_state.fpscr = 0;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state:
-        */
-       regs->msr &= ~MSR_TS_MASK;
-#endif
 
        /* Set up to return from userspace. */
        if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
index e68fd1ae727a56c2edd9f79a21fcf9dd467b4f04..7a37ecd3afa3b211202ddcfbdfe382f6ce5d4995 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/unistd.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
index c1cf4a1522d9940bf3bb97a3e995a2642dee41ca..ac2621af31545b4aa3a4a434f7119c2c3aac222e 100644 (file)
@@ -369,13 +369,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid));
        cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid));
 
-       if (smp_ops)
-               if (smp_ops->probe)
-                       max_cpus = smp_ops->probe();
-               else
-                       max_cpus = NR_CPUS;
-       else
-               max_cpus = 1;
+       if (smp_ops && smp_ops->probe)
+               smp_ops->probe();
 }
 
 void smp_prepare_boot_cpu(void)
index 0f204053e5b5a49e29df9d2f4113d208cb65417e..553c1405ee05774b49f355a7c3bfcedc1e7a69f9 100644 (file)
@@ -74,21 +74,21 @@ _GLOBAL(swsusp_arch_suspend)
        bne     1b
 
        /* Save SPRGs */
-       mfsprg  r4,0
+       mfspr   r4,SPRN_SPRG0
        stw     r4,SL_SPRG0(r11)
-       mfsprg  r4,1
+       mfspr   r4,SPRN_SPRG1
        stw     r4,SL_SPRG1(r11)
-       mfsprg  r4,2
+       mfspr   r4,SPRN_SPRG2
        stw     r4,SL_SPRG2(r11)
-       mfsprg  r4,3
+       mfspr   r4,SPRN_SPRG3
        stw     r4,SL_SPRG3(r11)
-       mfsprg  r4,4
+       mfspr   r4,SPRN_SPRG4
        stw     r4,SL_SPRG4(r11)
-       mfsprg  r4,5
+       mfspr   r4,SPRN_SPRG5
        stw     r4,SL_SPRG5(r11)
-       mfsprg  r4,6
+       mfspr   r4,SPRN_SPRG6
        stw     r4,SL_SPRG6(r11)
-       mfsprg  r4,7
+       mfspr   r4,SPRN_SPRG7
        stw     r4,SL_SPRG7(r11)
 
        /* Call the low level suspend stuff (we should probably have made
@@ -150,21 +150,21 @@ _GLOBAL(swsusp_arch_resume)
        bl      _tlbil_all
 
        lwz     r4,SL_SPRG0(r11)
-       mtsprg  0,r4
+       mtspr   SPRN_SPRG0,r4
        lwz     r4,SL_SPRG1(r11)
-       mtsprg  1,r4
+       mtspr   SPRN_SPRG1,r4
        lwz     r4,SL_SPRG2(r11)
-       mtsprg  2,r4
+       mtspr   SPRN_SPRG2,r4
        lwz     r4,SL_SPRG3(r11)
-       mtsprg  3,r4
+       mtspr   SPRN_SPRG3,r4
        lwz     r4,SL_SPRG4(r11)
-       mtsprg  4,r4
+       mtspr   SPRN_SPRG4,r4
        lwz     r4,SL_SPRG5(r11)
-       mtsprg  5,r4
+       mtspr   SPRN_SPRG5,r4
        lwz     r4,SL_SPRG6(r11)
-       mtsprg  6,r4
+       mtspr   SPRN_SPRG6,r4
        lwz     r4,SL_SPRG7(r11)
-       mtsprg  7,r4
+       mtspr   SPRN_SPRG7,r4
 
        /* restore the MSR */
        lwz     r3,SL_MSR(r11)
index 4e3cc47f26b90e157ebb5c2a1cd156918e655930..cd9be9aa016d184da98d24cd5dbb2f04c48dce50 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ipc.h>
 #include <linux/utsname.h>
 #include <linux/file.h>
-#include <linux/init.h>
 #include <linux/personality.h>
 
 #include <asm/uaccess.h>
index b4e667663d9bfc2e9954435790b0ebc5b6fc94ca..d4a43e64a6a9ef6868137c1bb2ad094f02be5e29 100644 (file)
@@ -86,6 +86,304 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+#define MAX_BIT                                63
+
+static u64 pw20_wt;
+static u64 altivec_idle_wt;
+
+static unsigned int get_idle_ticks_bit(u64 ns)
+{
+       u64 cycle;
+
+       if (ns >= 10000)
+               cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
+       else
+               cycle = div_u64(ns * tb_ticks_per_usec, 1000);
+
+       if (!cycle)
+               return 0;
+
+       return ilog2(cycle);
+}
+
+static void do_show_pwrmgtcr0(void *val)
+{
+       u32 *value = val;
+
+       *value = mfspr(SPRN_PWRMGTCR0);
+}
+
+static ssize_t show_pw20_state(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u32 value;
+       unsigned int cpu = dev->id;
+
+       smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+
+       value &= PWRMGTCR0_PW20_WAIT;
+
+       return sprintf(buf, "%u\n", value ? 1 : 0);
+}
+
+static void do_store_pw20_state(void *val)
+{
+       u32 *value = val;
+       u32 pw20_state;
+
+       pw20_state = mfspr(SPRN_PWRMGTCR0);
+
+       if (*value)
+               pw20_state |= PWRMGTCR0_PW20_WAIT;
+       else
+               pw20_state &= ~PWRMGTCR0_PW20_WAIT;
+
+       mtspr(SPRN_PWRMGTCR0, pw20_state);
+}
+
+static ssize_t store_pw20_state(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u32 value;
+       unsigned int cpu = dev->id;
+
+       if (kstrtou32(buf, 0, &value))
+               return -EINVAL;
+
+       if (value > 1)
+               return -EINVAL;
+
+       smp_call_function_single(cpu, do_store_pw20_state, &value, 1);
+
+       return count;
+}
+
+static ssize_t show_pw20_wait_time(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u32 value;
+       u64 tb_cycle = 1;
+       u64 time;
+
+       unsigned int cpu = dev->id;
+
+       if (!pw20_wt) {
+               smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+               value = (value & PWRMGTCR0_PW20_ENT) >>
+                                       PWRMGTCR0_PW20_ENT_SHIFT;
+
+               tb_cycle = (tb_cycle << (MAX_BIT - value + 1));
+               /* convert ms to ns */
+               if (tb_ticks_per_usec > 1000) {
+                       time = div_u64(tb_cycle, tb_ticks_per_usec / 1000);
+               } else {
+                       u32 rem_us;
+
+                       time = div_u64_rem(tb_cycle, tb_ticks_per_usec,
+                                               &rem_us);
+                       time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec;
+               }
+       } else {
+               time = pw20_wt;
+       }
+
+       return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+}
+
+static void set_pw20_wait_entry_bit(void *val)
+{
+       u32 *value = val;
+       u32 pw20_idle;
+
+       pw20_idle = mfspr(SPRN_PWRMGTCR0);
+
+       /* Set Automatic PW20 Core Idle Count */
+       /* clear count */
+       pw20_idle &= ~PWRMGTCR0_PW20_ENT;
+
+       /* set count */
+       pw20_idle |= ((MAX_BIT - *value) << PWRMGTCR0_PW20_ENT_SHIFT);
+
+       mtspr(SPRN_PWRMGTCR0, pw20_idle);
+}
+
+static ssize_t store_pw20_wait_time(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u32 entry_bit;
+       u64 value;
+
+       unsigned int cpu = dev->id;
+
+       if (kstrtou64(buf, 0, &value))
+               return -EINVAL;
+
+       if (!value)
+               return -EINVAL;
+
+       entry_bit = get_idle_ticks_bit(value);
+       if (entry_bit > MAX_BIT)
+               return -EINVAL;
+
+       pw20_wt = value;
+
+       smp_call_function_single(cpu, set_pw20_wait_entry_bit,
+                               &entry_bit, 1);
+
+       return count;
+}
+
+static ssize_t show_altivec_idle(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u32 value;
+       unsigned int cpu = dev->id;
+
+       smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+
+       value &= PWRMGTCR0_AV_IDLE_PD_EN;
+
+       return sprintf(buf, "%u\n", value ? 1 : 0);
+}
+
+static void do_store_altivec_idle(void *val)
+{
+       u32 *value = val;
+       u32 altivec_idle;
+
+       altivec_idle = mfspr(SPRN_PWRMGTCR0);
+
+       if (*value)
+               altivec_idle |= PWRMGTCR0_AV_IDLE_PD_EN;
+       else
+               altivec_idle &= ~PWRMGTCR0_AV_IDLE_PD_EN;
+
+       mtspr(SPRN_PWRMGTCR0, altivec_idle);
+}
+
+static ssize_t store_altivec_idle(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u32 value;
+       unsigned int cpu = dev->id;
+
+       if (kstrtou32(buf, 0, &value))
+               return -EINVAL;
+
+       if (value > 1)
+               return -EINVAL;
+
+       smp_call_function_single(cpu, do_store_altivec_idle, &value, 1);
+
+       return count;
+}
+
+static ssize_t show_altivec_idle_wait_time(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u32 value;
+       u64 tb_cycle = 1;
+       u64 time;
+
+       unsigned int cpu = dev->id;
+
+       if (!altivec_idle_wt) {
+               smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+               value = (value & PWRMGTCR0_AV_IDLE_CNT) >>
+                                       PWRMGTCR0_AV_IDLE_CNT_SHIFT;
+
+               tb_cycle = (tb_cycle << (MAX_BIT - value + 1));
+               /* convert ms to ns */
+               if (tb_ticks_per_usec > 1000) {
+                       time = div_u64(tb_cycle, tb_ticks_per_usec / 1000);
+               } else {
+                       u32 rem_us;
+
+                       time = div_u64_rem(tb_cycle, tb_ticks_per_usec,
+                                               &rem_us);
+                       time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec;
+               }
+       } else {
+               time = altivec_idle_wt;
+       }
+
+       return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+}
+
+static void set_altivec_idle_wait_entry_bit(void *val)
+{
+       u32 *value = val;
+       u32 altivec_idle;
+
+       altivec_idle = mfspr(SPRN_PWRMGTCR0);
+
+       /* Set Automatic AltiVec Idle Count */
+       /* clear count */
+       altivec_idle &= ~PWRMGTCR0_AV_IDLE_CNT;
+
+       /* set count */
+       altivec_idle |= ((MAX_BIT - *value) << PWRMGTCR0_AV_IDLE_CNT_SHIFT);
+
+       mtspr(SPRN_PWRMGTCR0, altivec_idle);
+}
+
+static ssize_t store_altivec_idle_wait_time(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       u32 entry_bit;
+       u64 value;
+
+       unsigned int cpu = dev->id;
+
+       if (kstrtou64(buf, 0, &value))
+               return -EINVAL;
+
+       if (!value)
+               return -EINVAL;
+
+       entry_bit = get_idle_ticks_bit(value);
+       if (entry_bit > MAX_BIT)
+               return -EINVAL;
+
+       altivec_idle_wt = value;
+
+       smp_call_function_single(cpu, set_altivec_idle_wait_entry_bit,
+                               &entry_bit, 1);
+
+       return count;
+}
+
+/*
+ * Enable/Disable interface:
+ * 0, disable. 1, enable.
+ */
+static DEVICE_ATTR(pw20_state, 0600, show_pw20_state, store_pw20_state);
+static DEVICE_ATTR(altivec_idle, 0600, show_altivec_idle, store_altivec_idle);
+
+/*
+ * Set wait time interface:(Nanosecond)
+ * Example: Base on TBfreq is 41MHZ.
+ * 1~48(ns): TB[63]
+ * 49~97(ns): TB[62]
+ * 98~195(ns): TB[61]
+ * 196~390(ns): TB[60]
+ * 391~780(ns): TB[59]
+ * 781~1560(ns): TB[58]
+ * ...
+ */
+static DEVICE_ATTR(pw20_wait_time, 0600,
+                       show_pw20_wait_time,
+                       store_pw20_wait_time);
+static DEVICE_ATTR(altivec_idle_wait_time, 0600,
+                       show_altivec_idle_wait_time,
+                       store_altivec_idle_wait_time);
+#endif
+
 /*
  * Enabling PMCs will slow partition context switch times so we only do
  * it the first time we write to the PMCs.
@@ -108,14 +406,14 @@ void ppc_enable_pmcs(void)
 }
 EXPORT_SYMBOL(ppc_enable_pmcs);
 
-#define SYSFS_PMCSETUP(NAME, ADDRESS) \
+#define __SYSFS_SPRSETUP(NAME, ADDRESS, EXTRA) \
 static void read_##NAME(void *val) \
 { \
        *(unsigned long *)val = mfspr(ADDRESS); \
 } \
 static void write_##NAME(void *val) \
 { \
-       ppc_enable_pmcs(); \
+       EXTRA; \
        mtspr(ADDRESS, *(unsigned long *)val);  \
 } \
 static ssize_t show_##NAME(struct device *dev, \
@@ -140,6 +438,10 @@ static ssize_t __used \
        return count; \
 }
 
+#define SYSFS_PMCSETUP(NAME, ADDRESS)  \
+       __SYSFS_SPRSETUP(NAME, ADDRESS, ppc_enable_pmcs())
+#define SYSFS_SPRSETUP(NAME, ADDRESS)  \
+       __SYSFS_SPRSETUP(NAME, ADDRESS, )
 
 /* Let's define all possible registers, we'll only hook up the ones
  * that are implemented on the current processor
@@ -175,10 +477,10 @@ SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
 SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
 
 SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
-SYSFS_PMCSETUP(purr, SPRN_PURR);
-SYSFS_PMCSETUP(spurr, SPRN_SPURR);
-SYSFS_PMCSETUP(dscr, SPRN_DSCR);
-SYSFS_PMCSETUP(pir, SPRN_PIR);
+SYSFS_SPRSETUP(purr, SPRN_PURR);
+SYSFS_SPRSETUP(spurr, SPRN_SPURR);
+SYSFS_SPRSETUP(dscr, SPRN_DSCR);
+SYSFS_SPRSETUP(pir, SPRN_PIR);
 
 /*
   Lets only enable read for phyp resources and
@@ -249,34 +551,34 @@ SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
 SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
 SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
 #ifdef CONFIG_DEBUG_KERNEL
-SYSFS_PMCSETUP(hid0, SPRN_HID0);
-SYSFS_PMCSETUP(hid1, SPRN_HID1);
-SYSFS_PMCSETUP(hid4, SPRN_HID4);
-SYSFS_PMCSETUP(hid5, SPRN_HID5);
-SYSFS_PMCSETUP(ima0, SPRN_PA6T_IMA0);
-SYSFS_PMCSETUP(ima1, SPRN_PA6T_IMA1);
-SYSFS_PMCSETUP(ima2, SPRN_PA6T_IMA2);
-SYSFS_PMCSETUP(ima3, SPRN_PA6T_IMA3);
-SYSFS_PMCSETUP(ima4, SPRN_PA6T_IMA4);
-SYSFS_PMCSETUP(ima5, SPRN_PA6T_IMA5);
-SYSFS_PMCSETUP(ima6, SPRN_PA6T_IMA6);
-SYSFS_PMCSETUP(ima7, SPRN_PA6T_IMA7);
-SYSFS_PMCSETUP(ima8, SPRN_PA6T_IMA8);
-SYSFS_PMCSETUP(ima9, SPRN_PA6T_IMA9);
-SYSFS_PMCSETUP(imaat, SPRN_PA6T_IMAAT);
-SYSFS_PMCSETUP(btcr, SPRN_PA6T_BTCR);
-SYSFS_PMCSETUP(pccr, SPRN_PA6T_PCCR);
-SYSFS_PMCSETUP(rpccr, SPRN_PA6T_RPCCR);
-SYSFS_PMCSETUP(der, SPRN_PA6T_DER);
-SYSFS_PMCSETUP(mer, SPRN_PA6T_MER);
-SYSFS_PMCSETUP(ber, SPRN_PA6T_BER);
-SYSFS_PMCSETUP(ier, SPRN_PA6T_IER);
-SYSFS_PMCSETUP(sier, SPRN_PA6T_SIER);
-SYSFS_PMCSETUP(siar, SPRN_PA6T_SIAR);
-SYSFS_PMCSETUP(tsr0, SPRN_PA6T_TSR0);
-SYSFS_PMCSETUP(tsr1, SPRN_PA6T_TSR1);
-SYSFS_PMCSETUP(tsr2, SPRN_PA6T_TSR2);
-SYSFS_PMCSETUP(tsr3, SPRN_PA6T_TSR3);
+SYSFS_SPRSETUP(hid0, SPRN_HID0);
+SYSFS_SPRSETUP(hid1, SPRN_HID1);
+SYSFS_SPRSETUP(hid4, SPRN_HID4);
+SYSFS_SPRSETUP(hid5, SPRN_HID5);
+SYSFS_SPRSETUP(ima0, SPRN_PA6T_IMA0);
+SYSFS_SPRSETUP(ima1, SPRN_PA6T_IMA1);
+SYSFS_SPRSETUP(ima2, SPRN_PA6T_IMA2);
+SYSFS_SPRSETUP(ima3, SPRN_PA6T_IMA3);
+SYSFS_SPRSETUP(ima4, SPRN_PA6T_IMA4);
+SYSFS_SPRSETUP(ima5, SPRN_PA6T_IMA5);
+SYSFS_SPRSETUP(ima6, SPRN_PA6T_IMA6);
+SYSFS_SPRSETUP(ima7, SPRN_PA6T_IMA7);
+SYSFS_SPRSETUP(ima8, SPRN_PA6T_IMA8);
+SYSFS_SPRSETUP(ima9, SPRN_PA6T_IMA9);
+SYSFS_SPRSETUP(imaat, SPRN_PA6T_IMAAT);
+SYSFS_SPRSETUP(btcr, SPRN_PA6T_BTCR);
+SYSFS_SPRSETUP(pccr, SPRN_PA6T_PCCR);
+SYSFS_SPRSETUP(rpccr, SPRN_PA6T_RPCCR);
+SYSFS_SPRSETUP(der, SPRN_PA6T_DER);
+SYSFS_SPRSETUP(mer, SPRN_PA6T_MER);
+SYSFS_SPRSETUP(ber, SPRN_PA6T_BER);
+SYSFS_SPRSETUP(ier, SPRN_PA6T_IER);
+SYSFS_SPRSETUP(sier, SPRN_PA6T_SIER);
+SYSFS_SPRSETUP(siar, SPRN_PA6T_SIAR);
+SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0);
+SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1);
+SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2);
+SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3);
 #endif /* CONFIG_DEBUG_KERNEL */
 #endif /* HAS_PPC_PMC_PA6T */
 
@@ -421,6 +723,15 @@ static void register_cpu_online(unsigned int cpu)
                device_create_file(s, &dev_attr_pir);
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
+               device_create_file(s, &dev_attr_pw20_state);
+               device_create_file(s, &dev_attr_pw20_wait_time);
+
+               device_create_file(s, &dev_attr_altivec_idle);
+               device_create_file(s, &dev_attr_altivec_idle_wait_time);
+       }
+#endif
        cacheinfo_cpu_online(cpu);
 }
 
@@ -493,6 +804,15 @@ static void unregister_cpu_online(unsigned int cpu)
                device_remove_file(s, &dev_attr_pir);
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+       if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
+               device_remove_file(s, &dev_attr_pw20_state);
+               device_remove_file(s, &dev_attr_pw20_wait_time);
+
+               device_remove_file(s, &dev_attr_altivec_idle);
+               device_remove_file(s, &dev_attr_altivec_idle_wait_time);
+       }
+#endif
        cacheinfo_cpu_offline(cpu);
 }
 
index b3b144121cc99d64df0c409b0773259770ddf0af..b3dab20acf34abe126e244d34a7dee39021457de 100644 (file)
@@ -510,7 +510,6 @@ void timer_interrupt(struct pt_regs * regs)
         */
        may_hard_irq_enable();
 
-       __get_cpu_var(irq_stat).timer_irqs++;
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
@@ -532,10 +531,15 @@ void timer_interrupt(struct pt_regs * regs)
                *next_tb = ~(u64)0;
                if (evt->event_handler)
                        evt->event_handler(evt);
+               __get_cpu_var(irq_stat).timer_irqs_event++;
        } else {
                now = *next_tb - now;
                if (now <= DECREMENTER_MAX)
                        set_dec((int)now);
+               /* We may have raced with new irq work */
+               if (test_irq_work_pending())
+                       set_dec(1);
+               __get_cpu_var(irq_stat).timer_irqs_others++;
        }
 
 #ifdef CONFIG_PPC64
@@ -801,8 +805,16 @@ static void __init clocksource_init(void)
 static int decrementer_set_next_event(unsigned long evt,
                                      struct clock_event_device *dev)
 {
+       /* Don't adjust the decrementer if some irq work is pending */
+       if (test_irq_work_pending())
+               return 0;
        __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
        set_dec(evt);
+
+       /* We may have raced with new irq work */
+       if (test_irq_work_pending())
+               set_dec(1);
+
        return 0;
 }
 
index 907a472f9a9e4c1db3747a8d4ff22cc1bb133ee8..33cd7a0b8e730b1d22583ab304821a2d1d203cc2 100644 (file)
@@ -285,6 +285,21 @@ void system_reset_exception(struct pt_regs *regs)
 
        /* What should we do here? We could issue a shutdown or hard reset. */
 }
+
+/*
+ * This function is called in real mode. Strictly no printk's please.
+ *
+ * regs->nip and regs->msr contains srr0 and ssr1.
+ */
+long machine_check_early(struct pt_regs *regs)
+{
+       long handled = 0;
+
+       if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
+               handled = cur_cpu_spec->machine_check_early(regs);
+       return handled;
+}
+
 #endif
 
 /*
@@ -1384,7 +1399,6 @@ void fp_unavailable_tm(struct pt_regs *regs)
 
        TM_DEBUG("FP Unavailable trap whilst transactional at 0x%lx, MSR=%lx\n",
                 regs->nip, regs->msr);
-       tm_enable();
 
         /* We can only have got here if the task started using FP after
          * beginning the transaction.  So, the transactional regs are just a
@@ -1393,8 +1407,7 @@ void fp_unavailable_tm(struct pt_regs *regs)
          * transaction, and probably retry but now with FP enabled.  So the
          * checkpointed FP registers need to be loaded.
         */
-       tm_reclaim(&current->thread, current->thread.regs->msr,
-                  TM_CAUSE_FAC_UNAV);
+       tm_reclaim_current(TM_CAUSE_FAC_UNAV);
        /* Reclaim didn't save out any FPRs to transact_fprs. */
 
        /* Enable FP for the task: */
@@ -1403,11 +1416,19 @@ void fp_unavailable_tm(struct pt_regs *regs)
        /* This loads and recheckpoints the FP registers from
         * thread.fpr[].  They will remain in registers after the
         * checkpoint so we don't need to reload them after.
+        * If VMX is in use, the VRs now hold checkpointed values,
+        * so we don't want to load the VRs from the thread_struct.
         */
-       tm_recheckpoint(&current->thread, regs->msr);
+       tm_recheckpoint(&current->thread, MSR_FP);
+
+       /* If VMX is in use, get the transactional values back */
+       if (regs->msr & MSR_VEC) {
+               do_load_up_transact_altivec(&current->thread);
+               /* At this point all the VSX state is loaded, so enable it */
+               regs->msr |= MSR_VSX;
+       }
 }
 
-#ifdef CONFIG_ALTIVEC
 void altivec_unavailable_tm(struct pt_regs *regs)
 {
        /* See the comments in fp_unavailable_tm().  This function operates
@@ -1417,18 +1438,21 @@ void altivec_unavailable_tm(struct pt_regs *regs)
        TM_DEBUG("Vector Unavailable trap whilst transactional at 0x%lx,"
                 "MSR=%lx\n",
                 regs->nip, regs->msr);
-       tm_enable();
-       tm_reclaim(&current->thread, current->thread.regs->msr,
-                  TM_CAUSE_FAC_UNAV);
+       tm_reclaim_current(TM_CAUSE_FAC_UNAV);
        regs->msr |= MSR_VEC;
-       tm_recheckpoint(&current->thread, regs->msr);
+       tm_recheckpoint(&current->thread, MSR_VEC);
        current->thread.used_vr = 1;
+
+       if (regs->msr & MSR_FP) {
+               do_load_up_transact_fpu(&current->thread);
+               regs->msr |= MSR_VSX;
+       }
 }
-#endif
 
-#ifdef CONFIG_VSX
 void vsx_unavailable_tm(struct pt_regs *regs)
 {
+       unsigned long orig_msr = regs->msr;
+
        /* See the comments in fp_unavailable_tm().  This works similarly,
         * though we're loading both FP and VEC registers in here.
         *
@@ -1440,18 +1464,30 @@ void vsx_unavailable_tm(struct pt_regs *regs)
                 "MSR=%lx\n",
                 regs->nip, regs->msr);
 
-       tm_enable();
+       current->thread.used_vsr = 1;
+
+       /* If FP and VMX are already loaded, we have all the state we need */
+       if ((orig_msr & (MSR_FP | MSR_VEC)) == (MSR_FP | MSR_VEC)) {
+               regs->msr |= MSR_VSX;
+               return;
+       }
+
        /* This reclaims FP and/or VR regs if they're already enabled */
-       tm_reclaim(&current->thread, current->thread.regs->msr,
-                  TM_CAUSE_FAC_UNAV);
+       tm_reclaim_current(TM_CAUSE_FAC_UNAV);
 
        regs->msr |= MSR_VEC | MSR_FP | current->thread.fpexc_mode |
                MSR_VSX;
-       /* This loads & recheckpoints FP and VRs. */
-       tm_recheckpoint(&current->thread, regs->msr);
-       current->thread.used_vsr = 1;
+
+       /* This loads & recheckpoints FP and VRs; but we have
+        * to be sure not to overwrite previously-valid state.
+        */
+       tm_recheckpoint(&current->thread, regs->msr & ~orig_msr);
+
+       if (orig_msr & MSR_FP)
+               do_load_up_transact_fpu(&current->thread);
+       if (orig_msr & MSR_VEC)
+               do_load_up_transact_altivec(&current->thread);
 }
-#endif
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 void performance_monitor_exception(struct pt_regs *regs)
index 6e8f507ed32bb5f74f9d9f5574f09636ae15f9a3..79683d0393f5d01577503b02d7d298018647a758 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/page.h>
 
index b8553d62b792ffb2953a400fabdf8fc746c62501..8df9e2463007c1601012aae7062c6a8896ebf9ef 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/page.h>
 
index 0458a9aaba9d135867d6a4263404a8264148a7cd..74f8050518d69034984eaf50c8e34e131842f22c 100644 (file)
@@ -36,6 +36,16 @@ _GLOBAL(do_load_up_transact_altivec)
        blr
 #endif
 
+/*
+ * Enable use of VMX/Altivec for the caller.
+ */
+_GLOBAL(vec_enable)
+       mfmsr   r3
+       oris    r3,r3,MSR_VEC@h
+       MTMSRD(r3)
+       isync
+       blr
+
 /*
  * Load state from memory into VMX registers including VSCR.
  * Assumes the caller has enabled VMX in the MSR.
index 76a64821f4a23653b64cc6ba0e32daec509ee5b5..826d8bd9e5223d94eccfe3639d980e323c78b189 100644 (file)
@@ -518,16 +518,18 @@ static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
                                          struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
+       struct iommu_table *tbl;
        dma_addr_t ret = DMA_ERROR_CODE;
 
-       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+       tbl = get_iommu_table_base(dev);
+       if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)))) {
                atomic_inc(&viodev->cmo.allocs_failed);
                return ret;
        }
 
        ret = dma_iommu_ops.map_page(dev, page, offset, size, direction, attrs);
        if (unlikely(dma_mapping_error(dev, ret))) {
-               vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+               vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
                atomic_inc(&viodev->cmo.allocs_failed);
        }
 
@@ -540,10 +542,12 @@ static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
                                     struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
+       struct iommu_table *tbl;
 
+       tbl = get_iommu_table_base(dev);
        dma_iommu_ops.unmap_page(dev, dma_handle, size, direction, attrs);
 
-       vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+       vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
 }
 
 static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
@@ -551,12 +555,14 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
                                 struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
+       struct iommu_table *tbl;
        struct scatterlist *sgl;
        int ret, count = 0;
        size_t alloc_size = 0;
 
+       tbl = get_iommu_table_base(dev);
        for (sgl = sglist; count < nelems; count++, sgl++)
-               alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE);
+               alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl));
 
        if (vio_cmo_alloc(viodev, alloc_size)) {
                atomic_inc(&viodev->cmo.allocs_failed);
@@ -572,7 +578,7 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
        }
 
        for (sgl = sglist, count = 0; count < ret; count++, sgl++)
-               alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+               alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
        if (alloc_size)
                vio_cmo_dealloc(viodev, alloc_size);
 
@@ -585,12 +591,14 @@ static void vio_dma_iommu_unmap_sg(struct device *dev,
                struct dma_attrs *attrs)
 {
        struct vio_dev *viodev = to_vio_dev(dev);
+       struct iommu_table *tbl;
        struct scatterlist *sgl;
        size_t alloc_size = 0;
        int count = 0;
 
+       tbl = get_iommu_table_base(dev);
        for (sgl = sglist; count < nelems; count++, sgl++)
-               alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE);
+               alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
 
        dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
 
@@ -706,11 +714,14 @@ static int vio_cmo_bus_probe(struct vio_dev *viodev)
 {
        struct vio_cmo_dev_entry *dev_ent;
        struct device *dev = &viodev->dev;
+       struct iommu_table *tbl;
        struct vio_driver *viodrv = to_vio_driver(dev->driver);
        unsigned long flags;
        size_t size;
        bool dma_capable = false;
 
+       tbl = get_iommu_table_base(dev);
+
        /* A device requires entitlement if it has a DMA window property */
        switch (viodev->family) {
        case VDEVICE:
@@ -736,7 +747,8 @@ static int vio_cmo_bus_probe(struct vio_dev *viodev)
                        return -EINVAL;
                }
 
-               viodev->cmo.desired = IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev));
+               viodev->cmo.desired =
+                       IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev), tbl);
                if (viodev->cmo.desired < VIO_CMO_MIN_ENT)
                        viodev->cmo.desired = VIO_CMO_MIN_ENT;
                size = VIO_CMO_MIN_ENT;
@@ -1176,9 +1188,10 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
                            &tbl->it_index, &offset, &size);
 
        /* TCE table size - measured in tce entries */
-       tbl->it_size = size >> IOMMU_PAGE_SHIFT;
+       tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
+       tbl->it_size = size >> tbl->it_page_shift;
        /* offset for VIO should always be 0 */
-       tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
+       tbl->it_offset = offset >> tbl->it_page_shift;
        tbl->it_busno = 0;
        tbl->it_type = TCE_VB;
        tbl->it_blocksize = 16;
index a353c485808c6ea203eac428106b5fdf41943b36..768a9f977c001ee73e6d5aa2f0b8ee44ea3b35f5 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kvm_host.h>
 #include <linux/kernel.h>
 #include <asm/opal.h>
+#include <asm/mce.h>
 
 /* SRR1 bits for machine check on POWER7 */
 #define SRR1_MC_LDSTERR                (1ul << (63-42))
@@ -58,18 +59,6 @@ static void reload_slb(struct kvm_vcpu *vcpu)
        }
 }
 
-/* POWER7 TLB flush */
-static void flush_tlb_power7(struct kvm_vcpu *vcpu)
-{
-       unsigned long i, rb;
-
-       rb = TLBIEL_INVAL_SET_LPID;
-       for (i = 0; i < POWER7_TLB_SETS; ++i) {
-               asm volatile("tlbiel %0" : : "r" (rb));
-               rb += 1 << TLBIEL_INVAL_SET_SHIFT;
-       }
-}
-
 /*
  * On POWER7, see if we can handle a machine check that occurred inside
  * the guest in real mode, without switching to the host partition.
@@ -79,9 +68,7 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu)
 static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
 {
        unsigned long srr1 = vcpu->arch.shregs.msr;
-#ifdef CONFIG_PPC_POWERNV
-       struct opal_machine_check_event *opal_evt;
-#endif
+       struct machine_check_event mce_evt;
        long handled = 1;
 
        if (srr1 & SRR1_MC_LDSTERR) {
@@ -96,7 +83,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
                                   DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
                }
                if (dsisr & DSISR_MC_TLB_MULTI) {
-                       flush_tlb_power7(vcpu);
+                       if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                               cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
                        dsisr &= ~DSISR_MC_TLB_MULTI;
                }
                /* Any other errors we don't understand? */
@@ -113,28 +101,38 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
                reload_slb(vcpu);
                break;
        case SRR1_MC_IFETCH_TLBMULTI:
-               flush_tlb_power7(vcpu);
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
                break;
        default:
                handled = 0;
        }
 
-#ifdef CONFIG_PPC_POWERNV
        /*
-        * See if OPAL has already handled the condition.
-        * We assume that if the condition is recovered then OPAL
+        * See if we have already handled the condition in the linux host.
+        * We assume that if the condition is recovered then linux host
         * will have generated an error log event that we will pick
         * up and log later.
+        * Don't release mce event now. In case if condition is not
+        * recovered we do guest exit and go back to linux host machine
+        * check handler. Hence we need make sure that current mce event
+        * is available for linux host to consume.
         */
-       opal_evt = local_paca->opal_mc_evt;
-       if (opal_evt->version == OpalMCE_V1 &&
-           (opal_evt->severity == OpalMCE_SEV_NO_ERROR ||
-            opal_evt->disposition == OpalMCE_DISPOSITION_RECOVERED))
+       if (!get_mce_event(&mce_evt, MCE_EVENT_DONTRELEASE))
+               goto out;
+
+       if (mce_evt.version == MCE_V1 &&
+           (mce_evt.severity == MCE_SEV_NO_ERROR ||
+            mce_evt.disposition == MCE_DISPOSITION_RECOVERED))
                handled = 1;
 
+out:
+       /*
+        * If we have handled the error, then release the mce event because
+        * we will be delivering machine check to guest.
+        */
        if (handled)
-               opal_evt->in_use = 0;
-#endif
+               release_mce_event();
 
        return handled;
 }
index e8ed7d659c55f8cbcdc341c07ea58a8bc26b744d..a0d6929d867844f36cc61a8138b24c6be4362579 100644 (file)
@@ -319,6 +319,8 @@ kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
        SPRN_DSRR0, SPRN_DSRR1, 0
 kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
        SPRN_CSRR0, SPRN_CSRR1, 0
+kvm_handler BOOKE_INTERRUPT_LRAT_ERROR, EX_PARAMS(GEN), \
+       SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
 #else
 /*
  * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
index 17e5b23643124347febe56a05f5deb7e1a2e361e..d5edbeb8eb8209e61a9d6524acfa565e3f30782f 100644 (file)
@@ -159,6 +159,21 @@ unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
        return 0;
 }
 
+#ifdef CONFIG_PPC_BOOK3E_64
+void __patch_exception(int exc, unsigned long addr)
+{
+       extern unsigned int interrupt_base_book3e;
+       unsigned int *ibase = &interrupt_base_book3e;
+
+       /* Our exceptions vectors start with a NOP and -then- a branch
+        * to deal with single stepping from userspace which stops on
+        * the second instruction. Thus we need to patch the second
+        * instruction of the exception, not the first one
+        */
+
+       patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
+#endif
 
 #ifdef CONFIG_CODE_PATCHING_SELFTEST
 
index b2c68ce139aecbc6819ff8f6493dde59c749fa7e..a5b30c71a8d3f863d6717d0cf51503dbb8387df9 100644 (file)
@@ -231,6 +231,87 @@ _GLOBAL(_rest32gpr_31_x)
        mr      1,11
        blr
 
+#ifdef CONFIG_ALTIVEC
+/* Called with r0 pointing just beyond the end of the vector save area.  */
+
+_GLOBAL(_savevr_20)
+       li      r11,-192
+       stvx    vr20,r11,r0
+_GLOBAL(_savevr_21)
+       li      r11,-176
+       stvx    vr21,r11,r0
+_GLOBAL(_savevr_22)
+       li      r11,-160
+       stvx    vr22,r11,r0
+_GLOBAL(_savevr_23)
+       li      r11,-144
+       stvx    vr23,r11,r0
+_GLOBAL(_savevr_24)
+       li      r11,-128
+       stvx    vr24,r11,r0
+_GLOBAL(_savevr_25)
+       li      r11,-112
+       stvx    vr25,r11,r0
+_GLOBAL(_savevr_26)
+       li      r11,-96
+       stvx    vr26,r11,r0
+_GLOBAL(_savevr_27)
+       li      r11,-80
+       stvx    vr27,r11,r0
+_GLOBAL(_savevr_28)
+       li      r11,-64
+       stvx    vr28,r11,r0
+_GLOBAL(_savevr_29)
+       li      r11,-48
+       stvx    vr29,r11,r0
+_GLOBAL(_savevr_30)
+       li      r11,-32
+       stvx    vr30,r11,r0
+_GLOBAL(_savevr_31)
+       li      r11,-16
+       stvx    vr31,r11,r0
+       blr
+
+_GLOBAL(_restvr_20)
+       li      r11,-192
+       lvx     vr20,r11,r0
+_GLOBAL(_restvr_21)
+       li      r11,-176
+       lvx     vr21,r11,r0
+_GLOBAL(_restvr_22)
+       li      r11,-160
+       lvx     vr22,r11,r0
+_GLOBAL(_restvr_23)
+       li      r11,-144
+       lvx     vr23,r11,r0
+_GLOBAL(_restvr_24)
+       li      r11,-128
+       lvx     vr24,r11,r0
+_GLOBAL(_restvr_25)
+       li      r11,-112
+       lvx     vr25,r11,r0
+_GLOBAL(_restvr_26)
+       li      r11,-96
+       lvx     vr26,r11,r0
+_GLOBAL(_restvr_27)
+       li      r11,-80
+       lvx     vr27,r11,r0
+_GLOBAL(_restvr_28)
+       li      r11,-64
+       lvx     vr28,r11,r0
+_GLOBAL(_restvr_29)
+       li      r11,-48
+       lvx     vr29,r11,r0
+_GLOBAL(_restvr_30)
+       li      r11,-32
+       lvx     vr30,r11,r0
+_GLOBAL(_restvr_31)
+       li      r11,-16
+       lvx     vr31,r11,r0
+       blr
+
+#endif /* CONFIG_ALTIVEC */
+
 #else /* CONFIG_PPC64 */
 
        .section ".text.save.restore","ax",@progbits
@@ -356,6 +437,111 @@ _restgpr0_31:
        mtlr    r0
        blr
 
+#ifdef CONFIG_ALTIVEC
+/* Called with r0 pointing just beyond the end of the vector save area.  */
+
+.globl _savevr_20
+_savevr_20:
+       li      r12,-192
+       stvx    vr20,r12,r0
+.globl _savevr_21
+_savevr_21:
+       li      r12,-176
+       stvx    vr21,r12,r0
+.globl _savevr_22
+_savevr_22:
+       li      r12,-160
+       stvx    vr22,r12,r0
+.globl _savevr_23
+_savevr_23:
+       li      r12,-144
+       stvx    vr23,r12,r0
+.globl _savevr_24
+_savevr_24:
+       li      r12,-128
+       stvx    vr24,r12,r0
+.globl _savevr_25
+_savevr_25:
+       li      r12,-112
+       stvx    vr25,r12,r0
+.globl _savevr_26
+_savevr_26:
+       li      r12,-96
+       stvx    vr26,r12,r0
+.globl _savevr_27
+_savevr_27:
+       li      r12,-80
+       stvx    vr27,r12,r0
+.globl _savevr_28
+_savevr_28:
+       li      r12,-64
+       stvx    vr28,r12,r0
+.globl _savevr_29
+_savevr_29:
+       li      r12,-48
+       stvx    vr29,r12,r0
+.globl _savevr_30
+_savevr_30:
+       li      r12,-32
+       stvx    vr30,r12,r0
+.globl _savevr_31
+_savevr_31:
+       li      r12,-16
+       stvx    vr31,r12,r0
+       blr
+
+.globl _restvr_20
+_restvr_20:
+       li      r12,-192
+       lvx     vr20,r12,r0
+.globl _restvr_21
+_restvr_21:
+       li      r12,-176
+       lvx     vr21,r12,r0
+.globl _restvr_22
+_restvr_22:
+       li      r12,-160
+       lvx     vr22,r12,r0
+.globl _restvr_23
+_restvr_23:
+       li      r12,-144
+       lvx     vr23,r12,r0
+.globl _restvr_24
+_restvr_24:
+       li      r12,-128
+       lvx     vr24,r12,r0
+.globl _restvr_25
+_restvr_25:
+       li      r12,-112
+       lvx     vr25,r12,r0
+.globl _restvr_26
+_restvr_26:
+       li      r12,-96
+       lvx     vr26,r12,r0
+.globl _restvr_27
+_restvr_27:
+       li      r12,-80
+       lvx     vr27,r12,r0
+.globl _restvr_28
+_restvr_28:
+       li      r12,-64
+       lvx     vr28,r12,r0
+.globl _restvr_29
+_restvr_29:
+       li      r12,-48
+       lvx     vr29,r12,r0
+.globl _restvr_30
+_restvr_30:
+       li      r12,-32
+       lvx     vr30,r12,r0
+.globl _restvr_31
+_restvr_31:
+       li      r12,-16
+       lvx     vr31,r12,r0
+       blr
+
+#endif /* CONFIG_ALTIVEC */
+
 #endif /* CONFIG_PPC64 */
 
 #endif
index a73f0884d358d0d9095c992d6c532929f853044c..28337c9709ae60c326bbe9e67364b9fe3c19796e 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/prctl.h>
 
 #include <asm/uaccess.h>
 #include <asm/reg.h>
@@ -275,21 +276,13 @@ int do_spe_mathemu(struct pt_regs *regs)
 
                case EFSCTSF:
                case EFSCTUF:
-                       if (!((vb.wp[1] >> 23) == 0xff && ((vb.wp[1] & 0x7fffff) > 0))) {
-                               /* NaN */
-                               if (((vb.wp[1] >> 23) & 0xff) == 0) {
-                                       /* denorm */
-                                       vc.wp[1] = 0x0;
-                               } else if ((vb.wp[1] >> 31) == 0) {
-                                       /* positive normal */
-                                       vc.wp[1] = (func == EFSCTSF) ?
-                                               0x7fffffff : 0xffffffff;
-                               } else { /* negative normal */
-                                       vc.wp[1] = (func == EFSCTSF) ?
-                                               0x80000000 : 0x0;
-                               }
-                       } else { /* rB is NaN */
-                               vc.wp[1] = 0x0;
+                       if (SB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               SB_e += (func == EFSCTSF ? 31 : 32);
+                               FP_TO_INT_ROUND_S(vc.wp[1], SB, 32,
+                                               (func == EFSCTSF));
                        }
                        goto update_regs;
 
@@ -306,16 +299,25 @@ int do_spe_mathemu(struct pt_regs *regs)
                }
 
                case EFSCTSI:
-               case EFSCTSIZ:
                case EFSCTUI:
+                       if (SB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_ROUND_S(vc.wp[1], SB, 32,
+                                               ((func & 0x3) != 0));
+                       }
+                       goto update_regs;
+
+               case EFSCTSIZ:
                case EFSCTUIZ:
-                       if (func & 0x4) {
-                               _FP_ROUND(1, SB);
+                       if (SB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
                        } else {
-                               _FP_ROUND_ZERO(1, SB);
+                               FP_TO_INT_S(vc.wp[1], SB, 32,
+                                               ((func & 0x3) != 0));
                        }
-                       FP_TO_INT_S(vc.wp[1], SB, 32,
-                                       (((func & 0x3) != 0) || SB_s));
                        goto update_regs;
 
                default:
@@ -404,22 +406,13 @@ cmp_s:
 
                case EFDCTSF:
                case EFDCTUF:
-                       if (!((vb.wp[0] >> 20) == 0x7ff &&
-                          ((vb.wp[0] & 0xfffff) > 0 || (vb.wp[1] > 0)))) {
-                               /* not a NaN */
-                               if (((vb.wp[0] >> 20) & 0x7ff) == 0) {
-                                       /* denorm */
-                                       vc.wp[1] = 0x0;
-                               } else if ((vb.wp[0] >> 31) == 0) {
-                                       /* positive normal */
-                                       vc.wp[1] = (func == EFDCTSF) ?
-                                               0x7fffffff : 0xffffffff;
-                               } else { /* negative normal */
-                                       vc.wp[1] = (func == EFDCTSF) ?
-                                               0x80000000 : 0x0;
-                               }
-                       } else { /* NaN */
-                               vc.wp[1] = 0x0;
+                       if (DB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               DB_e += (func == EFDCTSF ? 31 : 32);
+                               FP_TO_INT_ROUND_D(vc.wp[1], DB, 32,
+                                               (func == EFDCTSF));
                        }
                        goto update_regs;
 
@@ -437,21 +430,35 @@ cmp_s:
 
                case EFDCTUIDZ:
                case EFDCTSIDZ:
-                       _FP_ROUND_ZERO(2, DB);
-                       FP_TO_INT_D(vc.dp[0], DB, 64, ((func & 0x1) == 0));
+                       if (DB_c == FP_CLS_NAN) {
+                               vc.dp[0] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_D(vc.dp[0], DB, 64,
+                                               ((func & 0x1) == 0));
+                       }
                        goto update_regs;
 
                case EFDCTUI:
                case EFDCTSI:
+                       if (DB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_ROUND_D(vc.wp[1], DB, 32,
+                                               ((func & 0x3) != 0));
+                       }
+                       goto update_regs;
+
                case EFDCTUIZ:
                case EFDCTSIZ:
-                       if (func & 0x4) {
-                               _FP_ROUND(2, DB);
+                       if (DB_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
                        } else {
-                               _FP_ROUND_ZERO(2, DB);
+                               FP_TO_INT_D(vc.wp[1], DB, 32,
+                                               ((func & 0x3) != 0));
                        }
-                       FP_TO_INT_D(vc.wp[1], DB, 32,
-                                       (((func & 0x3) != 0) || DB_s));
                        goto update_regs;
 
                default:
@@ -556,37 +563,60 @@ cmp_d:
                        cmp = -1;
                        goto cmp_vs;
 
-               case EVFSCTSF:
-                       __asm__ __volatile__ ("mtspr 512, %4\n"
-                               "efsctsf %0, %2\n"
-                               "efsctsf %1, %3\n"
-                               : "=r" (vc.wp[0]), "=r" (vc.wp[1])
-                               : "r" (vb.wp[0]), "r" (vb.wp[1]), "r" (0));
-                       goto update_regs;
-
                case EVFSCTUF:
-                       __asm__ __volatile__ ("mtspr 512, %4\n"
-                               "efsctuf %0, %2\n"
-                               "efsctuf %1, %3\n"
-                               : "=r" (vc.wp[0]), "=r" (vc.wp[1])
-                               : "r" (vb.wp[0]), "r" (vb.wp[1]), "r" (0));
+               case EVFSCTSF:
+                       if (SB0_c == FP_CLS_NAN) {
+                               vc.wp[0] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               SB0_e += (func == EVFSCTSF ? 31 : 32);
+                               FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32,
+                                               (func == EVFSCTSF));
+                       }
+                       if (SB1_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               SB1_e += (func == EVFSCTSF ? 31 : 32);
+                               FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32,
+                                               (func == EVFSCTSF));
+                       }
                        goto update_regs;
 
                case EVFSCTUI:
                case EVFSCTSI:
+                       if (SB0_c == FP_CLS_NAN) {
+                               vc.wp[0] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32,
+                                               ((func & 0x3) != 0));
+                       }
+                       if (SB1_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32,
+                                               ((func & 0x3) != 0));
+                       }
+                       goto update_regs;
+
                case EVFSCTUIZ:
                case EVFSCTSIZ:
-                       if (func & 0x4) {
-                               _FP_ROUND(1, SB0);
-                               _FP_ROUND(1, SB1);
+                       if (SB0_c == FP_CLS_NAN) {
+                               vc.wp[0] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
                        } else {
-                               _FP_ROUND_ZERO(1, SB0);
-                               _FP_ROUND_ZERO(1, SB1);
+                               FP_TO_INT_S(vc.wp[0], SB0, 32,
+                                               ((func & 0x3) != 0));
+                       }
+                       if (SB1_c == FP_CLS_NAN) {
+                               vc.wp[1] = 0;
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       } else {
+                               FP_TO_INT_S(vc.wp[1], SB1, 32,
+                                               ((func & 0x3) != 0));
                        }
-                       FP_TO_INT_S(vc.wp[0], SB0, 32,
-                                       (((func & 0x3) != 0) || SB0_s));
-                       FP_TO_INT_S(vc.wp[1], SB1, 32,
-                                       (((func & 0x3) != 0) || SB1_s));
                        goto update_regs;
 
                default:
@@ -630,9 +660,27 @@ update_ccr:
        regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2));
 
 update_regs:
-       __FPU_FPSCR &= ~FP_EX_MASK;
+       /*
+        * If the "invalid" exception sticky bit was set by the
+        * processor for non-finite input, but was not set before the
+        * instruction being emulated, clear it.  Likewise for the
+        * "underflow" bit, which may have been set by the processor
+        * for exact underflow, not just inexact underflow when the
+        * flag should be set for IEEE 754 semantics.  Other sticky
+        * exceptions will only be set by the processor when they are
+        * correct according to IEEE 754 semantics, and we must not
+        * clear sticky bits that were already set before the emulated
+        * instruction as they represent the user-visible sticky
+        * exception status.  "inexact" traps to kernel are not
+        * required for IEEE semantics and are not enabled by default,
+        * so the "inexact" sticky bit may have been set by a previous
+        * instruction without the kernel being aware of it.
+        */
+       __FPU_FPSCR
+         &= ~(FP_EX_INVALID | FP_EX_UNDERFLOW) | current->thread.spefscr_last;
        __FPU_FPSCR |= (FP_CUR_EXCEPTIONS & FP_EX_MASK);
        mtspr(SPRN_SPEFSCR, __FPU_FPSCR);
+       current->thread.spefscr_last = __FPU_FPSCR;
 
        current->thread.evr[fc] = vc.wp[0];
        regs->gpr[fc] = vc.wp[1];
@@ -644,6 +692,23 @@ update_regs:
        pr_debug("va: %08x  %08x\n", va.wp[0], va.wp[1]);
        pr_debug("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
 
+       if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) {
+               if ((FP_CUR_EXCEPTIONS & FP_EX_DIVZERO)
+                   && (current->thread.fpexc_mode & PR_FP_EXC_DIV))
+                       return 1;
+               if ((FP_CUR_EXCEPTIONS & FP_EX_OVERFLOW)
+                   && (current->thread.fpexc_mode & PR_FP_EXC_OVF))
+                       return 1;
+               if ((FP_CUR_EXCEPTIONS & FP_EX_UNDERFLOW)
+                   && (current->thread.fpexc_mode & PR_FP_EXC_UND))
+                       return 1;
+               if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)
+                   && (current->thread.fpexc_mode & PR_FP_EXC_RES))
+                       return 1;
+               if ((FP_CUR_EXCEPTIONS & FP_EX_INVALID)
+                   && (current->thread.fpexc_mode & PR_FP_EXC_INV))
+                       return 1;
+       }
        return 0;
 
 illegal:
@@ -662,21 +727,28 @@ int speround_handler(struct pt_regs *regs)
 {
        union dw_union fgpr;
        int s_lo, s_hi;
-       unsigned long speinsn, type, fc;
+       int lo_inexact, hi_inexact;
+       int fp_result;
+       unsigned long speinsn, type, fb, fc, fptype, func;
 
        if (get_user(speinsn, (unsigned int __user *) regs->nip))
                return -EFAULT;
        if ((speinsn >> 26) != 4)
                return -EINVAL;         /* not an spe instruction */
 
-       type = insn_type(speinsn & 0x7ff);
+       func = speinsn & 0x7ff;
+       type = insn_type(func);
        if (type == XCR) return -ENOSYS;
 
        __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
        pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
 
+       fptype = (speinsn >> 5) & 0x7;
+
        /* No need to round if the result is exact */
-       if (!(__FPU_FPSCR & FP_EX_INEXACT))
+       lo_inexact = __FPU_FPSCR & (SPEFSCR_FG | SPEFSCR_FX);
+       hi_inexact = __FPU_FPSCR & (SPEFSCR_FGH | SPEFSCR_FXH);
+       if (!(lo_inexact || (hi_inexact && fptype == VCT)))
                return 0;
 
        fc = (speinsn >> 21) & 0x1f;
@@ -685,9 +757,68 @@ int speround_handler(struct pt_regs *regs)
        fgpr.wp[0] = current->thread.evr[fc];
        fgpr.wp[1] = regs->gpr[fc];
 
+       fb = (speinsn >> 11) & 0x1f;
+       switch (func) {
+       case EFSCTUIZ:
+       case EFSCTSIZ:
+       case EVFSCTUIZ:
+       case EVFSCTSIZ:
+       case EFDCTUIDZ:
+       case EFDCTSIDZ:
+       case EFDCTUIZ:
+       case EFDCTSIZ:
+               /*
+                * These instructions always round to zero,
+                * independent of the rounding mode.
+                */
+               return 0;
+
+       case EFSCTUI:
+       case EFSCTUF:
+       case EVFSCTUI:
+       case EVFSCTUF:
+       case EFDCTUI:
+       case EFDCTUF:
+               fp_result = 0;
+               s_lo = 0;
+               s_hi = 0;
+               break;
+
+       case EFSCTSI:
+       case EFSCTSF:
+               fp_result = 0;
+               /* Recover the sign of a zero result if possible.  */
+               if (fgpr.wp[1] == 0)
+                       s_lo = regs->gpr[fb] & SIGN_BIT_S;
+               break;
+
+       case EVFSCTSI:
+       case EVFSCTSF:
+               fp_result = 0;
+               /* Recover the sign of a zero result if possible.  */
+               if (fgpr.wp[1] == 0)
+                       s_lo = regs->gpr[fb] & SIGN_BIT_S;
+               if (fgpr.wp[0] == 0)
+                       s_hi = current->thread.evr[fb] & SIGN_BIT_S;
+               break;
+
+       case EFDCTSI:
+       case EFDCTSF:
+               fp_result = 0;
+               s_hi = s_lo;
+               /* Recover the sign of a zero result if possible.  */
+               if (fgpr.wp[1] == 0)
+                       s_hi = current->thread.evr[fb] & SIGN_BIT_S;
+               break;
+
+       default:
+               fp_result = 1;
+               break;
+       }
+
        pr_debug("round fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
-       switch ((speinsn >> 5) & 0x7) {
+       switch (fptype) {
        /* Since SPE instructions on E500 core can handle round to nearest
         * and round toward zero with IEEE-754 complied, we just need
         * to handle round toward +Inf and round toward -Inf by software.
@@ -696,25 +827,52 @@ int speround_handler(struct pt_regs *regs)
                if ((FP_ROUNDMODE) == FP_RND_PINF) {
                        if (!s_lo) fgpr.wp[1]++; /* Z > 0, choose Z1 */
                } else { /* round to -Inf */
-                       if (s_lo) fgpr.wp[1]++; /* Z < 0, choose Z2 */
+                       if (s_lo) {
+                               if (fp_result)
+                                       fgpr.wp[1]++; /* Z < 0, choose Z2 */
+                               else
+                                       fgpr.wp[1]--; /* Z < 0, choose Z2 */
+                       }
                }
                break;
 
        case DPFP:
                if (FP_ROUNDMODE == FP_RND_PINF) {
-                       if (!s_hi) fgpr.dp[0]++; /* Z > 0, choose Z1 */
+                       if (!s_hi) {
+                               if (fp_result)
+                                       fgpr.dp[0]++; /* Z > 0, choose Z1 */
+                               else
+                                       fgpr.wp[1]++; /* Z > 0, choose Z1 */
+                       }
                } else { /* round to -Inf */
-                       if (s_hi) fgpr.dp[0]++; /* Z < 0, choose Z2 */
+                       if (s_hi) {
+                               if (fp_result)
+                                       fgpr.dp[0]++; /* Z < 0, choose Z2 */
+                               else
+                                       fgpr.wp[1]--; /* Z < 0, choose Z2 */
+                       }
                }
                break;
 
        case VCT:
                if (FP_ROUNDMODE == FP_RND_PINF) {
-                       if (!s_lo) fgpr.wp[1]++; /* Z_low > 0, choose Z1 */
-                       if (!s_hi) fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */
+                       if (lo_inexact && !s_lo)
+                               fgpr.wp[1]++; /* Z_low > 0, choose Z1 */
+                       if (hi_inexact && !s_hi)
+                               fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */
                } else { /* round to -Inf */
-                       if (s_lo) fgpr.wp[1]++; /* Z_low < 0, choose Z2 */
-                       if (s_hi) fgpr.wp[0]++; /* Z_high < 0, choose Z2 */
+                       if (lo_inexact && s_lo) {
+                               if (fp_result)
+                                       fgpr.wp[1]++; /* Z_low < 0, choose Z2 */
+                               else
+                                       fgpr.wp[1]--; /* Z_low < 0, choose Z2 */
+                       }
+                       if (hi_inexact && s_hi) {
+                               if (fp_result)
+                                       fgpr.wp[0]++; /* Z_high < 0, choose Z2 */
+                               else
+                                       fgpr.wp[0]--; /* Z_high < 0, choose Z2 */
+                       }
                }
                break;
 
@@ -727,6 +885,8 @@ int speround_handler(struct pt_regs *regs)
 
        pr_debug("  to fgpr: %08x  %08x\n", fgpr.wp[0], fgpr.wp[1]);
 
+       if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
+               return (current->thread.fpexc_mode & PR_FP_EXC_RES) ? 1 : 0;
        return 0;
 }
 
index 07ba45b0f07c8ed311313c14fdf4422613639e0e..94cd728166d37a1be14a8867ec1ea2f059249d96 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
+#include <asm/paca.h>
 
 #include "mmu_decl.h"
 
@@ -171,11 +172,10 @@ unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
        return 1UL << camsize;
 }
 
-unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
+static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
+                                       unsigned long ram, int max_cam_idx)
 {
        int i;
-       unsigned long virt = PAGE_OFFSET;
-       phys_addr_t phys = memstart_addr;
        unsigned long amount_mapped = 0;
 
        /* Calculate CAM values */
@@ -192,9 +192,23 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
        }
        tlbcam_index = i;
 
+#ifdef CONFIG_PPC64
+       get_paca()->tcd.esel_next = i;
+       get_paca()->tcd.esel_max = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+       get_paca()->tcd.esel_first = i;
+#endif
+
        return amount_mapped;
 }
 
+unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx)
+{
+       unsigned long virt = PAGE_OFFSET;
+       phys_addr_t phys = memstart_addr;
+
+       return map_mem_in_cams_addr(phys, virt, ram, max_cam_idx);
+}
+
 #ifdef CONFIG_PPC32
 
 #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS)
@@ -222,7 +236,9 @@ void __init adjust_total_lowmem(void)
        /* adjust lowmem size to __max_low_memory */
        ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem);
 
+       i = switch_to_as1();
        __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM);
+       restore_to_as0(i, 0, 0, 1);
 
        pr_info("Memory CAM mapping: ");
        for (i = 0; i < tlbcam_index - 1; i++)
@@ -241,4 +257,62 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
        /* 64M mapped initially according to head_fsl_booke.S */
        memblock_set_current_limit(min_t(u64, limit, 0x04000000));
 }
+
+#ifdef CONFIG_RELOCATABLE
+int __initdata is_second_reloc;
+notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
+{
+       unsigned long base = KERNELBASE;
+
+       kernstart_addr = start;
+       if (is_second_reloc) {
+               virt_phys_offset = PAGE_OFFSET - memstart_addr;
+               return;
+       }
+
+       /*
+        * Relocatable kernel support based on processing of dynamic
+        * relocation entries. Before we get the real memstart_addr,
+        * We will compute the virt_phys_offset like this:
+        * virt_phys_offset = stext.run - kernstart_addr
+        *
+        * stext.run = (KERNELBASE & ~0x3ffffff) +
+        *                              (kernstart_addr & 0x3ffffff)
+        * When we relocate, we have :
+        *
+        *      (kernstart_addr & 0x3ffffff) = (stext.run & 0x3ffffff)
+        *
+        * hence:
+        *  virt_phys_offset = (KERNELBASE & ~0x3ffffff) -
+        *                              (kernstart_addr & ~0x3ffffff)
+        *
+        */
+       start &= ~0x3ffffff;
+       base &= ~0x3ffffff;
+       virt_phys_offset = base - start;
+       early_get_first_memblock_info(__va(dt_ptr), NULL);
+       /*
+        * We now get the memstart_addr, then we should check if this
+        * address is the same as what the PAGE_OFFSET map to now. If
+        * not we have to change the map of PAGE_OFFSET to memstart_addr
+        * and do a second relocation.
+        */
+       if (start != memstart_addr) {
+               int n;
+               long offset = start - memstart_addr;
+
+               is_second_reloc = 1;
+               n = switch_to_as1();
+               /* map a 64M area for the second relocation */
+               if (memstart_addr > start)
+                       map_mem_in_cams(0x4000000, CONFIG_LOWMEM_CAM_NUM);
+               else
+                       map_mem_in_cams_addr(start, PAGE_OFFSET + offset,
+                                       0x4000000, CONFIG_LOWMEM_CAM_NUM);
+               restore_to_as0(n, offset, __va(dt_ptr), 1);
+               /* We should never reach here */
+               panic("Relocation error");
+       }
+}
+#endif
 #endif
index d3cbda62857b92ffb0867c4fe0ab1deeb0979313..1136d26a95ae02ac075914e13f54720864b71fea 100644 (file)
@@ -148,7 +148,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r30,r0               /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...) 
@@ -457,7 +460,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r3,r0                /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...)
@@ -795,7 +801,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r30,r0               /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...)
index 6176b3cdf57991590df2b26f42f27eed593096bb..de6881259aef3bd552c53ea77751093336e2e5be 100644 (file)
@@ -169,9 +169,10 @@ static unsigned long htab_convert_pte_flags(unsigned long pteflags)
        if ((pteflags & _PAGE_USER) && !((pteflags & _PAGE_RW) &&
                                         (pteflags & _PAGE_DIRTY)))
                rflags |= 1;
-
-       /* Always add C */
-       return rflags | HPTE_R_C;
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       return rflags | HPTE_R_C | HPTE_R_M;
 }
 
 int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
index 34de9e0cdc3466313eea62bbdd7079df409547c8..826893fcb3a78b0198d5fa4b0b047428d8852802 100644 (file)
@@ -127,7 +127,11 @@ repeat:
 
                /* Add in WIMG bits */
                rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
-                                     _PAGE_COHERENT | _PAGE_GUARDED));
+                                     _PAGE_GUARDED));
+               /*
+                * enable the memory coherence always
+                */
+               rflags |= HPTE_R_M;
 
                /* Insert into the hash table, primary slot */
                slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
index 74551b5e41e5156b0720c65ec9cdd1adf988260a..5e4ee2573903eb1af940ac1927c6be61c78fc8a9 100644 (file)
@@ -8,6 +8,44 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 
+#ifdef CONFIG_PPC_FSL_BOOK3E
+#ifdef CONFIG_PPC64
+static inline int tlb1_next(void)
+{
+       struct paca_struct *paca = get_paca();
+       struct tlb_core_data *tcd;
+       int this, next;
+
+       tcd = paca->tcd_ptr;
+       this = tcd->esel_next;
+
+       next = this + 1;
+       if (next >= tcd->esel_max)
+               next = tcd->esel_first;
+
+       tcd->esel_next = next;
+       return this;
+}
+#else
+static inline int tlb1_next(void)
+{
+       int index, ncams;
+
+       ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
+
+       index = __get_cpu_var(next_tlbcam_idx);
+
+       /* Just round-robin the entries and wrap when we hit the end */
+       if (unlikely(index == ncams - 1))
+               __get_cpu_var(next_tlbcam_idx) = tlbcam_index;
+       else
+               __get_cpu_var(next_tlbcam_idx)++;
+
+       return index;
+}
+#endif /* !PPC64 */
+#endif /* FSL */
+
 static inline int mmu_get_tsize(int psize)
 {
        return mmu_psize_defs[psize].enc;
@@ -47,7 +85,7 @@ void book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea,
        struct mm_struct *mm;
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
-       int index, ncams;
+       int index;
 #endif
 
        if (unlikely(is_kernel_addr(ea)))
@@ -77,18 +115,11 @@ void book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea,
        }
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
-       ncams = mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY;
-
        /* We have to use the CAM(TLB1) on FSL parts for hugepages */
-       index = __get_cpu_var(next_tlbcam_idx);
+       index = tlb1_next();
        mtspr(SPRN_MAS0, MAS0_ESEL(index) | MAS0_TLBSEL(1));
-
-       /* Just round-robin the entries and wrap when we hit the end */
-       if (unlikely(index == ncams - 1))
-               __get_cpu_var(next_tlbcam_idx) = tlbcam_index;
-       else
-               __get_cpu_var(next_tlbcam_idx)++;
 #endif
+
        mas1 = MAS1_VALID | MAS1_TID(mm->context.id) | MAS1_TSIZE(tsize);
        mas2 = ea & ~((1UL << shift) - 1);
        mas2 |= (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
@@ -103,7 +134,8 @@ void book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea,
        if (mmu_has_feature(MMU_FTR_USE_PAIRED_MAS)) {
                mtspr(SPRN_MAS7_MAS3, mas7_3);
        } else {
-               mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
+               if (mmu_has_feature(MMU_FTR_BIG_PHYS))
+                       mtspr(SPRN_MAS7, upper_32_bits(mas7_3));
                mtspr(SPRN_MAS3, lower_32_bits(mas7_3));
        }
 
index 0b7fb6761015526a38be8dac7ee51d0ca4d9f161..a5bcf930119691ad01c4116faaece823292669aa 100644 (file)
@@ -99,6 +99,10 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                /* Add in WIMG bits */
                rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
                                      _PAGE_COHERENT | _PAGE_GUARDED));
+               /*
+                * enable the memory coherence always
+                */
+               rflags |= HPTE_R_M;
 
                slot = hpte_insert_repeating(hash, vpn, pa, rflags, 0,
                                             mmu_psize, ssize);
index 8c1dd23652a13e32f0818772e62b9b2ec24539b1..4b5cd5c2594d9b5ca507bc80751f6d1003fde4d6 100644 (file)
@@ -307,6 +307,12 @@ static void __init register_page_bootmem_info(void)
 
 void __init mem_init(void)
 {
+       /*
+        * book3s is limited to 16 page sizes due to encoding this in
+        * a 4-bit field for slices.
+        */
+       BUILD_BUG_ON(MMU_PAGE_COUNT > 16);
+
 #ifdef CONFIG_SWIOTLB
        swiotlb_init(0);
 #endif
@@ -507,7 +513,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
  * System memory should not be in /proc/iomem but various tools expect it
  * (eg kdump).
  */
-static int add_system_ram_resources(void)
+static int __init add_system_ram_resources(void)
 {
        struct memblock_region *reg;
 
index 83eb5d5f53d52f51c278db4ff0f0d2d75a0f7c54..9615d82919b8b47075794acbf1dc44038aaf8ea8 100644 (file)
@@ -148,6 +148,8 @@ extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
 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);
 #endif
 extern void loadcam_entry(unsigned int index);
 
index 5a944f25e94ff4618661cd6efaea6ca3140157c8..86a63de072c617c35dc65b138b456d0ba900001a 100644 (file)
@@ -31,6 +31,8 @@
 #include <asm/sparsemem.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
+#include <asm/cputhreads.h>
+#include <asm/topology.h>
 #include <asm/firmware.h>
 #include <asm/paca.h>
 #include <asm/hvcall.h>
@@ -152,9 +154,22 @@ static void __init get_node_active_region(unsigned long pfn,
        }
 }
 
-static void map_cpu_to_node(int cpu, int node)
+static void reset_numa_cpu_lookup_table(void)
+{
+       unsigned int cpu;
+
+       for_each_possible_cpu(cpu)
+               numa_cpu_lookup_table[cpu] = -1;
+}
+
+static void update_numa_cpu_lookup_table(unsigned int cpu, int node)
 {
        numa_cpu_lookup_table[cpu] = node;
+}
+
+static void map_cpu_to_node(int cpu, int node)
+{
+       update_numa_cpu_lookup_table(cpu, node);
 
        dbg("adding cpu %d to node %d\n", cpu, node);
 
@@ -522,11 +537,24 @@ static int of_drconf_to_nid_single(struct of_drconf_cell *drmem,
  */
 static int numa_setup_cpu(unsigned long lcpu)
 {
-       int nid = 0;
-       struct device_node *cpu = of_get_cpu_node(lcpu, NULL);
+       int nid;
+       struct device_node *cpu;
+
+       /*
+        * If a valid cpu-to-node mapping is already available, use it
+        * directly instead of querying the firmware, since it represents
+        * the most recent mapping notified to us by the platform (eg: VPHN).
+        */
+       if ((nid = numa_cpu_lookup_table[lcpu]) >= 0) {
+               map_cpu_to_node(lcpu, nid);
+               return nid;
+       }
+
+       cpu = of_get_cpu_node(lcpu, NULL);
 
        if (!cpu) {
                WARN_ON(1);
+               nid = 0;
                goto out;
        }
 
@@ -542,16 +570,38 @@ out:
        return nid;
 }
 
+static void verify_cpu_node_mapping(int cpu, int node)
+{
+       int base, sibling, i;
+
+       /* Verify that all the threads in the core belong to the same node */
+       base = cpu_first_thread_sibling(cpu);
+
+       for (i = 0; i < threads_per_core; i++) {
+               sibling = base + i;
+
+               if (sibling == cpu || cpu_is_offline(sibling))
+                       continue;
+
+               if (cpu_to_node(sibling) != node) {
+                       WARN(1, "CPU thread siblings %d and %d don't belong"
+                               " to the same node!\n", cpu, sibling);
+                       break;
+               }
+       }
+}
+
 static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action,
                             void *hcpu)
 {
        unsigned long lcpu = (unsigned long)hcpu;
-       int ret = NOTIFY_DONE;
+       int ret = NOTIFY_DONE, nid;
 
        switch (action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
-               numa_setup_cpu(lcpu);
+               nid = numa_setup_cpu(lcpu);
+               verify_cpu_node_mapping((int)lcpu, nid);
                ret = NOTIFY_OK;
                break;
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1069,6 +1119,7 @@ void __init do_init_bootmem(void)
         */
        setup_node_to_cpumask_map();
 
+       reset_numa_cpu_lookup_table();
        register_cpu_notifier(&ppc64_numa_nb);
        cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
                          (void *)(unsigned long)boot_cpuid);
@@ -1447,6 +1498,33 @@ static int update_cpu_topology(void *data)
        return 0;
 }
 
+static int update_lookup_table(void *data)
+{
+       struct topology_update_data *update;
+
+       if (!data)
+               return -EINVAL;
+
+       /*
+        * Upon topology update, the numa-cpu lookup table needs to be updated
+        * for all threads in the core, including offline CPUs, to ensure that
+        * future hotplug operations respect the cpu-to-node associativity
+        * properly.
+        */
+       for (update = data; update; update = update->next) {
+               int nid, base, j;
+
+               nid = update->new_nid;
+               base = cpu_first_thread_sibling(update->cpu);
+
+               for (j = 0; j < threads_per_core; j++) {
+                       update_numa_cpu_lookup_table(base + j, nid);
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Update the node maps and sysfs entries for each cpu whose home node
  * has changed. Returns 1 when the topology has changed, and 0 otherwise.
@@ -1515,6 +1593,14 @@ int arch_update_cpu_topology(void)
 
        stop_machine(update_cpu_topology, &updates[0], &updated_cpus);
 
+       /*
+        * Update the numa-cpu lookup table with the new mappings, even for
+        * offline CPUs. It is best to perform this update from the stop-
+        * machine context.
+        */
+       stop_machine(update_lookup_table, &updates[0],
+                                       cpumask_of(raw_smp_processor_id()));
+
        for (ud = &updates[0]; ud; ud = ud->next) {
                unregister_cpu_under_node(ud->cpu, ud->old_nid);
                register_cpu_under_node(ud->cpu, ud->new_nid);
index 841e0d00863c94d99cac5c139b887dc97c21cfe1..c695943a513cc638621c830f537ea903ccfa3b86 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/mm.h>
-#include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
 #include <linux/hugetlb.h>
@@ -174,7 +173,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
                pte_t pte)
 {
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(pte_present(*ptep));
+       WARN_ON(pte_val(*ptep) & _PAGE_PRESENT);
 #endif
        /* Note: mm->context.id might not yet have been assigned as
         * this context might not have been activated yet when this
index 5b9601715289c450a23e41b7ffc62d428496b8c9..343a87fa78b5eb3ea403c7a4dcf18ef5da7e2b63 100644 (file)
@@ -299,6 +299,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
                set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
                                                     __pgprot(flags)));
        }
+       smp_wmb();
        return err;
 }
 
index 9d95786aa80ffbdcb8601379d774fc1f158006d0..65b7b65e8708bd1867861f4b519d207b25beb5a7 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/swap.h>
 #include <linux/stddef.h>
 #include <linux/vmalloc.h>
-#include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/slab.h>
@@ -153,6 +152,18 @@ int map_kernel_page(unsigned long ea, unsigned long pa, int flags)
                }
 #endif /* !CONFIG_PPC_MMU_NOHASH */
        }
+
+#ifdef CONFIG_PPC_BOOK3E_64
+       /*
+        * With hardware tablewalk, a sync is needed to ensure that
+        * subsequent accesses see the PTE we just wrote.  Unlike userspace
+        * mappings, we can't tolerate spurious faults, so make sure
+        * the new PTE will be seen the first time.
+        */
+       mb();
+#else
+       smp_wmb();
+#endif
        return 0;
 }
 
@@ -687,7 +698,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                pmd_t *pmdp, pmd_t pmd)
 {
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(!pmd_none(*pmdp));
+       WARN_ON(pmd_val(*pmdp) & _PAGE_PRESENT);
        assert_spin_locked(&mm->page_table_lock);
        WARN_ON(!pmd_trans_huge(pmd));
 #endif
index 36e44b4260ebd25ea5fa34660d7cbd81f71bf760..c99f6510a0b267220253249ed836e3dee4327ba7 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
 #include <asm/pgalloc.h>
index b4113bf863538adbf6d0bffdaa3aabe090270064..16250b162375da69581f7c7d563ea8f6d2632c79 100644 (file)
@@ -136,7 +136,7 @@ BEGIN_MMU_FTR_SECTION
         */
        PPC_TLBSRX_DOT(0,R16)
        ldx     r14,r14,r15             /* grab pgd entry */
-       beq     normal_tlb_miss_done    /* tlb exists already, bail */
+       beq     tlb_miss_done_bolted    /* tlb exists already, bail */
 MMU_FTR_SECTION_ELSE
        ldx     r14,r14,r15             /* grab pgd entry */
 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBRSRV)
@@ -192,6 +192,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_USE_TLBRSRV)
        mtspr   SPRN_MAS7_MAS3,r15
        tlbwe
 
+tlb_miss_done_bolted:
        TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK)
        tlb_epilog_bolted
        rfi
@@ -239,6 +240,177 @@ itlb_miss_fault_bolted:
        beq     tlb_miss_common_bolted
        b       itlb_miss_kernel_bolted
 
+/*
+ * TLB miss handling for e6500 and derivatives, using hardware tablewalk.
+ *
+ * Linear mapping is bolted: no virtual page table or nested TLB misses
+ * Indirect entries in TLB1, hardware loads resulting direct entries
+ *    into TLB0
+ * No HES or NV hint on TLB1, so we need to do software round-robin
+ * No tlbsrx. so we need a spinlock, and we have to deal
+ *    with MAS-damage caused by tlbsx
+ * 4K pages only
+ */
+
+       START_EXCEPTION(instruction_tlb_miss_e6500)
+       tlb_prolog_bolted BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR0
+
+       ld      r11,PACA_TCD_PTR(r13)
+       srdi.   r15,r16,60              /* get region */
+       ori     r16,r16,1
+
+       TLB_MISS_STATS_SAVE_INFO_BOLTED
+       bne     tlb_miss_kernel_e6500   /* user/kernel test */
+
+       b       tlb_miss_common_e6500
+
+       START_EXCEPTION(data_tlb_miss_e6500)
+       tlb_prolog_bolted BOOKE_INTERRUPT_DTLB_MISS SPRN_DEAR
+
+       ld      r11,PACA_TCD_PTR(r13)
+       srdi.   r15,r16,60              /* get region */
+       rldicr  r16,r16,0,62
+
+       TLB_MISS_STATS_SAVE_INFO_BOLTED
+       bne     tlb_miss_kernel_e6500   /* user vs kernel check */
+
+/*
+ * This is the guts of the TLB miss handler for e6500 and derivatives.
+ * We are entered with:
+ *
+ * r16 = page of faulting address (low bit 0 if data, 1 if instruction)
+ * r15 = crap (free to use)
+ * r14 = page table base
+ * r13 = PACA
+ * r11 = tlb_per_core ptr
+ * r10 = crap (free to use)
+ */
+tlb_miss_common_e6500:
+       /*
+        * Search if we already have an indirect entry for that virtual
+        * address, and if we do, bail out.
+        *
+        * MAS6:IND should be already set based on MAS4
+        */
+       addi    r10,r11,TCD_LOCK
+1:     lbarx   r15,0,r10
+       cmpdi   r15,0
+       bne     2f
+       li      r15,1
+       stbcx.  r15,0,r10
+       bne     1b
+       .subsection 1
+2:     lbz     r15,0(r10)
+       cmpdi   r15,0
+       bne     2b
+       b       1b
+       .previous
+
+       mfspr   r15,SPRN_MAS2
+
+       tlbsx   0,r16
+       mfspr   r10,SPRN_MAS1
+       andis.  r10,r10,MAS1_VALID@h
+       bne     tlb_miss_done_e6500
+
+       /* Undo MAS-damage from the tlbsx */
+       mfspr   r10,SPRN_MAS1
+       oris    r10,r10,MAS1_VALID@h
+       mtspr   SPRN_MAS1,r10
+       mtspr   SPRN_MAS2,r15
+
+       /* Now, we need to walk the page tables. First check if we are in
+        * range.
+        */
+       rldicl. r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
+       bne-    tlb_miss_fault_e6500
+
+       rldicl  r15,r16,64-PGDIR_SHIFT+3,64-PGD_INDEX_SIZE-3
+       cmpldi  cr0,r14,0
+       clrrdi  r15,r15,3
+       beq-    tlb_miss_fault_e6500 /* No PGDIR, bail */
+       ldx     r14,r14,r15             /* grab pgd entry */
+
+       rldicl  r15,r16,64-PUD_SHIFT+3,64-PUD_INDEX_SIZE-3
+       clrrdi  r15,r15,3
+       cmpdi   cr0,r14,0
+       bge     tlb_miss_fault_e6500    /* Bad pgd entry or hugepage; bail */
+       ldx     r14,r14,r15             /* grab pud entry */
+
+       rldicl  r15,r16,64-PMD_SHIFT+3,64-PMD_INDEX_SIZE-3
+       clrrdi  r15,r15,3
+       cmpdi   cr0,r14,0
+       bge     tlb_miss_fault_e6500
+       ldx     r14,r14,r15             /* Grab pmd entry */
+
+       mfspr   r10,SPRN_MAS0
+       cmpdi   cr0,r14,0
+       bge     tlb_miss_fault_e6500
+
+       /* Now we build the MAS for a 2M indirect page:
+        *
+        * MAS 0   :    ESEL needs to be filled by software round-robin
+        * MAS 1   :    Fully set up
+        *               - PID already updated by caller if necessary
+        *               - TSIZE for now is base ind page size always
+        *               - TID already cleared if necessary
+        * MAS 2   :    Default not 2M-aligned, need to be redone
+        * MAS 3+7 :    Needs to be done
+        */
+
+       ori     r14,r14,(BOOK3E_PAGESZ_4K << MAS3_SPSIZE_SHIFT)
+       mtspr   SPRN_MAS7_MAS3,r14
+
+       clrrdi  r15,r16,21              /* make EA 2M-aligned */
+       mtspr   SPRN_MAS2,r15
+
+       lbz     r15,TCD_ESEL_NEXT(r11)
+       lbz     r16,TCD_ESEL_MAX(r11)
+       lbz     r14,TCD_ESEL_FIRST(r11)
+       rlwimi  r10,r15,16,0x00ff0000   /* insert esel_next into MAS0 */
+       addi    r15,r15,1               /* increment esel_next */
+       mtspr   SPRN_MAS0,r10
+       cmpw    r15,r16
+       iseleq  r15,r14,r15             /* if next == last use first */
+       stb     r15,TCD_ESEL_NEXT(r11)
+
+       tlbwe
+
+tlb_miss_done_e6500:
+       .macro  tlb_unlock_e6500
+       li      r15,0
+       isync
+       stb     r15,TCD_LOCK(r11)
+       .endm
+
+       tlb_unlock_e6500
+       TLB_MISS_STATS_X(MMSTAT_TLB_MISS_NORM_OK)
+       tlb_epilog_bolted
+       rfi
+
+tlb_miss_kernel_e6500:
+       mfspr   r10,SPRN_MAS1
+       ld      r14,PACA_KERNELPGD(r13)
+       cmpldi  cr0,r15,8               /* Check for vmalloc region */
+       rlwinm  r10,r10,0,16,1          /* Clear TID */
+       mtspr   SPRN_MAS1,r10
+       beq+    tlb_miss_common_e6500
+
+tlb_miss_fault_e6500:
+       tlb_unlock_e6500
+       /* We need to check if it was an instruction miss */
+       andi.   r16,r16,1
+       bne     itlb_miss_fault_e6500
+dtlb_miss_fault_e6500:
+       TLB_MISS_STATS_D(MMSTAT_TLB_MISS_NORM_FAULT)
+       tlb_epilog_bolted
+       b       exc_data_storage_book3e
+itlb_miss_fault_e6500:
+       TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT)
+       tlb_epilog_bolted
+       b       exc_instruction_storage_book3e
+
+
 /**********************************************************************
  *                                                                    *
  * TLB miss handling for Book3E with TLB reservation and HES support  *
index 358d743031385ae7a269ba65200483227126d372..735839b74dc5a3d20cbf8eab97459f76e8b1d4aa 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/tlb.h>
 #include <asm/code-patching.h>
 #include <asm/hugetlb.h>
+#include <asm/paca.h>
 
 #include "mmu_decl.h"
 
@@ -58,6 +59,10 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
                .shift  = 12,
                .enc    = BOOK3E_PAGESZ_4K,
        },
+       [MMU_PAGE_2M] = {
+               .shift  = 21,
+               .enc    = BOOK3E_PAGESZ_2M,
+       },
        [MMU_PAGE_4M] = {
                .shift  = 22,
                .enc    = BOOK3E_PAGESZ_4M,
@@ -136,7 +141,7 @@ static inline int mmu_get_tsize(int psize)
 int mmu_linear_psize;          /* Page size used for the linear mapping */
 int mmu_pte_psize;             /* Page size used for PTE pages */
 int mmu_vmemmap_psize;         /* Page size used for the virtual mem map */
-int book3e_htw_enabled;                /* Is HW tablewalk enabled ? */
+int book3e_htw_mode;           /* HW tablewalk?  Value is PPC_HTW_* */
 unsigned long linear_map_top;  /* Top of linear mapping */
 
 #endif /* CONFIG_PPC64 */
@@ -377,7 +382,7 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address)
 {
        int tsize = mmu_psize_defs[mmu_pte_psize].enc;
 
-       if (book3e_htw_enabled) {
+       if (book3e_htw_mode != PPC_HTW_NONE) {
                unsigned long start = address & PMD_MASK;
                unsigned long end = address + PMD_SIZE;
                unsigned long size = 1UL << mmu_psize_defs[mmu_pte_psize].shift;
@@ -430,7 +435,7 @@ static void setup_page_sizes(void)
                        def = &mmu_psize_defs[psize];
                        shift = def->shift;
 
-                       if (shift == 0)
+                       if (shift == 0 || shift & 1)
                                continue;
 
                        /* adjust to be in terms of 4^shift Kb */
@@ -440,21 +445,40 @@ static void setup_page_sizes(void)
                                def->flags |= MMU_PAGE_SIZE_DIRECT;
                }
 
-               goto no_indirect;
+               goto out;
        }
 
        if (fsl_mmu && (mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
-               u32 tlb1ps = mfspr(SPRN_TLB1PS);
+               u32 tlb1cfg, tlb1ps;
+
+               tlb0cfg = mfspr(SPRN_TLB0CFG);
+               tlb1cfg = mfspr(SPRN_TLB1CFG);
+               tlb1ps = mfspr(SPRN_TLB1PS);
+               eptcfg = mfspr(SPRN_EPTCFG);
+
+               if ((tlb1cfg & TLBnCFG_IND) && (tlb0cfg & TLBnCFG_PT))
+                       book3e_htw_mode = PPC_HTW_E6500;
+
+               /*
+                * We expect 4K subpage size and unrestricted indirect size.
+                * The lack of a restriction on indirect size is a Freescale
+                * extension, indicated by PSn = 0 but SPSn != 0.
+                */
+               if (eptcfg != 2)
+                       book3e_htw_mode = PPC_HTW_NONE;
 
                for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
                        struct mmu_psize_def *def = &mmu_psize_defs[psize];
 
                        if (tlb1ps & (1U << (def->shift - 10))) {
                                def->flags |= MMU_PAGE_SIZE_DIRECT;
+
+                               if (book3e_htw_mode && psize == MMU_PAGE_2M)
+                                       def->flags |= MMU_PAGE_SIZE_INDIRECT;
                        }
                }
 
-               goto no_indirect;
+               goto out;
        }
 #endif
 
@@ -471,8 +495,11 @@ static void setup_page_sizes(void)
        }
 
        /* Indirect page sizes supported ? */
-       if ((tlb0cfg & TLBnCFG_IND) == 0)
-               goto no_indirect;
+       if ((tlb0cfg & TLBnCFG_IND) == 0 ||
+           (tlb0cfg & TLBnCFG_PT) == 0)
+               goto out;
+
+       book3e_htw_mode = PPC_HTW_IBM;
 
        /* Now, we only deal with one IND page size for each
         * direct size. Hopefully all implementations today are
@@ -497,8 +524,8 @@ static void setup_page_sizes(void)
                                def->ind = ps + 10;
                }
        }
- no_indirect:
 
+out:
        /* Cleanup array and print summary */
        pr_info("MMU: Supported page sizes\n");
        for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
@@ -518,44 +545,25 @@ static void setup_page_sizes(void)
        }
 }
 
-static void __patch_exception(int exc, unsigned long addr)
-{
-       extern unsigned int interrupt_base_book3e;
-       unsigned int *ibase = &interrupt_base_book3e;
-       /* Our exceptions vectors start with a NOP and -then- a branch
-        * to deal with single stepping from userspace which stops on
-        * the second instruction. Thus we need to patch the second
-        * instruction of the exception, not the first one
-        */
-
-       patch_branch(ibase + (exc / 4) + 1, addr, 0);
-}
-
-#define patch_exception(exc, name) do { \
-       extern unsigned int name; \
-       __patch_exception((exc), (unsigned long)&name); \
-} while (0)
-
 static void setup_mmu_htw(void)
 {
-       /* Check if HW tablewalk is present, and if yes, enable it by:
-        *
-        * - patching the TLB miss handlers to branch to the
-        *   one dedicates to it
-        *
-        * - setting the global book3e_htw_enabled
-                */
-       unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG);
+       /*
+        * If we want to use HW tablewalk, enable it by patching the TLB miss
+        * handlers to branch to the one dedicated to it.
+        */
 
-       if ((tlb0cfg & TLBnCFG_IND) &&
-           (tlb0cfg & TLBnCFG_PT)) {
+       switch (book3e_htw_mode) {
+       case PPC_HTW_IBM:
                patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
                patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
-               book3e_htw_enabled = 1;
+               break;
+       case PPC_HTW_E6500:
+               patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e);
+               patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e);
+               break;
        }
        pr_info("MMU: Book3E HW tablewalk %s\n",
-               book3e_htw_enabled ? "enabled" : "not supported");
+               book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported");
 }
 
 /*
@@ -595,8 +603,16 @@ static void __early_init_mmu(int boot_cpu)
        /* Set MAS4 based on page table setting */
 
        mas4 = 0x4 << MAS4_WIMGED_SHIFT;
-       if (book3e_htw_enabled) {
-               mas4 |= mas4 | MAS4_INDD;
+       switch (book3e_htw_mode) {
+       case PPC_HTW_E6500:
+               mas4 |= MAS4_INDD;
+               mas4 |= BOOK3E_PAGESZ_2M << MAS4_TSIZED_SHIFT;
+               mas4 |= MAS4_TLBSELD(1);
+               mmu_pte_psize = MMU_PAGE_2M;
+               break;
+
+       case PPC_HTW_IBM:
+               mas4 |= MAS4_INDD;
 #ifdef CONFIG_PPC_64K_PAGES
                mas4 |= BOOK3E_PAGESZ_256M << MAS4_TSIZED_SHIFT;
                mmu_pte_psize = MMU_PAGE_256M;
@@ -604,13 +620,16 @@ static void __early_init_mmu(int boot_cpu)
                mas4 |= BOOK3E_PAGESZ_1M << MAS4_TSIZED_SHIFT;
                mmu_pte_psize = MMU_PAGE_1M;
 #endif
-       } else {
+               break;
+
+       case PPC_HTW_NONE:
 #ifdef CONFIG_PPC_64K_PAGES
                mas4 |= BOOK3E_PAGESZ_64K << MAS4_TSIZED_SHIFT;
 #else
                mas4 |= BOOK3E_PAGESZ_4K << MAS4_TSIZED_SHIFT;
 #endif
                mmu_pte_psize = mmu_virtual_psize;
+               break;
        }
        mtspr(SPRN_MAS4, mas4);
 
@@ -630,8 +649,11 @@ static void __early_init_mmu(int boot_cpu)
                /* limit memory so we dont have linear faults */
                memblock_enforce_memory_limit(linear_map_top);
 
-               patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
-               patch_exception(0x1e0, exc_instruction_tlb_miss_bolted_book3e);
+               if (book3e_htw_mode == PPC_HTW_NONE) {
+                       patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e);
+                       patch_exception(0x1e0,
+                               exc_instruction_tlb_miss_bolted_book3e);
+               }
        }
 #endif
 
index 626ad081639f0e25e910bd3207082d097a684c6c..43ff3c797fbfed1eb3191470ce57813107b10619 100644 (file)
@@ -402,7 +402,9 @@ _GLOBAL(set_context)
  * Load TLBCAM[index] entry in to the L2 CAM MMU
  */
 _GLOBAL(loadcam_entry)
-       LOAD_REG_ADDR(r4, TLBCAM)
+       mflr    r5
+       LOAD_REG_ADDR_PIC(r4, TLBCAM)
+       mtlr    r5
        mulli   r5,r3,TLBCAM_SIZE
        add     r3,r5,r4
        lwz     r4,TLBCAM_MAS0(r3)
index ff617246d128b7a9c5555c42f2b22f4bf9cfa000..d29b6e4e5e721f1509417a0eef829dcaf58dd80b 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 #include <linux/oprofile.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
index b9589c19ccdabff66348caae82bf49ec2ed1d243..1f0ebdeea5f77cdd63a844680912242d8b0a7574 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/kthread.h>
 #include <linux/oprofile.h>
index 2a82d3ed464d09123db06c59c429014176611272..14cf86fdddab4373f76594509e0cc5789b33a371 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/oprofile.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
index 42f778dff919b3c75977a2dd118217259647de7a..a114a7c22d40a9cbce59550a973c0f784552c6ca 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/oprofile.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
 #include <asm/processor.h>
index f444b94935f560f6a7abf1a1de46d88cd32e71d5..962fe7b3e3fb1924543634b10593914257e30b39 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/oprofile.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/firmware.h>
 #include <asm/ptrace.h>
index 9b801b8c8c5adb63c8b9bc908c700ad214411c65..7e5b8ed3a1b772609bdd44de8136bd80035006d3 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/oprofile.h>
-#include <linux/init.h>
 #include <linux/smp.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
index 670a033264c0f1626af64f79b7b4fd23da797ec4..2bdc8c862c46c1af3c9ca38f4c116923d254fad6 100644 (file)
@@ -99,7 +99,6 @@ config SBC834x
 config ASP834x
        bool "Analogue & Micro ASP 834x"
        select PPC_MPC834x
-       select REDBOOT
        help
          This enables support for the Analogue & Micro ASP 83xx
          board.
index fd71cfdf23802e56f121d6c5dbc6144d3dcbd11f..e238b6a55b1593e08f43e029bf6b4f9af1a7836f 100644 (file)
@@ -11,7 +11,6 @@
  * (at your option) any later version.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
index 3d9716ccd3274b2fa162e2137ced47883c9a27cd..4b4c081df94db168e480e10bff1d427debb1c6bb 100644 (file)
@@ -10,7 +10,6 @@
  * by the Free Software Foundation.
  */
 
-#include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
index 4d4634958cfb09107a37829dc19ee65b427a6bab..c17aae80e7ffd73d4860a64a42bee8b686fb4b62 100644 (file)
@@ -123,6 +123,12 @@ config P1023_RDS
        help
          This option enables support for the P1023 RDS and RDB boards
 
+config TWR_P102x
+       bool "Freescale TWR-P102x"
+       select DEFAULT_UIMAGE
+       help
+         This option enables support for the TWR-P1025 board.
+
 config SOCRATES
        bool "Socrates"
        select DEFAULT_UIMAGE
index dd4c0b59577bb98f0574f5eca765f46a5a5b287c..25cebe74ac463365b7d5a4d7e89aea8088a818a4 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1022_RDK)   += p1022_rdk.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
+obj-$(CONFIG_TWR_P102x)   += twr_p102x.o
 obj-$(CONFIG_CORENET_GENERIC)   += corenet_generic.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
 obj-$(CONFIG_TQM85xx)    += tqm85xx.o
index eba78c85303f9f6ee27eb8d1d0c2f4221e056d65..3b085c7ee539bc23fbcaf0e38ebaa7752a8e05d3 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
+#include <asm/qe.h>
 #include <sysdev/cpm2_pic.h>
 
 #include "mpc85xx.h"
@@ -82,3 +83,40 @@ void __init mpc85xx_cpm2_pic_init(void)
        irq_set_chained_handler(irq, cpm2_cascade);
 }
 #endif
+
+#ifdef CONFIG_QUICC_ENGINE
+void __init mpc85xx_qe_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+       if (!np) {
+               np = of_find_node_by_name(NULL, "qe");
+               if (!np) {
+                       pr_err("%s: Could not find Quicc Engine node\n",
+                                       __func__);
+                       return;
+               }
+       }
+
+       if (!of_device_is_available(np)) {
+               of_node_put(np);
+               return;
+       }
+
+       qe_reset();
+       of_node_put(np);
+
+       np = of_find_node_by_name(NULL, "par_io");
+       if (np) {
+               struct device_node *ucc;
+
+               par_io_init(np);
+               of_node_put(np);
+
+               for_each_node_by_name(ucc, "ucc")
+                       par_io_of_config(ucc);
+
+       }
+}
+#endif
index 2aa7c5dc2c7f6d1131e482a27d58ff2931fdf709..fc51dd4092e5d10d88620f10c07434072e612b63 100644 (file)
@@ -8,4 +8,10 @@ extern void mpc85xx_cpm2_pic_init(void);
 static inline void __init mpc85xx_cpm2_pic_init(void) {}
 #endif /* CONFIG_CPM2 */
 
+#ifdef CONFIG_QUICC_ENGINE
+extern void mpc85xx_qe_init(void);
+#else
+static inline void __init mpc85xx_qe_init(void) {}
+#endif
+
 #endif
index a7b3621a8df5dc019c4ec63102ec71ef9a5d947f..34f3c5eb3bee77dcf584b9742a241ee9d99cc310 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010, 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006-2010, 2012-2013 Freescale Semiconductor, Inc.
  * All rights reserved.
  *
  * Author: Andy Fleming <afleming@freescale.com>
@@ -238,32 +238,7 @@ static void __init mpc85xx_mds_qe_init(void)
 {
        struct device_node *np;
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,qe");
-       if (!np) {
-               np = of_find_node_by_name(NULL, "qe");
-               if (!np)
-                       return;
-       }
-
-       if (!of_device_is_available(np)) {
-               of_node_put(np);
-               return;
-       }
-
-       qe_reset();
-       of_node_put(np);
-
-       np = of_find_node_by_name(NULL, "par_io");
-       if (np) {
-               struct device_node *ucc;
-
-               par_io_init(np);
-               of_node_put(np);
-
-               for_each_node_by_name(ucc, "ucc")
-                       par_io_of_config(ucc);
-       }
-
+       mpc85xx_qe_init();
        mpc85xx_mds_reset_ucc_phys();
 
        if (machine_is(p1021_mds)) {
index 53b6fb0a3d560a5be2e2aa0dd186075d34ff794b..e15bdd18fdb2f2571312a6cfad74ee5ee741bbd9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MPC85xx RDB Board Setup
  *
- * Copyright 2009,2012 Freescale Semiconductor Inc.
+ * Copyright 2009,2012-2013 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
@@ -98,26 +98,7 @@ static void __init mpc85xx_rdb_setup_arch(void)
        fsl_pci_assign_primary();
 
 #ifdef CONFIG_QUICC_ENGINE
-       np = of_find_compatible_node(NULL, NULL, "fsl,qe");
-       if (!np) {
-               pr_err("%s: Could not find Quicc Engine node\n", __func__);
-               goto qe_fail;
-       }
-
-       qe_reset();
-       of_node_put(np);
-
-       np = of_find_node_by_name(NULL, "par_io");
-       if (np) {
-               struct device_node *ucc;
-
-               par_io_init(np);
-               of_node_put(np);
-
-               for_each_node_by_name(ucc, "ucc")
-                       par_io_of_config(ucc);
-
-       }
+       mpc85xx_qe_init();
 #if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
        if (machine_is(p1025_rdb)) {
 
@@ -148,8 +129,6 @@ static void __init mpc85xx_rdb_setup_arch(void)
 
        }
 #endif
-
-qe_fail:
 #endif /* CONFIG_QUICC_ENGINE */
 
        printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
index b9197cea1854da9e9934b302c45045868efc8c83..bb75add670844e3f2e990d0a21e1c48a0ac42c20 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/workqueue.h>
index 393f975ab397c1dd32919b77f9f0cfe8351fc397..6382098d6f8d884aeea1fbbef387df8572f0b5b9 100644 (file)
@@ -389,15 +389,18 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 }
 #endif /* CONFIG_KEXEC */
 
-static void smp_85xx_setup_cpu(int cpu_nr)
+static void smp_85xx_basic_setup(int cpu_nr)
 {
-       if (smp_85xx_ops.probe == smp_mpic_probe)
-               mpic_setup_this_cpu();
-
        if (cpu_has_feature(CPU_FTR_DBELL))
                doorbell_setup_this_cpu();
 }
 
+static void smp_85xx_setup_cpu(int cpu_nr)
+{
+       mpic_setup_this_cpu();
+       smp_85xx_basic_setup(cpu_nr);
+}
+
 static const struct of_device_id mpc85xx_smp_guts_ids[] = {
        { .compatible = "fsl,mpc8572-guts", },
        { .compatible = "fsl,p1020-guts", },
@@ -412,13 +415,14 @@ void __init mpc85xx_smp_init(void)
 {
        struct device_node *np;
 
-       smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
 
        np = of_find_node_by_type(NULL, "open-pic");
        if (np) {
                smp_85xx_ops.probe = smp_mpic_probe;
+               smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
                smp_85xx_ops.message_pass = smp_mpic_message_pass;
-       }
+       } else
+               smp_85xx_ops.setup_cpu = smp_85xx_basic_setup;
 
        if (cpu_has_feature(CPU_FTR_DBELL)) {
                /*
@@ -427,6 +431,7 @@ void __init mpc85xx_smp_init(void)
                 */
                smp_85xx_ops.message_pass = NULL;
                smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
+               smp_85xx_ops.probe = NULL;
        }
 
        np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
new file mode 100644 (file)
index 0000000..c25ff10
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2010-2011, 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Michael Johnston <michael.johnston@freescale.com>
+ *
+ * Description:
+ * TWR-P102x Board Setup
+ *
+ * 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/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/of_platform.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+#include <asm/fsl_guts.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include "smp.h"
+
+#include "mpc85xx.h"
+
+static void __init twr_p1025_pic_init(void)
+{
+       struct mpic *mpic;
+
+#ifdef CONFIG_QUICC_ENGINE
+       struct device_node *np;
+#endif
+
+       mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+                       MPIC_SINGLE_DEST_CPU,
+                       0, 256, " OpenPIC  ");
+
+       BUG_ON(mpic == NULL);
+       mpic_init(mpic);
+
+#ifdef CONFIG_QUICC_ENGINE
+       np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+       if (np) {
+               qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+                               qe_ic_cascade_high_mpic);
+               of_node_put(np);
+       } else
+               pr_err("Could not find qe-ic node\n");
+#endif
+}
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init twr_p1025_setup_arch(void)
+{
+#ifdef CONFIG_QUICC_ENGINE
+       struct device_node *np;
+#endif
+
+       if (ppc_md.progress)
+               ppc_md.progress("twr_p1025_setup_arch()", 0);
+
+       mpc85xx_smp_init();
+
+       fsl_pci_assign_primary();
+
+#ifdef CONFIG_QUICC_ENGINE
+       mpc85xx_qe_init();
+
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
+       if (machine_is(twr_p1025)) {
+               struct ccsr_guts __iomem *guts;
+
+               np = of_find_compatible_node(NULL, NULL, "fsl,p1021-guts");
+               if (np) {
+                       guts = of_iomap(np, 0);
+                       if (!guts)
+                               pr_err("twr_p1025: could not map global utilities register\n");
+                       else {
+                       /* P1025 has pins muxed for QE and other functions. To
+                        * enable QE UEC mode, we need to set bit QE0 for UCC1
+                        * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
+                        * and QE12 for QE MII management signals in PMUXCR
+                        * register.
+                        * Set QE mux bits in PMUXCR */
+                       setbits32(&guts->pmuxcr, MPC85xx_PMUXCR_QE(0) |
+                                       MPC85xx_PMUXCR_QE(3) |
+                                       MPC85xx_PMUXCR_QE(9) |
+                                       MPC85xx_PMUXCR_QE(12));
+                       iounmap(guts);
+
+#if defined(CONFIG_SERIAL_QE)
+                       /* On P1025TWR board, the UCC7 acted as UART port.
+                        * However, The UCC7's CTS pin is low level in default,
+                        * it will impact the transmission in full duplex
+                        * communication. So disable the Flow control pin PA18.
+                        * The UCC7 UART just can use RXD and TXD pins.
+                        */
+                       par_io_config_pin(0, 18, 0, 0, 0, 0);
+#endif
+                       /* Drive PB29 to CPLD low - CPLD will then change
+                        * muxing from LBC to QE */
+                       par_io_config_pin(1, 29, 1, 0, 0, 0);
+                       par_io_data_set(1, 29, 0);
+                       }
+                       of_node_put(np);
+               }
+       }
+#endif
+#endif /* CONFIG_QUICC_ENGINE */
+
+       pr_info("TWR-P1025 board from Freescale Semiconductor\n");
+}
+
+machine_arch_initcall(twr_p1025, mpc85xx_common_publish_devices);
+
+static int __init twr_p1025_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,TWR-P1025");
+}
+
+define_machine(twr_p1025) {
+       .name                   = "TWR-P1025",
+       .probe                  = twr_p1025_probe,
+       .setup_arch             = twr_p1025_setup_arch,
+       .init_IRQ               = twr_p1025_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index 8dec3c0911ad0f4ad047b6d68ce8a34b95452cfe..bd6f1a1cf922bc60bf15ed1e659c6ecb06d96312 100644 (file)
@@ -45,7 +45,6 @@ config PPC_EP88XC
 config PPC_ADDER875
        bool "Analogue & Micro Adder 875"
        select CPM1
-       select REDBOOT
        help
          This enables support for the Analogue & Micro Adder 875
          board.
index bca2465a9c347ad65f3617a7a51f2e4f2a73034a..434fda39bf8b51f219098f207ce9cf35760fd484 100644 (file)
@@ -72,6 +72,7 @@ config PPC_BOOK3S_64
        select PPC_HAVE_PMU_SUPPORT
        select SYS_SUPPORTS_HUGETLBFS
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if PPC_64K_PAGES
+       select ARCH_SUPPORTS_NUMA_BALANCING
 
 config PPC_BOOK3E_64
        bool "Embedded processors"
index c34ee4e608734f387a0e43ed87abc1ba27e6dd27..d4d245c0d78799a6f48e65aae52560b75daac6e7 100644 (file)
@@ -111,7 +111,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
                DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        if (rflags & _PAGE_NO_CACHE)
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
 
        raw_spin_lock(&beat_htab_lock);
        lpar_rc = beat_read_mask(hpte_group);
@@ -337,7 +337,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
                DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        if (rflags & _PAGE_NO_CACHE)
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
 
        /* insert into not-volted entry */
        lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
index b53560660b72e72030a6235d295be8ab1fd9c722..2b90ff8a93bea7542fee7d89f99d3439bf9e0d13 100644 (file)
@@ -197,7 +197,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
 
        io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
 
-       for (i = 0; i < npages; i++, uaddr += IOMMU_PAGE_SIZE)
+       for (i = 0; i < npages; i++, uaddr += tbl->it_page_shift)
                io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask);
 
        mb();
@@ -430,7 +430,7 @@ static void cell_iommu_setup_hardware(struct cbe_iommu *iommu,
 {
        cell_iommu_setup_stab(iommu, base, size, 0, 0);
        iommu->ptab = cell_iommu_alloc_ptab(iommu, base, size, 0, 0,
-                                           IOMMU_PAGE_SHIFT);
+                                           IOMMU_PAGE_SHIFT_4K);
        cell_iommu_enable_hardware(iommu);
 }
 
@@ -487,8 +487,10 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
        window->table.it_blocksize = 16;
        window->table.it_base = (unsigned long)iommu->ptab;
        window->table.it_index = iommu->nid;
-       window->table.it_offset = (offset >> IOMMU_PAGE_SHIFT) + pte_offset;
-       window->table.it_size = size >> IOMMU_PAGE_SHIFT;
+       window->table.it_page_shift = IOMMU_PAGE_SHIFT_4K;
+       window->table.it_offset =
+               (offset >> window->table.it_page_shift) + pte_offset;
+       window->table.it_size = size >> window->table.it_page_shift;
 
        iommu_init_table(&window->table, iommu->nid);
 
@@ -773,7 +775,7 @@ static void __init cell_iommu_init_one(struct device_node *np,
 
        /* Setup the iommu_table */
        cell_iommu_setup_window(iommu, np, base, size,
-                               offset >> IOMMU_PAGE_SHIFT);
+                               offset >> IOMMU_PAGE_SHIFT_4K);
 }
 
 static void __init cell_disable_iommus(void)
@@ -1122,7 +1124,7 @@ static int __init cell_iommu_fixed_mapping_init(void)
 
                cell_iommu_setup_stab(iommu, dbase, dsize, fbase, fsize);
                iommu->ptab = cell_iommu_alloc_ptab(iommu, dbase, dsize, 0, 0,
-                                                   IOMMU_PAGE_SHIFT);
+                                                   IOMMU_PAGE_SHIFT_4K);
                cell_iommu_setup_fixed_ptab(iommu, np, dbase, dsize,
                                             fbase, fsize);
                cell_iommu_enable_hardware(iommu);
index dead91b177b9df702e236d9abba5a379a5aa793d..b6c9a0dcc92485b6dbf07e1934d80a6a16d7264c 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/spinlock.h>
 
 #include <asm/ptrace.h>
index 302ba43d73a168df77e53d20f5203513c2c03695..6d3c7a9fd047a5de571a733d11aa31bd48cd82bd 100644 (file)
@@ -67,6 +67,18 @@ config PPC_C2K
          This option enables support for the GE Fanuc C2K board (formerly
          an SBS board).
 
+config MVME5100
+       bool "Motorola/Emerson MVME5100"
+       depends on EMBEDDED6xx
+       select MPIC
+       select PCI
+       select PPC_INDIRECT_PCI
+       select PPC_I8259
+       select PPC_NATIVE
+       help
+         This option enables support for the Motorola (now Emerson) MVME5100
+         board.
+
 config TSI108_BRIDGE
        bool
        select PCI
@@ -113,4 +125,3 @@ config WII
        help
          Select WII if configuring for the Nintendo Wii.
          More information at: <http://gc-linux.sourceforge.net/>
-
index 66c23e423f40784ae85affb14bd5d7e95f8d68c2..cdd48d402b93eba2633ff5854eb4bf8723e47cbb 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_USBGECKO_UDBG)   += usbgecko_udbg.o
 obj-$(CONFIG_GAMECUBE_COMMON)  += flipper-pic.o
 obj-$(CONFIG_GAMECUBE)         += gamecube.o
 obj-$(CONFIG_WII)              += wii.o hlwd-pic.o
+obj-$(CONFIG_MVME5100)         += mvme5100.o
index 6c03034dbbd31b4aba9f0faf06579bdf9e8fab21..c269caee58f9486f6e260cf67367cb501820642c 100644 (file)
@@ -15,7 +15,6 @@
 #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c
new file mode 100644 (file)
index 0000000..25e3bfb
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Board setup routines for the Motorola/Emerson MVME5100.
+ *
+ * Copyright 2013 CSC Australia Pty. Ltd.
+ *
+ * Based on earlier code by:
+ *
+ *    Matt Porter, MontaVista Software Inc.
+ *    Copyright 2001 MontaVista Software 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.
+ *
+ * Author: Stephen Chivers <schivers@csc.com>
+ *
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/i8259.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#define HAWK_MPIC_SIZE         0x00040000U
+#define MVME5100_PCI_MEM_OFFSET 0x00000000
+
+/* Board register addresses. */
+#define BOARD_STATUS_REG       0xfef88080
+#define BOARD_MODFAIL_REG      0xfef88090
+#define BOARD_MODRST_REG       0xfef880a0
+#define BOARD_TBEN_REG         0xfef880c0
+#define BOARD_SW_READ_REG      0xfef880e0
+#define BOARD_GEO_ADDR_REG     0xfef880e8
+#define BOARD_EXT_FEATURE1_REG 0xfef880f0
+#define BOARD_EXT_FEATURE2_REG 0xfef88100
+
+static phys_addr_t pci_membase;
+static u_char *restart;
+
+static void mvme5100_8259_cascade(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int cascade_irq = i8259_irq();
+
+       if (cascade_irq != NO_IRQ)
+               generic_handle_irq(cascade_irq);
+
+       chip->irq_eoi(&desc->irq_data);
+}
+
+static void __init mvme5100_pic_init(void)
+{
+       struct mpic *mpic;
+       struct device_node *np;
+       struct device_node *cp = NULL;
+       unsigned int cirq;
+       unsigned long intack = 0;
+       const u32 *prop = NULL;
+
+       np = of_find_node_by_type(NULL, "open-pic");
+       if (!np) {
+               pr_err("Could not find open-pic node\n");
+               return;
+       }
+
+       mpic = mpic_alloc(np, pci_membase, 0, 16, 256, " OpenPIC  ");
+
+       BUG_ON(mpic == NULL);
+       of_node_put(np);
+
+       mpic_assign_isu(mpic, 0, pci_membase + 0x10000);
+
+       mpic_init(mpic);
+
+       cp = of_find_compatible_node(NULL, NULL, "chrp,iic");
+       if (cp == NULL) {
+               pr_warn("mvme5100_pic_init: couldn't find i8259\n");
+               return;
+       }
+
+       cirq = irq_of_parse_and_map(cp, 0);
+       if (cirq == NO_IRQ) {
+               pr_warn("mvme5100_pic_init: no cascade interrupt?\n");
+               return;
+       }
+
+       np = of_find_compatible_node(NULL, "pci", "mpc10x-pci");
+       if (np) {
+               prop = of_get_property(np, "8259-interrupt-acknowledge", NULL);
+
+               if (prop)
+                       intack = prop[0];
+
+               of_node_put(np);
+       }
+
+       if (intack)
+               pr_debug("mvme5100_pic_init: PCI 8259 intack at 0x%016lx\n",
+                  intack);
+
+       i8259_init(cp, intack);
+       of_node_put(cp);
+       irq_set_chained_handler(cirq, mvme5100_8259_cascade);
+}
+
+static int __init mvme5100_add_bridge(struct device_node *dev)
+{
+       const int               *bus_range;
+       int                     len;
+       struct pci_controller   *hose;
+       unsigned short          devid;
+
+       pr_info("Adding PCI host bridge %s\n", dev->full_name);
+
+       bus_range = of_get_property(dev, "bus-range", &len);
+
+       hose = pcibios_alloc_controller(dev);
+       if (hose == NULL)
+               return -ENOMEM;
+
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+       setup_indirect_pci(hose, 0xfe000cf8, 0xfe000cfc, 0);
+
+       pci_process_bridge_OF_ranges(hose, dev, 1);
+
+       early_read_config_word(hose, 0, 0, PCI_DEVICE_ID, &devid);
+
+       if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) {
+               pr_err("HAWK PHB not present?\n");
+               return 0;
+       }
+
+       early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+       if (pci_membase == 0) {
+               pr_err("HAWK PHB mibar not correctly set?\n");
+               return 0;
+       }
+
+       pr_info("mvme5100_pic_init: pci_membase: %x\n", pci_membase);
+
+       return 0;
+}
+
+static struct of_device_id mvme5100_of_bus_ids[] __initdata = {
+       { .compatible = "hawk-bridge", },
+       {},
+};
+
+/*
+ * Setup the architecture
+ */
+static void __init mvme5100_setup_arch(void)
+{
+       struct device_node *np;
+
+       if (ppc_md.progress)
+               ppc_md.progress("mvme5100_setup_arch()", 0);
+
+       for_each_compatible_node(np, "pci", "hawk-pci")
+               mvme5100_add_bridge(np);
+
+       restart = ioremap(BOARD_MODRST_REG, 4);
+}
+
+
+static void mvme5100_show_cpuinfo(struct seq_file *m)
+{
+       seq_puts(m, "Vendor\t\t: Motorola/Emerson\n");
+       seq_puts(m, "Machine\t\t: MVME5100\n");
+}
+
+static void mvme5100_restart(char *cmd)
+{
+
+       local_irq_disable();
+       mtmsr(mfmsr() | MSR_IP);
+
+       out_8((u_char *) restart, 0x01);
+
+       while (1)
+               ;
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mvme5100_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "MVME5100");
+}
+
+static int __init probe_of_platform_devices(void)
+{
+
+       of_platform_bus_probe(NULL, mvme5100_of_bus_ids, NULL);
+       return 0;
+}
+
+machine_device_initcall(mvme5100, probe_of_platform_devices);
+
+define_machine(mvme5100) {
+       .name                   = "MVME5100",
+       .probe                  = mvme5100_probe,
+       .setup_arch             = mvme5100_setup_arch,
+       .init_IRQ               = mvme5100_pic_init,
+       .show_cpuinfo           = mvme5100_show_cpuinfo,
+       .get_irq                = mpic_get_irq,
+       .restart                = mvme5100_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index f3defd8a28069af474718e40017ac3a8359e79e7..aafa01ba062f80f904a44fa8e7fd7db93763aed0 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
index 7d2d036754b5b56ecf5df1ddeb6367d2cc6b223c..2e576f2ae44256301fbcdb149ea47fdeef241fe7 100644 (file)
@@ -138,8 +138,11 @@ static void iommu_table_iobmap_setup(void)
        pr_debug(" -> %s\n", __func__);
        iommu_table_iobmap.it_busno = 0;
        iommu_table_iobmap.it_offset = 0;
+       iommu_table_iobmap.it_page_shift = IOBMAP_PAGE_SHIFT;
+
        /* it_size is in number of entries */
-       iommu_table_iobmap.it_size = 0x80000000 >> IOBMAP_PAGE_SHIFT;
+       iommu_table_iobmap.it_size =
+               0x80000000 >> iommu_table_iobmap.it_page_shift;
 
        /* Initialize the common IOMMU code */
        iommu_table_iobmap.it_base = (unsigned long)iob_l2_base;
index d588e48dff74cd9d1469e4dfafce5627ec09b4f2..43075081721f7ea93c51240bc92a5b73573e4759 100644 (file)
@@ -5,7 +5,6 @@
  * FIXME: LOCKING !!!
  */
 
-#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
index 9fced3f6d2dcfadbf0f26c71d57693d79b1c78ba..895e8a20a3fc064069d49d4b4cc1280b05df4e87 100644 (file)
@@ -13,11 +13,6 @@ config PPC_POWERNV
        select ARCH_RANDOM
        default y
 
-config POWERNV_MSI
-       bool "Support PCI MSI on PowerNV platform"
-       depends on PCI_MSI
-       default y
-
 config PPC_POWERNV_RTAS
        depends on PPC_POWERNV
        bool "Support for RTAS based PowerNV platforms such as BML"
index 873fa1370dc44c1b0b3994e7555c4fac450adcbd..8d767fde5a6ac32484bf106698d8c43e1292cd73 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_SMP)       += smp.o
 obj-$(CONFIG_PCI)      += pci.o pci-p5ioc2.o pci-ioda.o
 obj-$(CONFIG_EEH)      += eeh-ioda.o eeh-powernv.o
 obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
+obj-$(CONFIG_MEMORY_FAILURE)   += opal-memory-errors.o
index d7ddcee7feb8bc8084d18be32f348263c8de6e0e..e1e71618b70cfe5d4caa7d15e30bc42a37361c56 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/bootmem.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -578,11 +577,8 @@ static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
                return -EIO;
        }
 
-       /*
-        * FIXME: We probably need log the error in somewhere.
-        * Lets make it up in future.
-        */
-       /* pr_info("%s", phb->diag.blob); */
+       /* The PHB diag-data is always indicative */
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
 
        spin_unlock_irqrestore(&phb->lock, flags);
 
@@ -670,143 +666,9 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
        }
 }
 
-static void ioda_eeh_p7ioc_phb_diag(struct pci_controller *hose,
-                                   struct OpalIoPhbErrorCommon *common)
-{
-       struct OpalIoP7IOCPhbErrorData *data;
-       int i;
-
-       data = (struct OpalIoP7IOCPhbErrorData *)common;
-
-       pr_info("P7IOC PHB#%x Diag-data (Version: %d)\n\n",
-               hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
-
-       for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
-               if ((data->pestA[i] >> 63) == 0 &&
-                   (data->pestB[i] >> 63) == 0)
-                       continue;
-
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
-       }
-}
-
-static void ioda_eeh_phb3_phb_diag(struct pci_controller *hose,
-                                   struct OpalIoPhbErrorCommon *common)
-{
-       struct OpalIoPhb3ErrorData *data;
-       int i;
-
-       data = (struct OpalIoPhb3ErrorData*)common;
-       pr_info("PHB3 PHB#%x Diag-data (Version: %d)\n\n",
-               hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  nFir:                 %016llx\n", data->nFir);
-       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
-       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
-       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
-       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
-
-       for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
-               if ((data->pestA[i] >> 63) == 0 &&
-                   (data->pestB[i] >> 63) == 0)
-                       continue;
-
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
-       }
-}
-
 static void ioda_eeh_phb_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoPhbErrorCommon *common;
        long rc;
 
        rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
@@ -817,18 +679,7 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose)
                return;
        }
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       switch (common->ioType) {
-       case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
-               ioda_eeh_p7ioc_phb_diag(hose, common);
-               break;
-       case OPAL_PHB_ERROR_DATA_TYPE_PHB3:
-               ioda_eeh_phb3_phb_diag(hose, common);
-               break;
-       default:
-               pr_warning("%s: Unrecognized I/O chip %d\n",
-                          __func__, common->ioType);
-       }
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
 }
 
 static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
@@ -862,11 +713,7 @@ static int ioda_eeh_get_pe(struct pci_controller *hose,
        dev.phb = hose;
        dev.pe_config_addr = pe_no;
        dev_pe = eeh_pe_get(&dev);
-       if (!dev_pe) {
-               pr_warning("%s: Can't find PE for PHB#%x - PE#%x\n",
-                          __func__, hose->global_number, pe_no);
-               return -EEXIST;
-       }
+       if (!dev_pe) return -EEXIST;
 
        *pe = dev_pe;
        return 0;
@@ -884,12 +731,12 @@ static int ioda_eeh_get_pe(struct pci_controller *hose,
  */
 static int ioda_eeh_next_error(struct eeh_pe **pe)
 {
-       struct pci_controller *hose, *tmp;
+       struct pci_controller *hose;
        struct pnv_phb *phb;
        u64 frozen_pe_no;
        u16 err_type, severity;
        long rc;
-       int ret = 1;
+       int ret = EEH_NEXT_ERR_NONE;
 
        /*
         * While running here, it's safe to purge the event queue.
@@ -899,7 +746,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
        eeh_remove_event(NULL);
        opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
 
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+       list_for_each_entry(hose, &hose_list, list_node) {
                /*
                 * If the subordinate PCI buses of the PHB has been
                 * removed, we needn't take care of it any more.
@@ -938,19 +785,19 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
                switch (err_type) {
                case OPAL_EEH_IOC_ERROR:
                        if (severity == OPAL_EEH_SEV_IOC_DEAD) {
-                               list_for_each_entry_safe(hose, tmp,
-                                               &hose_list, list_node) {
+                               list_for_each_entry(hose, &hose_list,
+                                                   list_node) {
                                        phb = hose->private_data;
                                        phb->eeh_state |= PNV_EEH_STATE_REMOVED;
                                }
 
                                pr_err("EEH: dead IOC detected\n");
-                               ret = 4;
-                               goto out;
+                               ret = EEH_NEXT_ERR_DEAD_IOC;
                        } else if (severity == OPAL_EEH_SEV_INF) {
                                pr_info("EEH: IOC informative error "
                                        "detected\n");
                                ioda_eeh_hub_diag(hose);
+                               ret = EEH_NEXT_ERR_NONE;
                        }
 
                        break;
@@ -962,37 +809,61 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
                                pr_err("EEH: dead PHB#%x detected\n",
                                        hose->global_number);
                                phb->eeh_state |= PNV_EEH_STATE_REMOVED;
-                               ret = 3;
-                               goto out;
+                               ret = EEH_NEXT_ERR_DEAD_PHB;
                        } else if (severity == OPAL_EEH_SEV_PHB_FENCED) {
                                if (ioda_eeh_get_phb_pe(hose, pe))
                                        break;
 
                                pr_err("EEH: fenced PHB#%x detected\n",
                                        hose->global_number);
-                               ret = 2;
-                               goto out;
+                               ret = EEH_NEXT_ERR_FENCED_PHB;
                        } else if (severity == OPAL_EEH_SEV_INF) {
                                pr_info("EEH: PHB#%x informative error "
                                        "detected\n",
                                        hose->global_number);
                                ioda_eeh_phb_diag(hose);
+                               ret = EEH_NEXT_ERR_NONE;
                        }
 
                        break;
                case OPAL_EEH_PE_ERROR:
-                       if (ioda_eeh_get_pe(hose, frozen_pe_no, pe))
-                               break;
+                       /*
+                        * If we can't find the corresponding PE, the
+                        * PEEV / PEST would be messy. So we force an
+                        * fenced PHB so that it can be recovered.
+                        */
+                       if (ioda_eeh_get_pe(hose, frozen_pe_no, pe)) {
+                               if (!ioda_eeh_get_phb_pe(hose, pe)) {
+                                       pr_err("EEH: Escalated fenced PHB#%x "
+                                              "detected for PE#%llx\n",
+                                               hose->global_number,
+                                               frozen_pe_no);
+                                       ret = EEH_NEXT_ERR_FENCED_PHB;
+                               } else {
+                                       ret = EEH_NEXT_ERR_NONE;
+                               }
+                       } else {
+                               pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
+                                       (*pe)->addr, (*pe)->phb->global_number);
+                               ret = EEH_NEXT_ERR_FROZEN_PE;
+                       }
 
-                       pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
-                               (*pe)->addr, (*pe)->phb->global_number);
-                       ret = 1;
-                       goto out;
+                       break;
+               default:
+                       pr_warn("%s: Unexpected error type %d\n",
+                               __func__, err_type);
                }
+
+               /*
+                * If we have no errors on the specific PHB or only
+                * informative error there, we continue poking it.
+                * Otherwise, we need actions to be taken by upper
+                * layer.
+                */
+               if (ret > EEH_NEXT_ERR_INF)
+                       break;
        }
 
-       ret = 0;
-out:
        return ret;
 }
 
index 73b981438cc583e0ba4345129046d56b72a8b9c1..a79fddc5e74e58ac0a0b18fc1b7cb5db607095b2 100644 (file)
@@ -344,6 +344,27 @@ static int powernv_eeh_next_error(struct eeh_pe **pe)
        return -EEXIST;
 }
 
+static int powernv_eeh_restore_config(struct device_node *dn)
+{
+       struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+       struct pnv_phb *phb;
+       s64 ret;
+
+       if (!edev)
+               return -EEXIST;
+
+       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);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static struct eeh_ops powernv_eeh_ops = {
        .name                   = "powernv",
        .init                   = powernv_eeh_init,
@@ -359,7 +380,8 @@ static struct eeh_ops powernv_eeh_ops = {
        .configure_bridge       = powernv_eeh_configure_bridge,
        .read_config            = pnv_pci_cfg_read,
        .write_config           = pnv_pci_cfg_write,
-       .next_error             = powernv_eeh_next_error
+       .next_error             = powernv_eeh_next_error,
+       .restore_config         = powernv_eeh_restore_config
 };
 
 /**
index d8773079ce195afd380a6fa97c5fc5809a976a78..714ef972406bcacf66a4a896283c6fb25963ca16 100644 (file)
@@ -76,8 +76,8 @@
 /* Validate buffer size */
 #define VALIDATE_BUF_SIZE      4096
 
-/* XXX: Assume candidate image size is <= 256MB */
-#define MAX_IMAGE_SIZE 0x10000000
+/* XXX: Assume candidate image size is <= 1GB */
+#define MAX_IMAGE_SIZE 0x40000000
 
 /* Flash sg list version */
 #define SG_LIST_VERSION (1UL)
@@ -103,27 +103,6 @@ struct image_header_t {
        uint32_t        size;
 };
 
-/* Scatter/gather entry */
-struct opal_sg_entry {
-       void    *data;
-       long    length;
-};
-
-/* We calculate number of entries based on PAGE_SIZE */
-#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
-
-/*
- * This struct is very similar but not identical to that
- * needed by the opal flash update. All we need to do for
- * opal is rewrite num_entries into a version/length and
- * translate the pointers to absolute.
- */
-struct opal_sg_list {
-       unsigned long num_entries;
-       struct opal_sg_list *next;
-       struct opal_sg_entry entry[SG_ENTRIES_PER_NODE];
-};
-
 struct validate_flash_t {
        int             status;         /* Return status */
        void            *buf;           /* Candidate image buffer */
@@ -333,7 +312,7 @@ static struct opal_sg_list *image_data_to_sglist(void)
        addr = image_data.data;
        size = image_data.size;
 
-       sg1 = kzalloc((sizeof(struct opal_sg_list)), GFP_KERNEL);
+       sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!sg1)
                return NULL;
 
@@ -351,8 +330,7 @@ static struct opal_sg_list *image_data_to_sglist(void)
 
                sg1->num_entries++;
                if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
-                       sg1->next = kzalloc((sizeof(struct opal_sg_list)),
-                                           GFP_KERNEL);
+                       sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
                        if (!sg1->next) {
                                pr_err("%s : Failed to allocate memory\n",
                                       __func__);
@@ -402,7 +380,10 @@ static int opal_flash_update(int op)
                else
                        sg->next = NULL;
 
-               /* Make num_entries into the version/length field */
+               /*
+                * Convert num_entries to version/length format
+                * to satisfy OPAL.
+                */
                sg->num_entries = (SG_LIST_VERSION << 56) |
                        (sg->num_entries * sizeof(struct opal_sg_entry) + 16);
        }
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c
new file mode 100644 (file)
index 0000000..ec41322
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * OPAL asynchronus Memory error handling support in PowreNV.
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/opal.h>
+#include <asm/cputable.h>
+
+static int opal_mem_err_nb_init;
+static LIST_HEAD(opal_memory_err_list);
+static DEFINE_SPINLOCK(opal_mem_err_lock);
+
+struct OpalMsgNode {
+       struct list_head list;
+       struct opal_msg msg;
+};
+
+static void handle_memory_error_event(struct OpalMemoryErrorData *merr_evt)
+{
+       uint64_t paddr_start, paddr_end;
+
+       pr_debug("%s: Retrived memory error event, type: 0x%x\n",
+                 __func__, merr_evt->type);
+       switch (merr_evt->type) {
+       case OPAL_MEM_ERR_TYPE_RESILIENCE:
+               paddr_start = merr_evt->u.resilience.physical_address_start;
+               paddr_end = merr_evt->u.resilience.physical_address_end;
+               break;
+       case OPAL_MEM_ERR_TYPE_DYN_DALLOC:
+               paddr_start = merr_evt->u.dyn_dealloc.physical_address_start;
+               paddr_end = merr_evt->u.dyn_dealloc.physical_address_end;
+               break;
+       default:
+               return;
+       }
+
+       for (; paddr_start < paddr_end; paddr_start += PAGE_SIZE) {
+               memory_failure(paddr_start >> PAGE_SHIFT, 0, 0);
+       }
+}
+
+static void handle_memory_error(void)
+{
+       unsigned long flags;
+       struct OpalMemoryErrorData *merr_evt;
+       struct OpalMsgNode *msg_node;
+
+       spin_lock_irqsave(&opal_mem_err_lock, flags);
+       while (!list_empty(&opal_memory_err_list)) {
+                msg_node = list_entry(opal_memory_err_list.next,
+                                          struct OpalMsgNode, list);
+               list_del(&msg_node->list);
+               spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+
+               merr_evt = (struct OpalMemoryErrorData *)
+                                       &msg_node->msg.params[0];
+               handle_memory_error_event(merr_evt);
+               kfree(msg_node);
+               spin_lock_irqsave(&opal_mem_err_lock, flags);
+       }
+       spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+}
+
+static void mem_error_handler(struct work_struct *work)
+{
+       handle_memory_error();
+}
+
+static DECLARE_WORK(mem_error_work, mem_error_handler);
+
+/*
+ * opal_memory_err_event - notifier handler that queues up the opal message
+ * to be preocessed later.
+ */
+static int opal_memory_err_event(struct notifier_block *nb,
+                         unsigned long msg_type, void *msg)
+{
+       unsigned long flags;
+       struct OpalMsgNode *msg_node;
+
+       if (msg_type != OPAL_MSG_MEM_ERR)
+               return 0;
+
+       msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC);
+       if (!msg_node) {
+               pr_err("MEMORY_ERROR: out of memory, Opal message event not"
+                      "handled\n");
+               return -ENOMEM;
+       }
+       memcpy(&msg_node->msg, msg, sizeof(struct opal_msg));
+
+       spin_lock_irqsave(&opal_mem_err_lock, flags);
+       list_add(&msg_node->list, &opal_memory_err_list);
+       spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+
+       schedule_work(&mem_error_work);
+       return 0;
+}
+
+static struct notifier_block opal_mem_err_nb = {
+       .notifier_call  = opal_memory_err_event,
+       .next           = NULL,
+       .priority       = 0,
+};
+
+static int __init opal_mem_err_init(void)
+{
+       int ret;
+
+       if (!opal_mem_err_nb_init) {
+               ret = opal_message_notifier_register(
+                                       OPAL_MSG_MEM_ERR, &opal_mem_err_nb);
+               if (ret) {
+                       pr_err("%s: Can't register OPAL event notifier (%d)\n",
+                              __func__, ret);
+                       return ret;
+               }
+               opal_mem_err_nb_init = 1;
+       }
+       return 0;
+}
+subsys_initcall(opal_mem_err_init);
index 7d07c7e80ec09e9232b3cafd9c41a104992b5331..b1885db8fdf34bfe068f1712d486f6884dc50d0e 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/opal.h>
 #include <asm/firmware.h>
+#include <asm/machdep.h>
 
 static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
 {
@@ -48,8 +49,11 @@ unsigned long __init opal_get_boot_time(void)
                else
                        mdelay(10);
        }
-       if (rc != OPAL_SUCCESS)
+       if (rc != OPAL_SUCCESS) {
+               ppc_md.get_rtc_time = NULL;
+               ppc_md.set_rtc_time = NULL;
                return 0;
+       }
        y_m_d = be32_to_cpu(__y_m_d);
        h_m_s_ms = be64_to_cpu(__h_m_s_ms);
        opal_to_tm(y_m_d, h_m_s_ms, &tm);
index e7806504e9769162f921e704cf55d0b3e210cf6c..3e8829c40fbbfc436adb206fb297b82ea7385e89 100644 (file)
@@ -126,3 +126,6 @@ OPAL_CALL(opal_return_cpu,                  OPAL_RETURN_CPU);
 OPAL_CALL(opal_validate_flash,                 OPAL_FLASH_VALIDATE);
 OPAL_CALL(opal_manage_flash,                   OPAL_FLASH_MANAGE);
 OPAL_CALL(opal_update_flash,                   OPAL_FLASH_UPDATE);
+OPAL_CALL(opal_get_msg,                                OPAL_GET_MSG);
+OPAL_CALL(opal_check_completion,               OPAL_CHECK_ASYNC_COMPLETION);
+OPAL_CALL(opal_sync_host_reboot,               OPAL_SYNC_HOST_REBOOT);
index 1c798cd553722f6f043a066c299100be89c10f96..65499adaecff2a1e2367612ece5e051028e38634 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/kobject.h>
+#include <linux/delay.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
+#include <asm/mce.h>
 
 #include "powernv.h"
 
@@ -38,6 +41,7 @@ extern u64 opal_mc_secondary_handler[];
 static unsigned int *opal_irqs;
 static unsigned int opal_irq_count;
 static ATOMIC_NOTIFIER_HEAD(opal_notifier_head);
+static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
 static DEFINE_SPINLOCK(opal_notifier_lock);
 static uint64_t last_notified_mask = 0x0ul;
 static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
@@ -88,14 +92,10 @@ static int __init opal_register_exception_handlers(void)
        if (!(powerpc_firmware_features & FW_FEATURE_OPAL))
                return -ENODEV;
 
-       /* Hookup some exception handlers. We use the fwnmi area at 0x7000
-        * to provide the glue space to OPAL
+       /* Hookup some exception handlers except machine check. We use the
+        * fwnmi area at 0x7000 to provide the glue space to OPAL
         */
        glue = 0x7000;
-       opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
-                                       __pa(opal_mc_secondary_handler[0]),
-                                       glue);
-       glue += 128;
        opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
                                        0, glue);
        glue += 128;
@@ -169,6 +169,95 @@ void opal_notifier_disable(void)
        atomic_set(&opal_notifier_hold, 1);
 }
 
+/*
+ * Opal message notifier based on message type. Allow subscribers to get
+ * notified for specific messgae type.
+ */
+int opal_message_notifier_register(enum OpalMessageType msg_type,
+                                       struct notifier_block *nb)
+{
+       if (!nb) {
+               pr_warning("%s: Invalid argument (%p)\n",
+                          __func__, nb);
+               return -EINVAL;
+       }
+       if (msg_type > OPAL_MSG_TYPE_MAX) {
+               pr_warning("%s: Invalid message type argument (%d)\n",
+                          __func__, msg_type);
+               return -EINVAL;
+       }
+       return atomic_notifier_chain_register(
+                               &opal_msg_notifier_head[msg_type], nb);
+}
+
+static void opal_message_do_notify(uint32_t msg_type, void *msg)
+{
+       /* notify subscribers */
+       atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
+                                       msg_type, msg);
+}
+
+static void opal_handle_message(void)
+{
+       s64 ret;
+       /*
+        * TODO: pre-allocate a message buffer depending on opal-msg-size
+        * value in /proc/device-tree.
+        */
+       static struct opal_msg msg;
+
+       ret = opal_get_msg(__pa(&msg), sizeof(msg));
+       /* No opal message pending. */
+       if (ret == OPAL_RESOURCE)
+               return;
+
+       /* check for errors. */
+       if (ret) {
+               pr_warning("%s: Failed to retrive opal message, err=%lld\n",
+                               __func__, ret);
+               return;
+       }
+
+       /* Sanity check */
+       if (msg.msg_type > OPAL_MSG_TYPE_MAX) {
+               pr_warning("%s: Unknown message type: %u\n",
+                               __func__, msg.msg_type);
+               return;
+       }
+       opal_message_do_notify(msg.msg_type, (void *)&msg);
+}
+
+static int opal_message_notify(struct notifier_block *nb,
+                         unsigned long events, void *change)
+{
+       if (events & OPAL_EVENT_MSG_PENDING)
+               opal_handle_message();
+       return 0;
+}
+
+static struct notifier_block opal_message_nb = {
+       .notifier_call  = opal_message_notify,
+       .next           = NULL,
+       .priority       = 0,
+};
+
+static int __init opal_message_init(void)
+{
+       int ret, i;
+
+       for (i = 0; i < OPAL_MSG_TYPE_MAX; i++)
+               ATOMIC_INIT_NOTIFIER_HEAD(&opal_msg_notifier_head[i]);
+
+       ret = opal_notifier_register(&opal_message_nb);
+       if (ret) {
+               pr_err("%s: Can't register OPAL event notifier (%d)\n",
+                      __func__, ret);
+               return ret;
+       }
+       return 0;
+}
+early_initcall(opal_message_init);
+
 int opal_get_chars(uint32_t vtermno, char *buf, int count)
 {
        s64 rc;
@@ -254,119 +343,62 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
        return written;
 }
 
+static int opal_recover_mce(struct pt_regs *regs,
+                                       struct machine_check_event *evt)
+{
+       int recovered = 0;
+       uint64_t ea = get_mce_fault_addr(evt);
+
+       if (!(regs->msr & MSR_RI)) {
+               /* If MSR_RI isn't set, we cannot recover */
+               recovered = 0;
+       } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
+               /* Platform corrected itself */
+               recovered = 1;
+       } else if (ea && !is_kernel_addr(ea)) {
+               /*
+                * Faulting address is not in kernel text. We should be fine.
+                * We need to find which process uses this address.
+                * For now, kill the task if we have received exception when
+                * in userspace.
+                *
+                * TODO: Queue up this address for hwpoisioning later.
+                */
+               if (user_mode(regs) && !is_global_init(current)) {
+                       _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+                       recovered = 1;
+               } else
+                       recovered = 0;
+       } else if (user_mode(regs) && !is_global_init(current) &&
+               evt->severity == MCE_SEV_ERROR_SYNC) {
+               /*
+                * If we have received a synchronous error when in userspace
+                * kill the task.
+                */
+               _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+               recovered = 1;
+       }
+       return recovered;
+}
+
 int opal_machine_check(struct pt_regs *regs)
 {
-       struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
-       struct opal_machine_check_event evt;
-       const char *level, *sevstr, *subtype;
-       static const char *opal_mc_ue_types[] = {
-               "Indeterminate",
-               "Instruction fetch",
-               "Page table walk ifetch",
-               "Load/Store",
-               "Page table walk Load/Store",
-       };
-       static const char *opal_mc_slb_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-       static const char *opal_mc_erat_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-       static const char *opal_mc_tlb_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-
-       /* Copy the event structure and release the original */
-       evt = *opal_evt;
-       opal_evt->in_use = 0;
+       struct machine_check_event evt;
+
+       if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
+               return 0;
 
        /* Print things out */
-       if (evt.version != OpalMCE_V1) {
+       if (evt.version != MCE_V1) {
                pr_err("Machine Check Exception, Unknown event version %d !\n",
                       evt.version);
                return 0;
        }
-       switch(evt.severity) {
-       case OpalMCE_SEV_NO_ERROR:
-               level = KERN_INFO;
-               sevstr = "Harmless";
-               break;
-       case OpalMCE_SEV_WARNING:
-               level = KERN_WARNING;
-               sevstr = "";
-               break;
-       case OpalMCE_SEV_ERROR_SYNC:
-               level = KERN_ERR;
-               sevstr = "Severe";
-               break;
-       case OpalMCE_SEV_FATAL:
-       default:
-               level = KERN_ERR;
-               sevstr = "Fatal";
-               break;
-       }
+       machine_check_print_event_info(&evt);
 
-       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
-              evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
-              "Recovered" : "[Not recovered");
-       printk("%s  Initiator: %s\n", level,
-              evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
-       switch(evt.error_type) {
-       case OpalMCE_ERROR_TYPE_UE:
-               subtype = evt.u.ue_error.ue_error_type <
-                       ARRAY_SIZE(opal_mc_ue_types) ?
-                       opal_mc_ue_types[evt.u.ue_error.ue_error_type]
-                       : "Unknown";
-               printk("%s  Error type: UE [%s]\n", level, subtype);
-               if (evt.u.ue_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.ue_error.effective_address);
-               if (evt.u.ue_error.physical_address_provided)
-                       printk("%s      Physial address: %016llx\n",
-                              level, evt.u.ue_error.physical_address);
-               break;
-       case OpalMCE_ERROR_TYPE_SLB:
-               subtype = evt.u.slb_error.slb_error_type <
-                       ARRAY_SIZE(opal_mc_slb_types) ?
-                       opal_mc_slb_types[evt.u.slb_error.slb_error_type]
-                       : "Unknown";
-               printk("%s  Error type: SLB [%s]\n", level, subtype);
-               if (evt.u.slb_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.slb_error.effective_address);
-               break;
-       case OpalMCE_ERROR_TYPE_ERAT:
-               subtype = evt.u.erat_error.erat_error_type <
-                       ARRAY_SIZE(opal_mc_erat_types) ?
-                       opal_mc_erat_types[evt.u.erat_error.erat_error_type]
-                       : "Unknown";
-               printk("%s  Error type: ERAT [%s]\n", level, subtype);
-               if (evt.u.erat_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.erat_error.effective_address);
-               break;
-       case OpalMCE_ERROR_TYPE_TLB:
-               subtype = evt.u.tlb_error.tlb_error_type <
-                       ARRAY_SIZE(opal_mc_tlb_types) ?
-                       opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
-                       : "Unknown";
-               printk("%s  Error type: TLB [%s]\n", level, subtype);
-               if (evt.u.tlb_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.tlb_error.effective_address);
-               break;
-       default:
-       case OpalMCE_ERROR_TYPE_UNKNOWN:
-               printk("%s  Error type: Unknown\n", level);
-               break;
-       }
-       return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+       if (opal_recover_mce(regs, &evt))
+               return 1;
+       return 0;
 }
 
 static irqreturn_t opal_interrupt(int irq, void *data)
@@ -451,10 +483,25 @@ subsys_initcall(opal_init);
 void opal_shutdown(void)
 {
        unsigned int i;
+       long rc = OPAL_BUSY;
 
+       /* First free interrupts, which will also mask them */
        for (i = 0; i < opal_irq_count; i++) {
                if (opal_irqs[i])
                        free_irq(opal_irqs[i], NULL);
                opal_irqs[i] = 0;
        }
+
+       /*
+        * Then sync with OPAL which ensure anything that can
+        * potentially write to our memory has completed such
+        * as an ongoing dump retrieval
+        */
+       while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
+               rc = opal_sync_host_reboot();
+               if (rc == OPAL_BUSY)
+                       opal_poll_events(NULL);
+               else
+                       mdelay(10);
+       }
 }
index 2c6d173842b2f1056d3702826b3c2a1d84d614ad..7d6dcc6d5fa9a6551c2465285cc1886242cc0125 100644 (file)
@@ -460,7 +460,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
                return;
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
-       set_iommu_table_base(&pdev->dev, &pe->tce32_table);
+       set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
 }
 
 static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
@@ -468,7 +468,7 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               set_iommu_table_base(&dev->dev, &pe->tce32_table);
+               set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table);
                if (dev->subordinate)
                        pnv_ioda_setup_bus_dma(pe, dev->subordinate);
        }
@@ -644,7 +644,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
        iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
-               set_iommu_table_base(&pe->pdev->dev, tbl);
+               set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
        else
                pnv_ioda_setup_bus_dma(pe, pe->pbus);
 
@@ -723,7 +723,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
        iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
-               set_iommu_table_base(&pe->pdev->dev, tbl);
+               set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
        else
                pnv_ioda_setup_bus_dma(pe, pe->pbus);
 
@@ -1144,7 +1144,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
 {
        struct pci_controller *hose;
        struct pnv_phb *phb;
-       unsigned long size, m32map_off, iomap_off, pemap_off;
+       unsigned long size, m32map_off, pemap_off, iomap_off = 0;
        const __be64 *prop64;
        const __be32 *prop32;
        int len;
@@ -1231,7 +1231,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
        size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
        m32map_off = size;
        size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
-       iomap_off = size;
        if (phb->type == PNV_PHB_IODA1) {
                iomap_off = size;
                size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
index f8b4bd8afb2e5da39cd8632c7a6a8eae54448aeb..e3807d69393e02c753e1777cffb03c5d6ae0db74 100644 (file)
@@ -92,7 +92,7 @@ static void pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
                                pci_domain_nr(phb->hose->bus), phb->opal_id);
        }
 
-       set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+       set_iommu_table_base_and_group(&pdev->dev, &phb->p5ioc2.iommu_table);
 }
 
 static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id,
index 4eb33a9ed5325a3e84b2a7f1d4d58d5dc7fa7b22..b555ebc57ef5a33010ea4becbf992d3deb2dcbad 100644 (file)
@@ -124,77 +124,157 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
 }
 #endif /* CONFIG_PCI_MSI */
 
-static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
+static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
+                                        struct OpalIoPhbErrorCommon *common)
 {
-       struct OpalIoP7IOCPhbErrorData *data = &phb->diag.p7ioc;
+       struct OpalIoP7IOCPhbErrorData *data;
        int i;
 
-       pr_info("PHB %d diagnostic data:\n", phb->hose->global_number);
-
-       pr_info("  brdgCtl              = 0x%08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg        = 0x%08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus      = 0x%08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus       = 0x%08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus         = 0x%08x\n", data->deviceStatus);
-       pr_info("  slotStatus           = 0x%08x\n", data->slotStatus);
-       pr_info("  linkStatus           = 0x%08x\n", data->linkStatus);
-       pr_info("  devCmdStatus         = 0x%08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus         = 0x%08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus      = 0x%08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus    = 0x%08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus      = 0x%08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1              = 0x%08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2              = 0x%08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3              = 0x%08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4              = 0x%08x\n", data->tlpHdr4);
-       pr_info("  sourceId             = 0x%08x\n", data->sourceId);
-
-       pr_info("  errorClass           = 0x%016llx\n", data->errorClass);
-       pr_info("  correlator           = 0x%016llx\n", data->correlator);
-
-       pr_info("  p7iocPlssr           = 0x%016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr             = 0x%016llx\n", data->p7iocCsr);
-       pr_info("  lemFir               = 0x%016llx\n", data->lemFir);
-       pr_info("  lemErrorMask         = 0x%016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF               = 0x%016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus       = 0x%016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus  = 0x%016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0         = 0x%016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1         = 0x%016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus      = 0x%016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus = 0x%016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0        = 0x%016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1        = 0x%016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus      = 0x%016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus = 0x%016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0        = 0x%016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1        = 0x%016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus      = 0x%016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus = 0x%016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0        = 0x%016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1        = 0x%016llx\n", data->dma1ErrorLog1);
+       data = (struct OpalIoP7IOCPhbErrorData *)common;
+       pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
+               hose->global_number, common->version);
+
+       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
+
+       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
+       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
+       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
+
+       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
+       pr_info("  slotStatus:           %08x\n", data->slotStatus);
+       pr_info("  linkStatus:           %08x\n", data->linkStatus);
+       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
+       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
+
+       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
+       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
+       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
+       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
+       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
+       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
+       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
+       pr_info("  sourceId:             %08x\n", data->sourceId);
+       pr_info("  errorClass:           %016llx\n", data->errorClass);
+       pr_info("  correlator:           %016llx\n", data->correlator);
+       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
+       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
+       pr_info("  lemFir:               %016llx\n", data->lemFir);
+       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
+       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
+       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
+       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
+       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
+       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
+       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
+       pr_info("  mmioFirstErrorStatus%016llx\n", data->mmioFirstErrorStatus);
+       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
+       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
+       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
+       pr_info("  dma0FirstErrorStatus%016llx\n", data->dma0FirstErrorStatus);
+       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
+       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
+       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
+       pr_info("  dma1FirstErrorStatus%016llx\n", data->dma1FirstErrorStatus);
+       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
+       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
-               pr_info("  PE[%3d] PESTA        = 0x%016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB        = 0x%016llx\n", data->pestB[i]);
+
+               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
+               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+       }
+}
+
+static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose,
+                                       struct OpalIoPhbErrorCommon *common)
+{
+       struct OpalIoPhb3ErrorData *data;
+       int i;
+
+       data = (struct OpalIoPhb3ErrorData*)common;
+       pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
+               hose->global_number, common->version);
+
+       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
+
+       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
+       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
+       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
+
+       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
+       pr_info("  slotStatus:           %08x\n", data->slotStatus);
+       pr_info("  linkStatus:           %08x\n", data->linkStatus);
+       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
+       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
+
+       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
+       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
+       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
+       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
+       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
+       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
+       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
+       pr_info("  sourceId:             %08x\n", data->sourceId);
+       pr_info("  errorClass:           %016llx\n", data->errorClass);
+       pr_info("  correlator:           %016llx\n", data->correlator);
+
+       pr_info("  nFir:                 %016llx\n", data->nFir);
+       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
+       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
+       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
+       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
+       pr_info("  lemFir:               %016llx\n", data->lemFir);
+       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
+       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
+       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
+       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
+       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
+       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
+       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
+       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
+       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
+       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
+       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
+       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
+       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
+       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
+       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
+       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
+       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
+       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+
+       for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
+               if ((data->pestA[i] >> 63) == 0 &&
+                   (data->pestB[i] >> 63) == 0)
+                       continue;
+
+               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
+               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
        }
 }
 
-static void pnv_pci_dump_phb_diag_data(struct pnv_phb *phb)
+void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
+                               unsigned char *log_buff)
 {
-       switch(phb->model) {
-       case PNV_PHB_MODEL_P7IOC:
-               pnv_pci_dump_p7ioc_diag_data(phb);
+       struct OpalIoPhbErrorCommon *common;
+
+       if (!hose || !log_buff)
+               return;
+
+       common = (struct OpalIoPhbErrorCommon *)log_buff;
+       switch (common->ioType) {
+       case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
+               pnv_pci_dump_p7ioc_diag_data(hose, common);
+               break;
+       case OPAL_PHB_ERROR_DATA_TYPE_PHB3:
+               pnv_pci_dump_phb3_diag_data(hose, common);
                break;
        default:
-               pr_warning("PCI %d: Can't decode this PHB diag data\n",
-                          phb->hose->global_number);
+               pr_warn("%s: Unrecognized ioType %d\n",
+                       __func__, common->ioType);
        }
 }
 
@@ -222,7 +302,7 @@ static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
                 * with the normal errors generated when probing empty slots
                 */
                if (has_diag)
-                       pnv_pci_dump_phb_diag_data(phb);
+                       pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
                else
                        pr_warning("PCI %d: No diag data available\n",
                                   phb->hose->global_number);
@@ -484,7 +564,8 @@ void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 {
        tbl->it_blocksize = 16;
        tbl->it_base = (unsigned long)tce_mem;
-       tbl->it_offset = dma_offset >> IOMMU_PAGE_SHIFT;
+       tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
+       tbl->it_offset = dma_offset >> tbl->it_page_shift;
        tbl->it_index = 0;
        tbl->it_size = tce_size >> 3;
        tbl->it_busno = 0;
@@ -536,7 +617,7 @@ static void pnv_pci_dma_fallback_setup(struct pci_controller *hose,
                pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
        if (!pdn->iommu_table)
                return;
-       set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+       set_iommu_table_base_and_group(&pdev->dev, pdn->iommu_table);
 }
 
 static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
@@ -657,3 +738,32 @@ void __init pnv_pci_init(void)
        ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
 #endif
 }
+
+static int tce_iommu_bus_notifier(struct notifier_block *nb,
+               unsigned long action, void *data)
+{
+       struct device *dev = data;
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               return iommu_add_device(dev);
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (dev->iommu_group)
+                       iommu_del_device(dev);
+               return 0;
+       default:
+               return 0;
+       }
+}
+
+static struct notifier_block tce_iommu_bus_nb = {
+       .notifier_call = tce_iommu_bus_notifier,
+};
+
+static int __init tce_iommu_bus_notifier_init(void)
+{
+       bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
+       return 0;
+}
+
+subsys_initcall_sync(tce_iommu_bus_notifier_init);
index 1ed8d5f40f5ad1423f78c9ae7fdac42abac4376d..13f1942a9a5f98708038808a2d816f2bec0d6e1a 100644 (file)
@@ -176,6 +176,7 @@ struct pnv_phb {
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoPhb3ErrorData      phb3;
                struct OpalIoP7IOCErrorData     hub_diag;
        } diag;
 
@@ -186,6 +187,8 @@ extern struct pci_ops pnv_pci_ops;
 extern struct pnv_eeh_ops ioda_eeh_ops;
 #endif
 
+void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
+                               unsigned char *log_buff);
 int pnv_pci_cfg_read(struct device_node *dn,
                     int where, int size, u32 *val);
 int pnv_pci_cfg_write(struct device_node *dn,
index 19884b2a51b4743f78a9389f22e8588e228616d7..a932feb2901c74df383aa7114b256ed57007b677 100644 (file)
@@ -145,8 +145,10 @@ static void pnv_shutdown(void)
        /* Let the PCI code clear up IODA tables */
        pnv_pci_shutdown();
 
-       /* And unregister all OPAL interrupts so they don't fire
-        * up while we kexec
+       /*
+        * Stop OPAL activity: Unregister all OPAL interrupts so they
+        * don't fire up while we kexec and make sure all potentially
+        * DMA'ing ops are complete (such as dump retrieval).
         */
        opal_shutdown();
 }
index e17fa1432d80706ad9b5fa2682ea88751027c38a..a0bca05e26b0c7478c7483c43b2437fa0f6a61d7 100644 (file)
@@ -143,7 +143,7 @@ static void _dump_areas(unsigned int spe_id, unsigned long priv2,
        pr_debug("%s:%d: shadow:  %lxh\n", func, line, shadow);
 }
 
-inline u64 ps3_get_spe_id(void *arg)
+u64 ps3_get_spe_id(void *arg)
 {
        return spu_pdata(arg)->spe_id;
 }
index 62b4f8025de005ad77bdbfcd42024d25614eb79c..e66643250fee3eea1c2de2d832f9b3cbb0fc7632 100644 (file)
@@ -34,7 +34,7 @@ config PPC_SPLPAR
 
 config PSERIES_MSI
        bool
-       depends on PCI_MSI && EEH
+       depends on PCI_MSI && PPC_PSERIES && EEH
        default y
 
 config PSERIES_ENERGY
index 1e561bef459b4261d4e06f8ee2c563edc04e7e9d..2d8bf15879fdd3e14da6c8c46f6bbeaf7ab3f138 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/gfp.h>
-#include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/oom.h>
index 5db66f1fbc2648f41244b15ca07fdc8bfad7ad5d..7d61498e45c082fee52f370be623dd8f97114f62 100644 (file)
@@ -20,7 +20,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
 #include <linux/spinlock.h>
index ccb633e077b16d6c7a57bb6cfd4372ca87ceeb6a..9ef3cc8ebc11c7f533a3bc966d90bd6c085d891d 100644 (file)
@@ -689,7 +689,9 @@ static struct eeh_ops pseries_eeh_ops = {
        .get_log                = pseries_eeh_get_log,
        .configure_bridge       = pseries_eeh_configure_bridge,
        .read_config            = pseries_eeh_read_config,
-       .write_config           = pseries_eeh_write_config
+       .write_config           = pseries_eeh_write_config,
+       .next_error             = NULL,
+       .restore_config         = NULL
 };
 
 /**
index f253361552aee3fbc3c98f077790f89551b4ea74..33b552ffbe576d4b452f31aa22af5b6a16a9cd0c 100644 (file)
@@ -486,9 +486,10 @@ static void iommu_table_setparms(struct pci_controller *phb,
                memset((void *)tbl->it_base, 0, *sizep);
 
        tbl->it_busno = phb->bus->number;
+       tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
 
        /* Units of tce entries */
-       tbl->it_offset = phb->dma_window_base_cur >> IOMMU_PAGE_SHIFT;
+       tbl->it_offset = phb->dma_window_base_cur >> tbl->it_page_shift;
 
        /* Test if we are going over 2GB of DMA space */
        if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
@@ -499,7 +500,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
        phb->dma_window_base_cur += phb->dma_window_size;
 
        /* Set the tce table size - measured in entries */
-       tbl->it_size = phb->dma_window_size >> IOMMU_PAGE_SHIFT;
+       tbl->it_size = phb->dma_window_size >> tbl->it_page_shift;
 
        tbl->it_index = 0;
        tbl->it_blocksize = 16;
@@ -537,11 +538,12 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
        of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
 
        tbl->it_busno = phb->bus->number;
+       tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
        tbl->it_base   = 0;
        tbl->it_blocksize  = 16;
        tbl->it_type = TCE_PCI;
-       tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
-       tbl->it_size = size >> IOMMU_PAGE_SHIFT;
+       tbl->it_offset = offset >> tbl->it_page_shift;
+       tbl->it_size = size >> tbl->it_page_shift;
 }
 
 static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
@@ -687,7 +689,8 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
                iommu_table_setparms(phb, dn, tbl);
                PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
                iommu_register_group(tbl, pci_domain_nr(phb->bus), 0);
-               set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table);
+               set_iommu_table_base_and_group(&dev->dev,
+                                              PCI_DN(dn)->iommu_table);
                return;
        }
 
@@ -699,7 +702,8 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
                dn = dn->parent;
 
        if (dn && PCI_DN(dn))
-               set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table);
+               set_iommu_table_base_and_group(&dev->dev,
+                                              PCI_DN(dn)->iommu_table);
        else
                printk(KERN_WARNING "iommu: Device %s has no iommu table\n",
                       pci_name(dev));
@@ -717,21 +721,6 @@ static int __init disable_ddw_setup(char *str)
 
 early_param("disable_ddw", disable_ddw_setup);
 
-static inline void __remove_ddw(struct device_node *np, const u32 *ddw_avail, u64 liobn)
-{
-       int ret;
-
-       ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn);
-       if (ret)
-               pr_warning("%s: failed to remove DMA window: rtas returned "
-                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
-                       np->full_name, ret, ddw_avail[2], liobn);
-       else
-               pr_debug("%s: successfully removed DMA window: rtas returned "
-                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
-                       np->full_name, ret, ddw_avail[2], liobn);
-}
-
 static void remove_ddw(struct device_node *np)
 {
        struct dynamic_dma_window_prop *dwp;
@@ -761,7 +750,15 @@ static void remove_ddw(struct device_node *np)
                pr_debug("%s successfully cleared tces in window.\n",
                         np->full_name);
 
-       __remove_ddw(np, ddw_avail, liobn);
+       ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn);
+       if (ret)
+               pr_warning("%s: failed to remove direct window: rtas returned "
+                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+                       np->full_name, ret, ddw_avail[2], liobn);
+       else
+               pr_debug("%s: successfully removed direct window: rtas returned "
+                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+                       np->full_name, ret, ddw_avail[2], liobn);
 
 delprop:
        ret = of_remove_property(np, win64);
@@ -790,68 +787,33 @@ static u64 find_existing_ddw(struct device_node *pdn)
        return dma_addr;
 }
 
-static void __restore_default_window(struct eeh_dev *edev,
-                                               u32 ddw_restore_token)
-{
-       u32 cfg_addr;
-       u64 buid;
-       int ret;
-
-       /*
-        * Get the config address and phb buid of the PE window.
-        * Rely on eeh to retrieve this for us.
-        * Retrieve them from the pci device, not the node with the
-        * dma-window property
-        */
-       cfg_addr = edev->config_addr;
-       if (edev->pe_config_addr)
-               cfg_addr = edev->pe_config_addr;
-       buid = edev->phb->buid;
-
-       do {
-               ret = rtas_call(ddw_restore_token, 3, 1, NULL, cfg_addr,
-                                       BUID_HI(buid), BUID_LO(buid));
-       } while (rtas_busy_delay(ret));
-       pr_info("ibm,reset-pe-dma-windows(%x) %x %x %x returned %d\n",
-                ddw_restore_token, cfg_addr, BUID_HI(buid), BUID_LO(buid), ret);
-}
-
 static int find_existing_ddw_windows(void)
 {
+       int len;
        struct device_node *pdn;
+       struct direct_window *window;
        const struct dynamic_dma_window_prop *direct64;
-       const u32 *ddw_extensions;
 
        if (!firmware_has_feature(FW_FEATURE_LPAR))
                return 0;
 
        for_each_node_with_property(pdn, DIRECT64_PROPNAME) {
-               direct64 = of_get_property(pdn, DIRECT64_PROPNAME, NULL);
+               direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
                if (!direct64)
                        continue;
 
-               /*
-                * We need to ensure the IOMMU table is active when we
-                * return from the IOMMU setup so that the common code
-                * can clear the table or find the holes. To that end,
-                * first, remove any existing DDW configuration.
-                */
-               remove_ddw(pdn);
+               window = kzalloc(sizeof(*window), GFP_KERNEL);
+               if (!window || len < sizeof(struct dynamic_dma_window_prop)) {
+                       kfree(window);
+                       remove_ddw(pdn);
+                       continue;
+               }
 
-               /*
-                * Second, if we are running on a new enough level of
-                * firmware where the restore API is present, use it to
-                * restore the 32-bit window, which was removed in
-                * create_ddw.
-                * If the API is not present, then create_ddw couldn't
-                * have removed the 32-bit window in the first place, so
-                * removing the DDW configuration should be sufficient.
-                */
-               ddw_extensions = of_get_property(pdn, "ibm,ddw-extensions",
-                                                                       NULL);
-               if (ddw_extensions && ddw_extensions[0] > 0)
-                       __restore_default_window(of_node_to_eeh_dev(pdn),
-                                                       ddw_extensions[1]);
+               window->device = pdn;
+               window->prop = direct64;
+               spin_lock(&direct_window_list_lock);
+               list_add(&window->list, &direct_window_list);
+               spin_unlock(&direct_window_list_lock);
        }
 
        return 0;
@@ -921,12 +883,6 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
        return ret;
 }
 
-static void restore_default_window(struct pci_dev *dev,
-                                       u32 ddw_restore_token)
-{
-       __restore_default_window(pci_dev_to_eeh_dev(dev), ddw_restore_token);
-}
-
 struct failed_ddw_pdn {
        struct device_node *pdn;
        struct list_head list;
@@ -954,13 +910,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        u64 dma_addr, max_addr;
        struct device_node *dn;
        const u32 *uninitialized_var(ddw_avail);
-       const u32 *uninitialized_var(ddw_extensions);
-       u32 ddw_restore_token = 0;
        struct direct_window *window;
        struct property *win64;
        struct dynamic_dma_window_prop *ddwprop;
-       const void *dma_window = NULL;
-       unsigned long liobn, offset, size;
        struct failed_ddw_pdn *fpdn;
 
        mutex_lock(&direct_window_init_mutex);
@@ -991,42 +943,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
         */
        ddw_avail = of_get_property(pdn, "ibm,ddw-applicable", &len);
        if (!ddw_avail || len < 3 * sizeof(u32))
-               goto out_unlock;
-
-       /*
-        * the extensions property is only required to exist in certain
-        * levels of firmware and later
-        * the ibm,ddw-extensions property is a list with the first
-        * element containing the number of extensions and each
-        * subsequent entry is a value corresponding to that extension
-        */
-       ddw_extensions = of_get_property(pdn, "ibm,ddw-extensions", &len);
-       if (ddw_extensions) {
-               /*
-                * each new defined extension length should be added to
-                * the top of the switch so the "earlier" entries also
-                * get picked up
-                */
-               switch (ddw_extensions[0]) {
-                       /* ibm,reset-pe-dma-windows */
-                       case 1:
-                               ddw_restore_token = ddw_extensions[1];
-                               break;
-               }
-       }
-
-       /*
-        * Only remove the existing DMA window if we can restore back to
-        * the default state. Removing the existing window maximizes the
-        * resources available to firmware for dynamic window creation.
-        */
-       if (ddw_restore_token) {
-               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
-               of_parse_dma_window(pdn, dma_window, &liobn, &offset, &size);
-               __remove_ddw(pdn, ddw_avail, liobn);
-       }
+               goto out_failed;
 
-       /*
+       /*
         * Query if there is a second window of size to map the
         * whole partition.  Query returns number of windows, largest
         * block assigned to PE (partition endpoint), and two bitmasks
@@ -1035,7 +954,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        dn = pci_device_to_OF_node(dev);
        ret = query_ddw(dev, ddw_avail, &query);
        if (ret != 0)
-               goto out_restore_window;
+               goto out_failed;
 
        if (query.windows_available == 0) {
                /*
@@ -1044,7 +963,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
                 * trading in for a larger page size.
                 */
                dev_dbg(&dev->dev, "no free dynamic windows");
-               goto out_restore_window;
+               goto out_failed;
        }
        if (be32_to_cpu(query.page_size) & 4) {
                page_shift = 24; /* 16MB */
@@ -1055,7 +974,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        } else {
                dev_dbg(&dev->dev, "no supported direct page size in mask %x",
                          query.page_size);
-               goto out_restore_window;
+               goto out_failed;
        }
        /* verify the window * number of ptes will map the partition */
        /* check largest block * page size > max memory hotplug addr */
@@ -1064,14 +983,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
                dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
                          "%llu-sized pages\n", max_addr,  query.largest_available_block,
                          1ULL << page_shift);
-               goto out_restore_window;
+               goto out_failed;
        }
        len = order_base_2(max_addr);
        win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
        if (!win64) {
                dev_info(&dev->dev,
                        "couldn't allocate property for 64bit dma window\n");
-               goto out_restore_window;
+               goto out_failed;
        }
        win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
        win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
@@ -1133,9 +1052,7 @@ out_free_prop:
        kfree(win64->value);
        kfree(win64);
 
-out_restore_window:
-       if (ddw_restore_token)
-               restore_default_window(dev, ddw_restore_token);
+out_failed:
 
        fpdn = kzalloc(sizeof(*fpdn), GFP_KERNEL);
        if (!fpdn)
@@ -1193,7 +1110,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
                pr_debug("  found DMA window, table: %p\n", pci->iommu_table);
        }
 
-       set_iommu_table_base(&dev->dev, pci->iommu_table);
+       set_iommu_table_base_and_group(&dev->dev, pci->iommu_table);
 }
 
 static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
index 4fca3def9db951896864d0b716d7dea8a2364ba2..b02af9ef3ff61ab45fb2ae86f2b49cdc6b5cc7ff 100644 (file)
@@ -92,7 +92,7 @@ void vpa_init(int cpu)
         * PAPR says this feature is SLB-Buffer but firmware never
         * reports that.  All SPLPAR support SLB shadow buffer.
         */
-       addr = __pa(&slb_shadow[cpu]);
+       addr = __pa(paca[cpu].slb_shadow_ptr);
        if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
                ret = register_slb_shadow(hwcpu, addr);
                if (ret)
@@ -153,7 +153,8 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 
        /* Make pHyp happy */
        if ((rflags & _PAGE_NO_CACHE) && !(rflags & _PAGE_WRITETHRU))
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
+
        if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
                flags |= H_COALESCE_CAND;
 
index 94134a5aecaac80ce2869826ce11c7ccd1703578..002d5b4112f25b4ac352ad7bab3ab7abfde8b1bf 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/reg.h>
 #include <asm/machdep.h>
 #include <asm/firmware.h>
-#include <asm/runlatch.h>
 #include <asm/plpar_wrappers.h>
 
 struct cpuidle_driver pseries_idle_driver = {
@@ -62,7 +61,6 @@ static int snooze_loop(struct cpuidle_device *dev,
        set_thread_flag(TIF_POLLING_NRFLAG);
 
        while ((!need_resched()) && cpu_online(cpu)) {
-               ppc64_runlatch_off();
                HMT_low();
                HMT_very_low();
        }
@@ -102,7 +100,6 @@ static int dedicated_cede_loop(struct cpuidle_device *dev,
        idle_loop_prolog(&in_purr);
        get_lppaca()->donate_dedicated_cpu = 1;
 
-       ppc64_runlatch_off();
        HMT_medium();
        check_and_cede_processor();
 
index 6f76ae417f47e561bbf7e8b01c588a8e73f6374d..8e639d7cbda72e057ab535083e29ef03f8d7f369 100644 (file)
@@ -72,7 +72,7 @@
 
 int CMO_PrPSP = -1;
 int CMO_SecPSP = -1;
-unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT);
+unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);
 EXPORT_SYMBOL(CMO_PageSize);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
@@ -569,7 +569,7 @@ void pSeries_cmo_feature_init(void)
 {
        char *ptr, *key, *value, *end;
        int call_status;
-       int page_order = IOMMU_PAGE_SHIFT;
+       int page_order = IOMMU_PAGE_SHIFT_4K;
 
        pr_debug(" -> fw_cmo_feature_init()\n");
        spin_lock(&rtas_data_buf_lock);
index 62cb527493e774969ec4dbf709e28f2bb41bf144..9a15e5b39bb8516c39f9da9e678534a8167f74ac 100644 (file)
@@ -260,7 +260,7 @@ static int tce_build_wsp(struct iommu_table *tbl, long index, long npages,
                *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
                dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n",
-                         tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT);
+                         tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT_4K);
 
                uaddr += TCE_PAGE_SIZE;
                index++;
@@ -381,8 +381,9 @@ static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb,
 
        /* Init bits and pieces */
        tbl->table.it_blocksize = 16;
-       tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT;
-       tbl->table.it_size = size >> IOMMU_PAGE_SHIFT;
+       tbl->table.it_page_shift = IOMMU_PAGE_SHIFT_4K;
+       tbl->table.it_offset = addr >> tbl->table.it_page_shift;
+       tbl->table.it_size = size >> tbl->table.it_page_shift;
 
        /*
         * It's already blank but we clear it anyway.
@@ -449,8 +450,8 @@ static void wsp_pci_dma_dev_setup(struct pci_dev *pdev)
        if (table) {
                pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n",
                        pci_name(pdev),
-                       table->table.it_offset << IOMMU_PAGE_SHIFT,
-                       (table->table.it_offset << IOMMU_PAGE_SHIFT)
+                       table->table.it_offset << IOMMU_PAGE_SHIFT_4K,
+                       (table->table.it_offset << IOMMU_PAGE_SHIFT_4K)
                        + phb->dma32_region_size - 1);
                archdata->dma_data.iommu_table_base = &table->table;
                return;
index 13ec968be4c7a25ca79fc480a7aab26e514b3bb8..7baa70d6dc016c85b8e4874f7618dbf9145d30ac 100644 (file)
@@ -19,7 +19,7 @@ config PPC_MSI_BITMAP
        default y if MPIC
        default y if FSL_PCI
        default y if PPC4xx_MSI
-       default y if POWERNV_MSI
+       default y if PPC_POWERNV
 
 source "arch/powerpc/sysdev/xics/Kconfig"
 
index 10386b676d8758b7f52bb8348f7cf321cc8db89a..a11bd1d433adf7e749ad7e3008f7327bdff29110 100644 (file)
@@ -27,7 +27,6 @@
  */
 
 #include <linux/stddef.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/irq.h>
index d7fc7223914487bdcabac51a6beba8fa68036474..fbc885b3194690fd8762f1f8b03e78e5bc712c93 100644 (file)
@@ -19,7 +19,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
index 6bc5a546d49fad87ccde51786371a8d5ca9dbf63..d631022ffb4b3c77a4fe057c3c6da91457a20c64 100644 (file)
@@ -214,10 +214,14 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
        struct fsl_lbc_ctrl *ctrl = data;
        struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
        u32 status;
+       unsigned long flags;
 
+       spin_lock_irqsave(&fsl_lbc_lock, flags);
        status = in_be32(&lbc->ltesr);
-       if (!status)
+       if (!status) {
+               spin_unlock_irqrestore(&fsl_lbc_lock, flags);
                return IRQ_NONE;
+       }
 
        out_be32(&lbc->ltesr, LTESR_CLEAR);
        out_be32(&lbc->lteatr, 0);
@@ -260,6 +264,7 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
        if (status & ~LTESR_MASK)
                dev_err(ctrl->dev, "Unknown error: "
                        "LTESR 0x%08X\n", status);
+       spin_unlock_irqrestore(&fsl_lbc_lock, flags);
        return IRQ_HANDLED;
 }
 
@@ -298,8 +303,8 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
                goto err;
        }
 
-       fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
-       if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+       fsl_lbc_ctrl_dev->irq[0] = irq_of_parse_and_map(dev->dev.of_node, 0);
+       if (!fsl_lbc_ctrl_dev->irq[0]) {
                dev_err(&dev->dev, "failed to get irq resource\n");
                ret = -ENODEV;
                goto err;
@@ -311,20 +316,34 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
        if (ret < 0)
                goto err;
 
-       ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+       ret = request_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_irq, 0,
                                "fsl-lbc", fsl_lbc_ctrl_dev);
        if (ret != 0) {
                dev_err(&dev->dev, "failed to install irq (%d)\n",
-                       fsl_lbc_ctrl_dev->irq);
-               ret = fsl_lbc_ctrl_dev->irq;
+                       fsl_lbc_ctrl_dev->irq[0]);
+               ret = fsl_lbc_ctrl_dev->irq[0];
                goto err;
        }
 
+       fsl_lbc_ctrl_dev->irq[1] = irq_of_parse_and_map(dev->dev.of_node, 1);
+       if (fsl_lbc_ctrl_dev->irq[1]) {
+               ret = request_irq(fsl_lbc_ctrl_dev->irq[1], fsl_lbc_ctrl_irq,
+                               IRQF_SHARED, "fsl-lbc-err", fsl_lbc_ctrl_dev);
+               if (ret) {
+                       dev_err(&dev->dev, "failed to install irq (%d)\n",
+                                       fsl_lbc_ctrl_dev->irq[1]);
+                       ret = fsl_lbc_ctrl_dev->irq[1];
+                       goto err1;
+               }
+       }
+
        /* Enable interrupts for any detected events */
        out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE);
 
        return 0;
 
+err1:
+       free_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_dev);
 err:
        iounmap(fsl_lbc_ctrl_dev->regs);
        kfree(fsl_lbc_ctrl_dev);
index 4dfd61df8aba99a01fb0d3d141d1544aeea3b341..a625dcf26b2b7c53374883980d9f45e1881098ff 100644 (file)
@@ -122,7 +122,7 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
         * address width of the SoC such that we can address any internal
         * SoC address from across PCI if needed
         */
-       if ((dev->bus == &pci_bus_type) &&
+       if ((dev_is_pci(dev)) &&
            dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
                set_dma_ops(dev, &dma_direct_ops);
                set_dma_offset(dev, pci64_dma_offset);
@@ -454,7 +454,7 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
-int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
+int fsl_add_bridge(struct platform_device *pdev, int is_primary)
 {
        int len;
        struct pci_controller *hose;
@@ -1035,6 +1035,7 @@ static const struct of_device_id pci_ids[] = {
        { .compatible = "fsl,mpc8548-pcie", },
        { .compatible = "fsl,mpc8610-pci", },
        { .compatible = "fsl,mpc8641-pcie", },
+       { .compatible = "fsl,qoriq-pcie", },
        { .compatible = "fsl,qoriq-pcie-v2.1", },
        { .compatible = "fsl,qoriq-pcie-v2.2", },
        { .compatible = "fsl,qoriq-pcie-v2.3", },
index 6149916da3f48c50c0e42c73e5dd7a1099fd0568..908dbd9826b6e15bf0fa8e916116ea0c568a44c7 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __GEF_PIC_H__
 #define __GEF_PIC_H__
 
-#include <linux/init.h>
 
 void gef_pic_cascade(unsigned int, struct irq_desc *);
 unsigned int gef_pic_get_irq(void);
index 997df6a7ab5d19fd1aeac65d020f51d2d17ba482..45598da0b3214221feb8b8d66200fe8146b3ef2f 100644 (file)
@@ -8,7 +8,6 @@
  */
 #undef DEBUG
 
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
index c6c8b526a4f6e5e68b569dd6451ad339d39cb78c..1f6c570d66d45ee88e1114b790d600f06c0bc4ec 100644 (file)
@@ -152,10 +152,8 @@ static struct pci_ops indirect_pci_ops =
        .write = indirect_write_config,
 };
 
-void __init
-setup_indirect_pci(struct pci_controller* hose,
-                  resource_size_t cfg_addr,
-                  resource_size_t cfg_data, u32 flags)
+void setup_indirect_pci(struct pci_controller *hose, resource_size_t cfg_addr,
+                       resource_size_t cfg_data, u32 flags)
 {
        resource_size_t base = cfg_addr & PAGE_MASK;
        void __iomem *mbase;
index b724622c3a0b74ab5eddfa3b0cfc10dc6eab2c34..c4828c0be5bd861e734577dc982071a305e8fbea 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/irq.h>
index 22d7d57eead9d88fca57629de658a5629fd2d6bf..9d9b06217f8b9dff2a994ad5d357436e9986553e 100644 (file)
@@ -41,6 +41,7 @@
 #define MPIC_TIMER_TCR_ROVR_OFFSET     24
 
 #define TIMER_STOP                     0x80000000
+#define GTCCR_TOG                      0x80000000
 #define TIMERS_PER_GROUP               4
 #define MAX_TICKS                      (~0U >> 1)
 #define MAX_TICKS_CASCADE              (~0U)
@@ -96,8 +97,11 @@ static void convert_ticks_to_time(struct timer_group_priv *priv,
        time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq);
        tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
 
-       time->tv_usec = (__kernel_suseconds_t)
-               div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+       time->tv_usec = 0;
+
+       if (tmp_sec <= ticks)
+               time->tv_usec = (__kernel_suseconds_t)
+                       div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
 
        return;
 }
@@ -327,11 +331,13 @@ void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time)
        casc_priv = priv->timer[handle->num].cascade_handle;
        if (casc_priv) {
                tmp_ticks = in_be32(&priv->regs[handle->num].gtccr);
+               tmp_ticks &= ~GTCCR_TOG;
                ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
                tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr);
                ticks += tmp_ticks;
        } else {
                ticks = in_be32(&priv->regs[handle->num].gtccr);
+               ticks &= ~GTCCR_TOG;
        }
 
        convert_ticks_to_time(priv, ticks, time);
index a88807b3dd578b7b4e2ed423d5305ef41dad00e3..d09994164dafd315027bd381209128e76fc79e15 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
index 134b07d2943564ee3e7244fee932366680c744d2..621575b7e84aa3b2c5932b1768f909b56d593587 100644 (file)
@@ -14,7 +14,6 @@
  * option) any later version.
  */
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
index cceb2e366738f90b7b9570c9dab1b1a14c37830d..65aaf15032aee221f313e844248749cb8029baee 100644 (file)
@@ -13,7 +13,6 @@
  * option) any later version.
  */
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
index 1c062f48f1ac8711e8975b3cf601cb595ce494fd..befaf1123f7f0c72e3c45bbf3807ec3fd0362e27 100644 (file)
@@ -13,7 +13,6 @@
  * option) any later version.
  */
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
index ce5a7b489e4b4282b7b0ac4d5f75ffd66c00ff36..9998c0de12d056739cf891e318ddb08b0f7cfc27 100644 (file)
@@ -18,7 +18,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <linux/init.h>
 #include <linux/kernel.h>
 #include <asm/barrier.h>
 #include <asm/page.h>
index df0fc58214697623b429f55555d494e8ccf56c52..c1917cf67c3ded26aee9e48b50340ff51d5048ac 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/of.h>
 
index af9d3469fb9933e4f3d424f01e3230ddeb580c67..a90731b3d44a3ea41052690975aefcd8b3ce2db7 100644 (file)
@@ -2051,6 +2051,10 @@ static void dump_one_paca(int cpu)
        DUMP(p, stab_addr, "lx");
 #endif
        DUMP(p, emergency_sp, "p");
+#ifdef CONFIG_PPC_BOOK3S_64
+       DUMP(p, mc_emergency_sp, "p");
+       DUMP(p, in_mce, "x");
+#endif
        DUMP(p, data_offset, "lx");
        DUMP(p, hw_cpu_id, "x");
        DUMP(p, cpu_start, "x");
index 4f858f77d870d842fa99fdc26e00b13521ae35e3..65a07750f4f946f038bb2e2a4e13f9f6d05dce83 100644 (file)
@@ -596,7 +596,7 @@ config CRASH_DUMP
 config ZFCPDUMP
        def_bool n
        prompt "zfcpdump support"
-       depends on SMP
+       depends on 64BIT && SMP
        help
          Select this option if you want to build an zfcpdump enabled kernel.
          Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
index 2e671d5004ca56651a0f246d91a5a65b81889603..06f8d95a16cdc9767d4538ea1798c32bfac73187 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
 
-s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o
+s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o hypfs_sprp.o
index 79f2ac55253f9289c3864f2ee7b286d67aca58bd..b34b5ab90a313b77bd0561503d882af311a50c7d 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/debugfs.h>
 #include <linux/workqueue.h>
 #include <linux/kref.h>
+#include <asm/hypfs.h>
 
 #define REG_FILE_MODE    0440
 #define UPDATE_FILE_MODE 0220
@@ -36,6 +37,10 @@ extern int hypfs_vm_init(void);
 extern void hypfs_vm_exit(void);
 extern int hypfs_vm_create_files(struct dentry *root);
 
+/* Set Partition-Resource Parameter */
+int hypfs_sprp_init(void);
+void hypfs_sprp_exit(void);
+
 /* debugfs interface */
 struct hypfs_dbfs_file;
 
@@ -52,6 +57,8 @@ struct hypfs_dbfs_file {
        int             (*data_create)(void **data, void **data_free_ptr,
                                       size_t *size);
        void            (*data_free)(const void *buf_free_ptr);
+       long            (*unlocked_ioctl) (struct file *, unsigned int,
+                                          unsigned long);
 
        /* Private data for hypfs_dbfs.c */
        struct hypfs_dbfs_data  *data;
index 17ab8b7b53cc58074fce7c214caa1e543164d991..2badf2bf9cd74217806129bb5a578ac1fd8e1131 100644 (file)
@@ -81,9 +81,25 @@ static ssize_t dbfs_read(struct file *file, char __user *buf,
        return rc;
 }
 
+static long dbfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct hypfs_dbfs_file *df;
+       long rc;
+
+       df = file->f_path.dentry->d_inode->i_private;
+       mutex_lock(&df->lock);
+       if (df->unlocked_ioctl)
+               rc = df->unlocked_ioctl(file, cmd, arg);
+       else
+               rc = -ENOTTY;
+       mutex_unlock(&df->lock);
+       return rc;
+}
+
 static const struct file_operations dbfs_ops = {
        .read           = dbfs_read,
        .llseek         = no_llseek,
+       .unlocked_ioctl = dbfs_ioctl,
 };
 
 int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
diff --git a/arch/s390/hypfs/hypfs_sprp.c b/arch/s390/hypfs/hypfs_sprp.c
new file mode 100644 (file)
index 0000000..f043c3c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *    Hypervisor filesystem for Linux on s390.
+ *    Set Partition-Resource Parameter interface.
+ *
+ *    Copyright IBM Corp. 2013
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <asm/compat.h>
+#include <asm/sclp.h>
+#include "hypfs.h"
+
+#define DIAG304_SET_WEIGHTS    0
+#define DIAG304_QUERY_PRP      1
+#define DIAG304_SET_CAPPING    2
+
+#define DIAG304_CMD_MAX                2
+
+static unsigned long hypfs_sprp_diag304(void *data, unsigned long cmd)
+{
+       register unsigned long _data asm("2") = (unsigned long) data;
+       register unsigned long _rc asm("3");
+       register unsigned long _cmd asm("4") = cmd;
+
+       asm volatile("diag %1,%2,0x304\n"
+                    : "=d" (_rc) : "d" (_data), "d" (_cmd) : "memory");
+
+       return _rc;
+}
+
+static void hypfs_sprp_free(const void *data)
+{
+       free_page((unsigned long) data);
+}
+
+static int hypfs_sprp_create(void **data_ptr, void **free_ptr, size_t *size)
+{
+       unsigned long rc;
+       void *data;
+
+       data = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       rc = hypfs_sprp_diag304(data, DIAG304_QUERY_PRP);
+       if (rc != 1) {
+               *data_ptr = *free_ptr = NULL;
+               *size = 0;
+               free_page((unsigned long) data);
+               return -EIO;
+       }
+       *data_ptr = *free_ptr = data;
+       *size = PAGE_SIZE;
+       return 0;
+}
+
+static int __hypfs_sprp_ioctl(void __user *user_area)
+{
+       struct hypfs_diag304 diag304;
+       unsigned long cmd;
+       void __user *udata;
+       void *data;
+       int rc;
+
+       if (copy_from_user(&diag304, user_area, sizeof(diag304)))
+               return -EFAULT;
+       if ((diag304.args[0] >> 8) != 0 || diag304.args[1] > DIAG304_CMD_MAX)
+               return -EINVAL;
+
+       data = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!data)
+               return -ENOMEM;
+
+       udata = (void __user *)(unsigned long) diag304.data;
+       if (diag304.args[1] == DIAG304_SET_WEIGHTS ||
+           diag304.args[1] == DIAG304_SET_CAPPING)
+               if (copy_from_user(data, udata, PAGE_SIZE)) {
+                       rc = -EFAULT;
+                       goto out;
+               }
+
+       cmd = *(unsigned long *) &diag304.args[0];
+       diag304.rc = hypfs_sprp_diag304(data, cmd);
+
+       if (diag304.args[1] == DIAG304_QUERY_PRP)
+               if (copy_to_user(udata, data, PAGE_SIZE)) {
+                       rc = -EFAULT;
+                       goto out;
+               }
+
+       rc = copy_to_user(user_area, &diag304, sizeof(diag304)) ? -EFAULT : 0;
+out:
+       free_page((unsigned long) data);
+       return rc;
+}
+
+static long hypfs_sprp_ioctl(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       void __user *argp;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+       if (is_compat_task())
+               argp = compat_ptr(arg);
+       else
+               argp = (void __user *) arg;
+       switch (cmd) {
+       case HYPFS_DIAG304:
+               return __hypfs_sprp_ioctl(argp);
+       default: /* unknown ioctl number */
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static struct hypfs_dbfs_file hypfs_sprp_file = {
+       .name           = "diag_304",
+       .data_create    = hypfs_sprp_create,
+       .data_free      = hypfs_sprp_free,
+       .unlocked_ioctl = hypfs_sprp_ioctl,
+};
+
+int hypfs_sprp_init(void)
+{
+       if (!sclp_has_sprp())
+               return 0;
+       return hypfs_dbfs_create_file(&hypfs_sprp_file);
+}
+
+void hypfs_sprp_exit(void)
+{
+       if (!sclp_has_sprp())
+               return;
+       hypfs_dbfs_remove_file(&hypfs_sprp_file);
+}
index ddfe09b4513492cd2700d691e61d70ad38f8379b..c952b981e4f28885223c7f77b51ada2299f03c6a 100644 (file)
@@ -478,10 +478,14 @@ static int __init hypfs_init(void)
                rc = -ENODATA;
                goto fail_hypfs_diag_exit;
        }
+       if (hypfs_sprp_init()) {
+               rc = -ENODATA;
+               goto fail_hypfs_vm_exit;
+       }
        s390_kobj = kobject_create_and_add("s390", hypervisor_kobj);
        if (!s390_kobj) {
                rc = -ENOMEM;
-               goto fail_hypfs_vm_exit;
+               goto fail_hypfs_sprp_exit;
        }
        rc = register_filesystem(&hypfs_type);
        if (rc)
@@ -490,6 +494,8 @@ static int __init hypfs_init(void)
 
 fail_filesystem:
        kobject_put(s390_kobj);
+fail_hypfs_sprp_exit:
+       hypfs_sprp_exit();
 fail_hypfs_vm_exit:
        hypfs_vm_exit();
 fail_hypfs_diag_exit:
@@ -502,11 +508,12 @@ fail_dbfs_exit:
 
 static void __exit hypfs_exit(void)
 {
-       hypfs_diag_exit();
-       hypfs_vm_exit();
-       hypfs_dbfs_exit();
        unregister_filesystem(&hypfs_type);
        kobject_put(s390_kobj);
+       hypfs_sprp_exit();
+       hypfs_vm_exit();
+       hypfs_diag_exit();
+       hypfs_dbfs_exit();
 }
 
 module_init(hypfs_init)
index 0f636cbdf3420973f169a591d03614b5f173ca11..4236408070e5f7cb163e1be623627ffc398e677f 100644 (file)
@@ -185,11 +185,12 @@ static inline unsigned long long __cmpxchg64(void *ptr,
 {
        register_pair rp_old = {.pair = old};
        register_pair rp_new = {.pair = new};
+       unsigned long long *ullptr = ptr;
 
        asm volatile(
                "       cds     %0,%2,%1"
-               : "+&d" (rp_old), "=Q" (ptr)
-               : "d" (rp_new), "Q" (ptr)
+               : "+d" (rp_old), "+Q" (*ullptr)
+               : "d" (rp_new)
                : "memory", "cc");
        return rp_old.pair;
 }
index 220e171413f857210012d7a09f07dfb904c21a10..abaca2275c7a5acb3f0f730539e4d8d5fd6cd19f 100644 (file)
@@ -54,6 +54,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
 bool __init sclp_has_linemode(void);
 bool __init sclp_has_vt220(void);
+bool sclp_has_sprp(void);
 int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
 int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
diff --git a/arch/s390/include/uapi/asm/hypfs.h b/arch/s390/include/uapi/asm/hypfs.h
new file mode 100644 (file)
index 0000000..37998b4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * IOCTL interface for hypfs
+ *
+ * Copyright IBM Corp. 2013
+ *
+ * Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _ASM_HYPFS_CTL_H
+#define _ASM_HYPFS_CTL_H
+
+#include <linux/types.h>
+
+struct hypfs_diag304 {
+       __u32   args[2];
+       __u64   data;
+       __u64   rc;
+} __attribute__((packed));
+
+#define HYPFS_IOCTL_MAGIC 0x10
+
+#define HYPFS_DIAG304 \
+       _IOWR(HYPFS_IOCTL_MAGIC, 0x20, struct hypfs_diag304)
+
+#endif
index a61d538756f29c9ec6f932aec471c2f74de93e8a..471eb09184d4558ae59963adac953443bc055fbe 100644 (file)
@@ -35,11 +35,11 @@ struct statfs {
 struct statfs64 {
        unsigned int    f_type;
        unsigned int    f_bsize;
-       unsigned long   f_blocks;
-       unsigned long   f_bfree;
-       unsigned long   f_bavail;
-       unsigned long   f_files;
-       unsigned long   f_ffree;
+       unsigned long long f_blocks;
+       unsigned long long f_bfree;
+       unsigned long long f_bavail;
+       unsigned long long f_files;
+       unsigned long long f_ffree;
        __kernel_fsid_t f_fsid;
        unsigned int    f_namelen;
        unsigned int    f_frsize;
index 864f693c237fe440cd02125e588c4b5867b6edb8..5eb5c9ddb120027df003990329a0b7ede4cbfa59 100644 (file)
 #define __NR_s390_runtime_instr 342
 #define __NR_kcmp              343
 #define __NR_finit_module      344
+#define __NR_sched_setattr     345
+#define __NR_sched_getattr     346
 #define NR_syscalls 345
 
 /* 
index e030d2bdec1b6aa2b9f29288b28c6600710ecfd1..db02052bd137254c1c6d46314005ed4fce1a6204 100644 (file)
@@ -286,8 +286,8 @@ asmlinkage long sys32_getegid16(void)
 }
 
 #ifdef CONFIG_SYSVIPC
-COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
-               unsigned long, third, compat_uptr_t, ptr)
+COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
+               compat_ulong_t, third, compat_uptr_t, ptr)
 {
        if (call >> 16)         /* hack for backward compatibility */
                return -EINVAL;
index 9cb1b975b3532f3cc6237ab1cd168146f99a9904..59c8efce1b99b52964950f0933b4934a12b6a9db 100644 (file)
@@ -1412,3 +1412,14 @@ ENTRY(sys_finit_module_wrapper)
        llgtr   %r3,%r3                 # const char __user *
        lgfr    %r4,%r4                 # int
        jg      sys_finit_module
+
+ENTRY(sys_sched_setattr_wrapper)
+       lgfr    %r2,%r2                 # pid_t
+       llgtr   %r3,%r3                 # struct sched_attr __user *
+       jg      sys_sched_setattr
+
+ENTRY(sys_sched_getattr_wrapper)
+       lgfr    %r2,%r2                 # pid_t
+       llgtr   %r3,%r3                 # const char __user *
+       llgfr   %r3,%r3                 # unsigned int
+       jg      sys_sched_getattr
index 913410bd74a335c0693637ccb69e49cb89fd63c1..143992152ec95d7c2b96c1978d1bae78da480efb 100644 (file)
@@ -353,3 +353,5 @@ SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev
 SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
 SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
 SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
+SYSCALL(sys_sched_setattr,sys_sched_setattr,sys_sched_setattr_wrapper) /* 345 */
+SYSCALL(sys_sched_getattr,sys_sched_getattr,sys_sched_getattr_wrapper)
index 315dbe09983e518b06326b2f730c45a176a57aa5..b1a22173d027b9bde6774194631d635932bc42ff 100644 (file)
@@ -6,15 +6,6 @@
 #ifndef __ARCH_S390_LIB_UACCESS_H
 #define __ARCH_S390_LIB_UACCESS_H
 
-extern size_t copy_from_user_std(size_t, const void __user *, void *);
-extern size_t copy_to_user_std(size_t, void __user *, const void *);
-extern size_t strnlen_user_std(size_t, const char __user *);
-extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
-extern int futex_atomic_op_std(int, u32 __user *, int, int *);
-
-extern size_t copy_from_user_pt(size_t, const void __user *, void *);
-extern size_t copy_to_user_pt(size_t, void __user *, const void *);
 extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
 extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
index 0632dc50da78b88557ca61c766b29bccbb30a64d..61ebcc9ccb3472abe320fd8ed4939b4cc5074ebe 100644 (file)
@@ -153,6 +153,8 @@ static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
        unsigned long offset, done, size, kaddr;
        void *from, *to;
 
+       if (!mm)
+               return n;
        done = 0;
 retry:
        spin_lock(&mm->page_table_lock);
@@ -209,7 +211,7 @@ fault:
        return 0;
 }
 
-size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
+static size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
 {
        size_t rc;
 
@@ -221,7 +223,7 @@ size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
        return rc;
 }
 
-size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
+static size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
 {
        if (segment_eq(get_fs(), KERNEL_DS))
                return copy_in_kernel(n, to, (void __user *) from);
@@ -262,6 +264,8 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
                return 0;
        if (segment_eq(get_fs(), KERNEL_DS))
                return strnlen_kernel(count, src);
+       if (!mm)
+               return 0;
        done = 0;
 retry:
        spin_lock(&mm->page_table_lock);
@@ -323,6 +327,8 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
 
        if (segment_eq(get_fs(), KERNEL_DS))
                return copy_in_kernel(n, to, from);
+       if (!mm)
+               return n;
        done = 0;
 retry:
        spin_lock(&mm->page_table_lock);
@@ -411,6 +417,8 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 
        if (segment_eq(get_fs(), KERNEL_DS))
                return __futex_atomic_op_pt(op, uaddr, oparg, old);
+       if (unlikely(!current->mm))
+               return -EFAULT;
        spin_lock(&current->mm->page_table_lock);
        uaddr = (u32 __force __user *)
                __dat_user_addr((__force unsigned long) uaddr, 1);
@@ -448,6 +456,8 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
 
        if (segment_eq(get_fs(), KERNEL_DS))
                return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
+       if (unlikely(!current->mm))
+               return -EFAULT;
        spin_lock(&current->mm->page_table_lock);
        uaddr = (u32 __force __user *)
                __dat_user_addr((__force unsigned long) uaddr, 1);
index 62ced589bcf78f1554bcadd4f420fad19c7ebcc1..b73274fb961a27a9b54eb5fd1719650762fef305 100644 (file)
 #define __NR_kern_features     340
 #define __NR_kcmp              341
 #define __NR_finit_module      342
+#define __NR_sched_setattr     343
+#define __NR_sched_getattr     344
 
-#define NR_syscalls            343
+#define NR_syscalls            345
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index cb5d272d658acce52fc85a77b1e730a40c5d885a..de1c844dfabc02569cfe71c91b3e52a9ea705ef4 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <asm/cpudata.h>
index e306fb08ee5e1fab217823321460d94deac5cb75..acf8314cec489d1beec128ce5d3d422f53554231 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 
index 4eb1a5a1d5440642aefbef171c527767cc722063..b7ddcdd1dea943a9f5e768c006547a3e7737d4f7 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
  */
 
-#include <linux/init.h>
 
 #include <asm/thread_info.h>
 #include <asm/hypervisor.h>
index de199bf0cb051c6e695296d8b8ab392efd00c7c6..3241f56331c2aced51e918aa9dde9ef936e54e7c 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
-#include <linux/init.h>
 #include <linux/export.h>
 #include <linux/mod_devicetable.h>
 #include <linux/errno.h>
index 7de8d1f590b7fbb7023c6d455b2a079714051bc7..1555bbcae1eee617fecd7cbecaa78eb5d6ab2ca8 100644 (file)
@@ -1005,6 +1005,5 @@ static int __init of_pci_slot_init(void)
 
        return 0;
 }
-
-module_init(of_pci_slot_init);
+device_initcall(of_pci_slot_init);
 #endif
index a6895987fb70254b7db258c2eff6fd65262aba46..944a06536ecc129ab81c9e758a6f89b92d3091fe 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/device.h>
 #include <linux/of_device.h>
index fdd819dfdacf2057474d6e09f590d7617eaf9cb2..510baec1b69b2ca79d3f9e8687520e1b0b541b91 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
-#include <linux/init.h>
 #include <linux/slab.h>
 
 #include <asm/auxio.h>
index e521c54560f9dffa74e1057dc9480ead73aea2df..bf4ccb10a78c600ac48cba552cb1794836b094bf 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
index 9f5e24ddcc70b0b10240f2a476b34610e011023b..a92d5d2c46a3a6553bf13a57f95f65c6d61c334c 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/export.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include <linux/bitops.h>
 
 #include <asm/cpudata.h>
index 7b87171ecf1e91803ce0a3908c629118d205c020..151ace8766cc2d99d5be3552a4b2014eb74fdaa6 100644 (file)
@@ -85,4 +85,4 @@ sys_call_table:
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
-/*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module
+/*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
index 6d81597064b6b5c7efa0861fc6c5c230e3c4984f..4bd4e2bb26cf4d35a8980f1a9040cdd88a645a4a 100644 (file)
@@ -86,7 +86,7 @@ sys_call_table32:
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/        .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
-/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module
+/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
 
 #endif /* CONFIG_COMPAT */
 
@@ -164,4 +164,4 @@ sys_call_table:
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
-/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module
+/*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
index 76dcbd3c988aed9445de17442e8cb1076ef5cc49..3eed99fc69892f40c34e2865895928c35b78067f 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <linux/init.h>
 #include <asm/head.h>
 #include <asm/psr.h>
 #include <asm/page.h>
index ad4bde3bb61e6763df6baf6c44b9b0f7be921f7b..737f8cbc7d56cda4e4afbdb1c7166c4fcaad3ece 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/init.h>
 
 #include <asm/head.h>
 #include <asm/asi.h>
index 30963178d7e940f4afe02ed86bc936020dd1ec8a..9bd9ce80bf77eb46605942278dd4c1fe72fa4da0 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 2002, 2003, 2006 David S. Miller (davem@davemloft.net)
  */
 
-#include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
index ad3bf4b4324d94f10504947bd88b2dea93a44b2e..b12cb5e72812140688d771ed0788b6a2cf2cfc16 100644 (file)
@@ -4,7 +4,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
index 04a4540509dd87d5c533938810eaebeb55a21edf..e58b817263199f9d45d28aed5f735b38eb94904b 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/string.h>
index 9be0d5d02a9a7681ab00cd21aa2272449336d8fa..f2f6323c8d64e4bdec2b9864a152244e5b33a8d3 100644 (file)
@@ -35,17 +35,11 @@ static struct console early_ocd_console = {
 
 static int __init setup_early_printk(char *buf)
 {
-       int keep_early;
-
        if (!buf || early_console)
                return 0;
 
-       if (strstr(buf, "keep"))
-               keep_early = 1;
-
        early_console = &early_ocd_console;
-
-       if (keep_early)
+       if (strstr(buf, "keep"))
                early_console->flags &= ~CON_BOOT;
        else
                early_console->flags |= CON_BOOT;
index 2f59cce3b38aaabb83efe9c528ffbfc7ea9ae8d8..f97fbe3abb67f5059d4e6f0a37261d6113df19de 100644 (file)
@@ -51,9 +51,9 @@ extern int devmem_is_allowed(unsigned long pagenr);
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
-static inline phys_addr_t get_max_low_mapped(void)
+static inline phys_addr_t get_max_mapped(void)
 {
-       return (phys_addr_t)max_low_pfn_mapped << PAGE_SHIFT;
+       return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
 }
 
 bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn);
index c9675594d7caee907fd6fd78559fe14bf1aea036..06853e6703541f8349106e17330f86621fa984db 100644 (file)
@@ -1119,7 +1119,7 @@ void __init setup_arch(char **cmdline_p)
 
        setup_real_mode();
 
-       memblock_set_current_limit(get_max_low_mapped());
+       memblock_set_current_limit(get_max_mapped());
        dma_contiguous_reserve(0);
 
        /*
index cb1db2979d3d7b5417a8a4b131e09c5c5f6767c0..16cab6635163797da9414a27cb8634356d5cd999 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 
 #include "rbd_types.h"
 
@@ -89,9 +90,9 @@ static int atomic_dec_return_safe(atomic_t *v)
 }
 
 #define RBD_DRV_NAME "rbd"
-#define RBD_DRV_NAME_LONG "rbd (rados block device)"
 
-#define RBD_MINORS_PER_MAJOR   256             /* max minors per blkdev */
+#define RBD_MINORS_PER_MAJOR           256
+#define RBD_SINGLE_MAJOR_PART_SHIFT    4
 
 #define RBD_SNAP_DEV_NAME_PREFIX       "snap_"
 #define RBD_MAX_SNAP_NAME_LEN  \
@@ -323,6 +324,7 @@ struct rbd_device {
        int                     dev_id;         /* blkdev unique id */
 
        int                     major;          /* blkdev assigned major */
+       int                     minor;
        struct gendisk          *disk;          /* blkdev's gendisk and rq */
 
        u32                     image_format;   /* Either 1 or 2 */
@@ -386,6 +388,17 @@ static struct kmem_cache   *rbd_img_request_cache;
 static struct kmem_cache       *rbd_obj_request_cache;
 static struct kmem_cache       *rbd_segment_name_cache;
 
+static int rbd_major;
+static DEFINE_IDA(rbd_dev_id_ida);
+
+/*
+ * Default to false for now, as single-major requires >= 0.75 version of
+ * userspace rbd utility.
+ */
+static bool single_major = false;
+module_param(single_major, bool, S_IRUGO);
+MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (default: false)");
+
 static int rbd_img_request_submit(struct rbd_img_request *img_request);
 
 static void rbd_dev_device_release(struct device *dev);
@@ -394,18 +407,52 @@ static ssize_t rbd_add(struct bus_type *bus, const char *buf,
                       size_t count);
 static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
                          size_t count);
+static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf,
+                                   size_t count);
+static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
+                                      size_t count);
 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
 static void rbd_spec_put(struct rbd_spec *spec);
 
+static int rbd_dev_id_to_minor(int dev_id)
+{
+       return dev_id << RBD_SINGLE_MAJOR_PART_SHIFT;
+}
+
+static int minor_to_rbd_dev_id(int minor)
+{
+       return minor >> RBD_SINGLE_MAJOR_PART_SHIFT;
+}
+
 static BUS_ATTR(add, S_IWUSR, NULL, rbd_add);
 static BUS_ATTR(remove, S_IWUSR, NULL, rbd_remove);
+static BUS_ATTR(add_single_major, S_IWUSR, NULL, rbd_add_single_major);
+static BUS_ATTR(remove_single_major, S_IWUSR, NULL, rbd_remove_single_major);
 
 static struct attribute *rbd_bus_attrs[] = {
        &bus_attr_add.attr,
        &bus_attr_remove.attr,
+       &bus_attr_add_single_major.attr,
+       &bus_attr_remove_single_major.attr,
        NULL,
 };
-ATTRIBUTE_GROUPS(rbd_bus);
+
+static umode_t rbd_bus_is_visible(struct kobject *kobj,
+                                 struct attribute *attr, int index)
+{
+       if (!single_major &&
+           (attr == &bus_attr_add_single_major.attr ||
+            attr == &bus_attr_remove_single_major.attr))
+               return 0;
+
+       return attr->mode;
+}
+
+static const struct attribute_group rbd_bus_group = {
+       .attrs = rbd_bus_attrs,
+       .is_visible = rbd_bus_is_visible,
+};
+__ATTRIBUTE_GROUPS(rbd_bus);
 
 static struct bus_type rbd_bus_type = {
        .name           = "rbd",
@@ -1041,9 +1088,9 @@ static const char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
        name_format = "%s.%012llx";
        if (rbd_dev->image_format == 2)
                name_format = "%s.%016llx";
-       ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, name_format,
+       ret = snprintf(name, CEPH_MAX_OID_NAME_LEN + 1, name_format,
                        rbd_dev->header.object_prefix, segment);
-       if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) {
+       if (ret < 0 || ret > CEPH_MAX_OID_NAME_LEN) {
                pr_err("error formatting segment name for #%llu (%d)\n",
                        segment, ret);
                kfree(name);
@@ -1761,11 +1808,8 @@ static struct ceph_osd_request *rbd_osd_req_create(
        osd_req->r_callback = rbd_osd_req_callback;
        osd_req->r_priv = obj_request;
 
-       osd_req->r_oid_len = strlen(obj_request->object_name);
-       rbd_assert(osd_req->r_oid_len < sizeof (osd_req->r_oid));
-       memcpy(osd_req->r_oid, obj_request->object_name, osd_req->r_oid_len);
-
-       osd_req->r_file_layout = rbd_dev->layout;       /* struct */
+       osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
+       ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
 
        return osd_req;
 }
@@ -1802,11 +1846,8 @@ rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request)
        osd_req->r_callback = rbd_osd_req_callback;
        osd_req->r_priv = obj_request;
 
-       osd_req->r_oid_len = strlen(obj_request->object_name);
-       rbd_assert(osd_req->r_oid_len < sizeof (osd_req->r_oid));
-       memcpy(osd_req->r_oid, obj_request->object_name, osd_req->r_oid_len);
-
-       osd_req->r_file_layout = rbd_dev->layout;       /* struct */
+       osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
+       ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
 
        return osd_req;
 }
@@ -2866,7 +2907,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
  * Request sync osd watch/unwatch.  The value of "start" determines
  * whether a watch request is being initiated or torn down.
  */
-static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, bool start)
+static int __rbd_dev_header_watch_sync(struct rbd_device *rbd_dev, bool start)
 {
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
        struct rbd_obj_request *obj_request;
@@ -2941,6 +2982,22 @@ out_cancel:
        return ret;
 }
 
+static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
+{
+       return __rbd_dev_header_watch_sync(rbd_dev, true);
+}
+
+static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+{
+       int ret;
+
+       ret = __rbd_dev_header_watch_sync(rbd_dev, false);
+       if (ret) {
+               rbd_warn(rbd_dev, "unable to tear down watch request: %d\n",
+                        ret);
+       }
+}
+
 /*
  * Synchronous osd object method call.  Returns the number of bytes
  * returned in the outbound buffer, or a negative error code.
@@ -3388,14 +3445,18 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        u64 segment_size;
 
        /* create gendisk info */
-       disk = alloc_disk(RBD_MINORS_PER_MAJOR);
+       disk = alloc_disk(single_major ?
+                         (1 << RBD_SINGLE_MAJOR_PART_SHIFT) :
+                         RBD_MINORS_PER_MAJOR);
        if (!disk)
                return -ENOMEM;
 
        snprintf(disk->disk_name, sizeof(disk->disk_name), RBD_DRV_NAME "%d",
                 rbd_dev->dev_id);
        disk->major = rbd_dev->major;
-       disk->first_minor = 0;
+       disk->first_minor = rbd_dev->minor;
+       if (single_major)
+               disk->flags |= GENHD_FL_EXT_DEVT;
        disk->fops = &rbd_bd_ops;
        disk->private_data = rbd_dev;
 
@@ -3467,7 +3528,14 @@ static ssize_t rbd_major_show(struct device *dev,
                return sprintf(buf, "%d\n", rbd_dev->major);
 
        return sprintf(buf, "(none)\n");
+}
 
+static ssize_t rbd_minor_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+
+       return sprintf(buf, "%d\n", rbd_dev->minor);
 }
 
 static ssize_t rbd_client_id_show(struct device *dev,
@@ -3589,6 +3657,7 @@ static ssize_t rbd_image_refresh(struct device *dev,
 static DEVICE_ATTR(size, S_IRUGO, rbd_size_show, NULL);
 static DEVICE_ATTR(features, S_IRUGO, rbd_features_show, NULL);
 static DEVICE_ATTR(major, S_IRUGO, rbd_major_show, NULL);
+static DEVICE_ATTR(minor, S_IRUGO, rbd_minor_show, NULL);
 static DEVICE_ATTR(client_id, S_IRUGO, rbd_client_id_show, NULL);
 static DEVICE_ATTR(pool, S_IRUGO, rbd_pool_show, NULL);
 static DEVICE_ATTR(pool_id, S_IRUGO, rbd_pool_id_show, NULL);
@@ -3602,6 +3671,7 @@ static struct attribute *rbd_attrs[] = {
        &dev_attr_size.attr,
        &dev_attr_features.attr,
        &dev_attr_major.attr,
+       &dev_attr_minor.attr,
        &dev_attr_client_id.attr,
        &dev_attr_pool.attr,
        &dev_attr_pool_id.attr,
@@ -4372,21 +4442,29 @@ static void rbd_bus_del_dev(struct rbd_device *rbd_dev)
        device_unregister(&rbd_dev->dev);
 }
 
-static atomic64_t rbd_dev_id_max = ATOMIC64_INIT(0);
-
 /*
  * Get a unique rbd identifier for the given new rbd_dev, and add
- * the rbd_dev to the global list.  The minimum rbd id is 1.
+ * the rbd_dev to the global list.
  */
-static void rbd_dev_id_get(struct rbd_device *rbd_dev)
+static int rbd_dev_id_get(struct rbd_device *rbd_dev)
 {
-       rbd_dev->dev_id = atomic64_inc_return(&rbd_dev_id_max);
+       int new_dev_id;
+
+       new_dev_id = ida_simple_get(&rbd_dev_id_ida,
+                                   0, minor_to_rbd_dev_id(1 << MINORBITS),
+                                   GFP_KERNEL);
+       if (new_dev_id < 0)
+               return new_dev_id;
+
+       rbd_dev->dev_id = new_dev_id;
 
        spin_lock(&rbd_dev_list_lock);
        list_add_tail(&rbd_dev->node, &rbd_dev_list);
        spin_unlock(&rbd_dev_list_lock);
-       dout("rbd_dev %p given dev id %llu\n", rbd_dev,
-               (unsigned long long) rbd_dev->dev_id);
+
+       dout("rbd_dev %p given dev id %d\n", rbd_dev, rbd_dev->dev_id);
+
+       return 0;
 }
 
 /*
@@ -4395,49 +4473,13 @@ static void rbd_dev_id_get(struct rbd_device *rbd_dev)
  */
 static void rbd_dev_id_put(struct rbd_device *rbd_dev)
 {
-       struct list_head *tmp;
-       int rbd_id = rbd_dev->dev_id;
-       int max_id;
-
-       rbd_assert(rbd_id > 0);
-
-       dout("rbd_dev %p released dev id %llu\n", rbd_dev,
-               (unsigned long long) rbd_dev->dev_id);
        spin_lock(&rbd_dev_list_lock);
        list_del_init(&rbd_dev->node);
-
-       /*
-        * If the id being "put" is not the current maximum, there
-        * is nothing special we need to do.
-        */
-       if (rbd_id != atomic64_read(&rbd_dev_id_max)) {
-               spin_unlock(&rbd_dev_list_lock);
-               return;
-       }
-
-       /*
-        * We need to update the current maximum id.  Search the
-        * list to find out what it is.  We're more likely to find
-        * the maximum at the end, so search the list backward.
-        */
-       max_id = 0;
-       list_for_each_prev(tmp, &rbd_dev_list) {
-               struct rbd_device *rbd_dev;
-
-               rbd_dev = list_entry(tmp, struct rbd_device, node);
-               if (rbd_dev->dev_id > max_id)
-                       max_id = rbd_dev->dev_id;
-       }
        spin_unlock(&rbd_dev_list_lock);
 
-       /*
-        * The max id could have been updated by rbd_dev_id_get(), in
-        * which case it now accurately reflects the new maximum.
-        * Be careful not to overwrite the maximum value in that
-        * case.
-        */
-       atomic64_cmpxchg(&rbd_dev_id_max, rbd_id, max_id);
-       dout("  max dev id has been reset\n");
+       ida_simple_remove(&rbd_dev_id_ida, rbd_dev->dev_id);
+
+       dout("rbd_dev %p released dev id %d\n", rbd_dev, rbd_dev->dev_id);
 }
 
 /*
@@ -4860,20 +4902,29 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       /* generate unique id: find highest unique id, add one */
-       rbd_dev_id_get(rbd_dev);
+       /* Get an id and fill in device name. */
+
+       ret = rbd_dev_id_get(rbd_dev);
+       if (ret)
+               return ret;
 
-       /* Fill in the device name, now that we have its id. */
        BUILD_BUG_ON(DEV_NAME_LEN
                        < sizeof (RBD_DRV_NAME) + MAX_INT_FORMAT_WIDTH);
        sprintf(rbd_dev->name, "%s%d", RBD_DRV_NAME, rbd_dev->dev_id);
 
-       /* Get our block major device number. */
+       /* Record our major and minor device numbers. */
 
-       ret = register_blkdev(0, rbd_dev->name);
-       if (ret < 0)
-               goto err_out_id;
-       rbd_dev->major = ret;
+       if (!single_major) {
+               ret = register_blkdev(0, rbd_dev->name);
+               if (ret < 0)
+                       goto err_out_id;
+
+               rbd_dev->major = ret;
+               rbd_dev->minor = 0;
+       } else {
+               rbd_dev->major = rbd_major;
+               rbd_dev->minor = rbd_dev_id_to_minor(rbd_dev->dev_id);
+       }
 
        /* Set up the blkdev mapping. */
 
@@ -4905,7 +4956,8 @@ err_out_mapping:
 err_out_disk:
        rbd_free_disk(rbd_dev);
 err_out_blkdev:
-       unregister_blkdev(rbd_dev->major, rbd_dev->name);
+       if (!single_major)
+               unregister_blkdev(rbd_dev->major, rbd_dev->name);
 err_out_id:
        rbd_dev_id_put(rbd_dev);
        rbd_dev_mapping_clear(rbd_dev);
@@ -4961,7 +5013,6 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 {
        int ret;
-       int tmp;
 
        /*
         * Get the id from the image id object.  Unless there's an
@@ -4980,7 +5031,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
                goto err_out_format;
 
        if (mapping) {
-               ret = rbd_dev_header_watch_sync(rbd_dev, true);
+               ret = rbd_dev_header_watch_sync(rbd_dev);
                if (ret)
                        goto out_header_name;
        }
@@ -5007,12 +5058,8 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 err_out_probe:
        rbd_dev_unprobe(rbd_dev);
 err_out_watch:
-       if (mapping) {
-               tmp = rbd_dev_header_watch_sync(rbd_dev, false);
-               if (tmp)
-                       rbd_warn(rbd_dev, "unable to tear down "
-                                       "watch request (%d)\n", tmp);
-       }
+       if (mapping)
+               rbd_dev_header_unwatch_sync(rbd_dev);
 out_header_name:
        kfree(rbd_dev->header_name);
        rbd_dev->header_name = NULL;
@@ -5026,9 +5073,9 @@ err_out_format:
        return ret;
 }
 
-static ssize_t rbd_add(struct bus_type *bus,
-                      const char *buf,
-                      size_t count)
+static ssize_t do_rbd_add(struct bus_type *bus,
+                         const char *buf,
+                         size_t count)
 {
        struct rbd_device *rbd_dev = NULL;
        struct ceph_options *ceph_opts = NULL;
@@ -5090,6 +5137,12 @@ static ssize_t rbd_add(struct bus_type *bus,
 
        rc = rbd_dev_device_setup(rbd_dev);
        if (rc) {
+               /*
+                * rbd_dev_header_unwatch_sync() can't be moved into
+                * rbd_dev_image_release() without refactoring, see
+                * commit 1f3ef78861ac.
+                */
+               rbd_dev_header_unwatch_sync(rbd_dev);
                rbd_dev_image_release(rbd_dev);
                goto err_out_module;
        }
@@ -5110,6 +5163,23 @@ err_out_module:
        return (ssize_t)rc;
 }
 
+static ssize_t rbd_add(struct bus_type *bus,
+                      const char *buf,
+                      size_t count)
+{
+       if (single_major)
+               return -EINVAL;
+
+       return do_rbd_add(bus, buf, count);
+}
+
+static ssize_t rbd_add_single_major(struct bus_type *bus,
+                                   const char *buf,
+                                   size_t count)
+{
+       return do_rbd_add(bus, buf, count);
+}
+
 static void rbd_dev_device_release(struct device *dev)
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
@@ -5117,8 +5187,8 @@ static void rbd_dev_device_release(struct device *dev)
        rbd_free_disk(rbd_dev);
        clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
        rbd_dev_mapping_clear(rbd_dev);
-       unregister_blkdev(rbd_dev->major, rbd_dev->name);
-       rbd_dev->major = 0;
+       if (!single_major)
+               unregister_blkdev(rbd_dev->major, rbd_dev->name);
        rbd_dev_id_put(rbd_dev);
        rbd_dev_mapping_clear(rbd_dev);
 }
@@ -5149,9 +5219,9 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
        }
 }
 
-static ssize_t rbd_remove(struct bus_type *bus,
-                         const char *buf,
-                         size_t count)
+static ssize_t do_rbd_remove(struct bus_type *bus,
+                            const char *buf,
+                            size_t count)
 {
        struct rbd_device *rbd_dev = NULL;
        struct list_head *tmp;
@@ -5191,16 +5261,14 @@ static ssize_t rbd_remove(struct bus_type *bus,
        if (ret < 0 || already)
                return ret;
 
-       ret = rbd_dev_header_watch_sync(rbd_dev, false);
-       if (ret)
-               rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
-
+       rbd_dev_header_unwatch_sync(rbd_dev);
        /*
         * flush remaining watch callbacks - these must be complete
         * before the osd_client is shutdown
         */
        dout("%s: flushing notifies", __func__);
        ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc);
+
        /*
         * Don't free anything from rbd_dev->disk until after all
         * notifies are completely processed. Otherwise
@@ -5214,6 +5282,23 @@ static ssize_t rbd_remove(struct bus_type *bus,
        return count;
 }
 
+static ssize_t rbd_remove(struct bus_type *bus,
+                         const char *buf,
+                         size_t count)
+{
+       if (single_major)
+               return -EINVAL;
+
+       return do_rbd_remove(bus, buf, count);
+}
+
+static ssize_t rbd_remove_single_major(struct bus_type *bus,
+                                      const char *buf,
+                                      size_t count)
+{
+       return do_rbd_remove(bus, buf, count);
+}
+
 /*
  * create control files in sysfs
  * /sys/bus/rbd/...
@@ -5259,7 +5344,7 @@ static int rbd_slab_init(void)
 
        rbd_assert(!rbd_segment_name_cache);
        rbd_segment_name_cache = kmem_cache_create("rbd_segment_name",
-                                       MAX_OBJ_NAME_SIZE + 1, 1, 0, NULL);
+                                       CEPH_MAX_OID_NAME_LEN + 1, 1, 0, NULL);
        if (rbd_segment_name_cache)
                return 0;
 out_err:
@@ -5295,24 +5380,45 @@ static int __init rbd_init(void)
 
        if (!libceph_compatible(NULL)) {
                rbd_warn(NULL, "libceph incompatibility (quitting)");
-
                return -EINVAL;
        }
+
        rc = rbd_slab_init();
        if (rc)
                return rc;
+
+       if (single_major) {
+               rbd_major = register_blkdev(0, RBD_DRV_NAME);
+               if (rbd_major < 0) {
+                       rc = rbd_major;
+                       goto err_out_slab;
+               }
+       }
+
        rc = rbd_sysfs_init();
        if (rc)
-               rbd_slab_exit();
+               goto err_out_blkdev;
+
+       if (single_major)
+               pr_info("loaded (major %d)\n", rbd_major);
        else
-               pr_info("loaded " RBD_DRV_NAME_LONG "\n");
+               pr_info("loaded\n");
+
+       return 0;
 
+err_out_blkdev:
+       if (single_major)
+               unregister_blkdev(rbd_major, RBD_DRV_NAME);
+err_out_slab:
+       rbd_slab_exit();
        return rc;
 }
 
 static void __exit rbd_exit(void)
 {
        rbd_sysfs_cleanup();
+       if (single_major)
+               unregister_blkdev(rbd_major, RBD_DRV_NAME);
        rbd_slab_exit();
 }
 
@@ -5322,9 +5428,8 @@ module_exit(rbd_exit);
 MODULE_AUTHOR("Alex Elder <elder@inktank.com>");
 MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
-MODULE_DESCRIPTION("rados block device");
-
 /* following authorship retained from original osdblk.c */
 MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
 
+MODULE_DESCRIPTION("RADOS Block Device (RBD) driver");
 MODULE_LICENSE("GPL");
index 0c16e9cdfb87857c3fd528eebefa72f4af28f629..a367a98317175f59745e5b61e6fdf175f29342bc 100644 (file)
@@ -9,45 +9,44 @@ obj-$(CONFIG_COMMON_CLK)      += clk-gate.o
 obj-$(CONFIG_COMMON_CLK)       += clk-mux.o
 obj-$(CONFIG_COMMON_CLK)       += clk-composite.o
 
-# SoCs specific
-obj-$(CONFIG_ARCH_BCM2835)     += clk-bcm2835.o
-obj-$(CONFIG_ARCH_EFM32)       += clk-efm32gg.o
-obj-$(CONFIG_ARCH_NOMADIK)     += clk-nomadik.o
-obj-$(CONFIG_ARCH_HIGHBANK)    += clk-highbank.o
-obj-$(CONFIG_ARCH_HI3xxx)      += hisilicon/
-obj-$(CONFIG_ARCH_NSPIRE)      += clk-nspire.o
-obj-$(CONFIG_ARCH_MXS)         += mxs/
-obj-$(CONFIG_ARCH_SOCFPGA)     += socfpga/
-obj-$(CONFIG_PLAT_SPEAR)       += spear/
-obj-$(CONFIG_ARCH_U300)                += clk-u300.o
-obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
-obj-$(CONFIG_COMMON_CLK_QCOM)  += qcom/
-obj-$(CONFIG_PLAT_ORION)       += mvebu/
+# hardware specific clock types
+# please keep this section sorted lexicographically by file/directory path name
+obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN)    += clk-axi-clkgen.o
+obj-$(CONFIG_ARCH_BCM2835)             += clk-bcm2835.o
+obj-$(CONFIG_ARCH_EFM32)               += clk-efm32gg.o
+obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
+obj-$(CONFIG_MACH_LOONGSON1)           += clk-ls1x.o
+obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
+obj-$(CONFIG_ARCH_NOMADIK)             += clk-nomadik.o
+obj-$(CONFIG_ARCH_NSPIRE)              += clk-nspire.o
+obj-$(CONFIG_CLK_PPC_CORENET)          += clk-ppc-corenet.o
+obj-$(CONFIG_COMMON_CLK_S2MPS11)       += clk-s2mps11.o
+obj-$(CONFIG_COMMON_CLK_SI5351)                += clk-si5351.o
+obj-$(CONFIG_COMMON_CLK_SI570)         += clk-si570.o
+obj-$(CONFIG_CLK_TWL6040)              += clk-twl6040.o
+obj-$(CONFIG_ARCH_U300)                        += clk-u300.o
+obj-$(CONFIG_ARCH_VT8500)              += clk-vt8500.o
+obj-$(CONFIG_COMMON_CLK_WM831X)                += clk-wm831x.o
+obj-$(CONFIG_COMMON_CLK_XGENE)         += clk-xgene.o
+obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
+obj-$(CONFIG_ARCH_HI3xxx)              += hisilicon/
+obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
-obj-$(CONFIG_ARCH_MMP)         += mmp/
+obj-$(CONFIG_ARCH_MMP)                 += mmp/
 endif
-obj-$(CONFIG_MACH_LOONGSON1)   += clk-ls1x.o
-obj-$(CONFIG_ARCH_ROCKCHIP)    += rockchip/
-obj-$(CONFIG_ARCH_SUNXI)       += sunxi/
-obj-$(CONFIG_ARCH_U8500)       += ux500/
-obj-$(CONFIG_ARCH_VT8500)      += clk-vt8500.o
-obj-$(CONFIG_ARCH_SIRF)                += sirf/
-obj-$(CONFIG_ARCH_ZYNQ)                += zynq/
-obj-$(CONFIG_ARCH_TEGRA)       += tegra/
-obj-$(CONFIG_PLAT_SAMSUNG)     += samsung/
-obj-$(CONFIG_COMMON_CLK_XGENE)  += clk-xgene.o
-obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
-obj-$(CONFIG_COMMON_CLK_AT91)  += at91/
+obj-$(CONFIG_PLAT_ORION)               += mvebu/
+obj-$(CONFIG_ARCH_MXS)                 += mxs/
+obj-$(CONFIG_COMMON_CLK_QCOM)          += qcom/
+obj-$(CONFIG_ARCH_ROCKCHIP)            += rockchip/
+obj-$(CONFIG_PLAT_SAMSUNG)             += samsung/
 obj-$(CONFIG_ARCH_SHMOBILE_MULTI)      += shmobile/
-
-obj-$(CONFIG_X86)              += x86/
-
-# Chip specific
-obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
-obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
-obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
-obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
-obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
-obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
-obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
-obj-$(CONFIG_CLK_PPC_CORENET)  += clk-ppc-corenet.o
+obj-$(CONFIG_ARCH_SIRF)                        += sirf/
+obj-$(CONFIG_ARCH_SOCFPGA)             += socfpga/
+obj-$(CONFIG_PLAT_SPEAR)               += spear/
+obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
+obj-$(CONFIG_ARCH_TEGRA)               += tegra/
+obj-$(CONFIG_ARCH_OMAP2PLUS)           += ti/
+obj-$(CONFIG_ARCH_U8500)               += ux500/
+obj-$(CONFIG_COMMON_CLK_VERSATILE)     += versatile/
+obj-$(CONFIG_X86)                      += x86/
+obj-$(CONFIG_ARCH_ZYNQ)                        += zynq/
index c50e83744b0aec3a0a8841f068bbbe05adc5ef8d..3b2a66f78755113fe9afde8f9caaa4d4e801260b 100644 (file)
@@ -1111,11 +1111,11 @@ static const struct of_device_id si5351_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, si5351_dt_ids);
 
-static int si5351_dt_parse(struct i2c_client *client)
+static int si5351_dt_parse(struct i2c_client *client,
+                          enum si5351_variant variant)
 {
        struct device_node *child, *np = client->dev.of_node;
        struct si5351_platform_data *pdata;
-       const struct of_device_id *match;
        struct property *prop;
        const __be32 *p;
        int num = 0;
@@ -1124,15 +1124,10 @@ static int si5351_dt_parse(struct i2c_client *client)
        if (np == NULL)
                return 0;
 
-       match = of_match_node(si5351_dt_ids, np);
-       if (match == NULL)
-               return -EINVAL;
-
        pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
                return -ENOMEM;
 
-       pdata->variant = (enum si5351_variant)match->data;
        pdata->clk_xtal = of_clk_get(np, 0);
        if (!IS_ERR(pdata->clk_xtal))
                clk_put(pdata->clk_xtal);
@@ -1163,7 +1158,7 @@ static int si5351_dt_parse(struct i2c_client *client)
                        pdata->pll_src[num] = SI5351_PLL_SRC_XTAL;
                        break;
                case 1:
-                       if (pdata->variant != SI5351_VARIANT_C) {
+                       if (variant != SI5351_VARIANT_C) {
                                dev_err(&client->dev,
                                        "invalid parent %d for pll %d\n",
                                        val, num);
@@ -1187,7 +1182,7 @@ static int si5351_dt_parse(struct i2c_client *client)
                }
 
                if (num >= 8 ||
-                   (pdata->variant == SI5351_VARIANT_A3 && num >= 3)) {
+                   (variant == SI5351_VARIANT_A3 && num >= 3)) {
                        dev_err(&client->dev, "invalid clkout %d\n", num);
                        return -EINVAL;
                }
@@ -1226,7 +1221,7 @@ static int si5351_dt_parse(struct i2c_client *client)
                                        SI5351_CLKOUT_SRC_XTAL;
                                break;
                        case 3:
-                               if (pdata->variant != SI5351_VARIANT_C) {
+                               if (variant != SI5351_VARIANT_C) {
                                        dev_err(&client->dev,
                                                "invalid parent %d for clkout %d\n",
                                                val, num);
@@ -1298,7 +1293,7 @@ static int si5351_dt_parse(struct i2c_client *client)
        return 0;
 }
 #else
-static int si5351_dt_parse(struct i2c_client *client)
+static int si5351_dt_parse(struct i2c_client *client, enum si5351_variant variant)
 {
        return 0;
 }
@@ -1307,6 +1302,7 @@ static int si5351_dt_parse(struct i2c_client *client)
 static int si5351_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
+       enum si5351_variant variant = (enum si5351_variant)id->driver_data;
        struct si5351_platform_data *pdata;
        struct si5351_driver_data *drvdata;
        struct clk_init_data init;
@@ -1315,7 +1311,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
        u8 num_parents, num_clocks;
        int ret, n;
 
-       ret = si5351_dt_parse(client);
+       ret = si5351_dt_parse(client, variant);
        if (ret)
                return ret;
 
@@ -1331,7 +1327,7 @@ static int si5351_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, drvdata);
        drvdata->client = client;
-       drvdata->variant = pdata->variant;
+       drvdata->variant = variant;
        drvdata->pxtal = pdata->clk_xtal;
        drvdata->pclkin = pdata->clk_clkin;
 
@@ -1568,10 +1564,10 @@ static int si5351_i2c_probe(struct i2c_client *client,
 }
 
 static const struct i2c_device_id si5351_i2c_ids[] = {
-       { "si5351a", 0 },
-       { "si5351a-msop", 0 },
-       { "si5351b", 0 },
-       { "si5351c", 0 },
+       { "si5351a", SI5351_VARIANT_A },
+       { "si5351a-msop", SI5351_VARIANT_A3 },
+       { "si5351b", SI5351_VARIANT_B },
+       { "si5351c", SI5351_VARIANT_C },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
index c0dbf2676872995c1ff698cefe37719f43f1236a..4d0746b50c32e8a6265fb5a410371daebfb5ba85 100644 (file)
 #define  SI5351_XTAL_ENABLE                    (1<<6)
 #define  SI5351_MULTISYNTH_ENABLE              (1<<4)
 
+/**
+ * enum si5351_variant - SiLabs Si5351 chip variant
+ * @SI5351_VARIANT_A: Si5351A (8 output clocks, XTAL input)
+ * @SI5351_VARIANT_A3: Si5351A MSOP10 (3 output clocks, XTAL input)
+ * @SI5351_VARIANT_B: Si5351B (8 output clocks, XTAL/VXCO input)
+ * @SI5351_VARIANT_C: Si5351C (8 output clocks, XTAL/CLKIN input)
+ */
+enum si5351_variant {
+       SI5351_VARIANT_A = 1,
+       SI5351_VARIANT_A3 = 2,
+       SI5351_VARIANT_B = 3,
+       SI5351_VARIANT_C = 4,
+};
+
 #endif
index 2b38dc99063f1b6574df031ccea84af5df9cb9e6..5517944495d893cc3c8dd60569b58e67e9289765 100644 (file)
@@ -575,16 +575,19 @@ struct clk_hw *__clk_get_hw(struct clk *clk)
 {
        return !clk ? NULL : clk->hw;
 }
+EXPORT_SYMBOL_GPL(__clk_get_hw);
 
 u8 __clk_get_num_parents(struct clk *clk)
 {
        return !clk ? 0 : clk->num_parents;
 }
+EXPORT_SYMBOL_GPL(__clk_get_num_parents);
 
 struct clk *__clk_get_parent(struct clk *clk)
 {
        return !clk ? NULL : clk->parent;
 }
+EXPORT_SYMBOL_GPL(__clk_get_parent);
 
 struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
 {
@@ -598,6 +601,7 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
        else
                return clk->parents[index];
 }
+EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
 
 unsigned int __clk_get_enable_count(struct clk *clk)
 {
@@ -629,6 +633,7 @@ unsigned long __clk_get_rate(struct clk *clk)
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(__clk_get_rate);
 
 unsigned long __clk_get_accuracy(struct clk *clk)
 {
@@ -685,6 +690,7 @@ bool __clk_is_enabled(struct clk *clk)
 out:
        return !!ret;
 }
+EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
 static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
 {
@@ -776,6 +782,7 @@ out:
 
        return best;
 }
+EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
 /***        clk api        ***/
 
@@ -2373,8 +2380,6 @@ struct of_clk_provider {
        void *data;
 };
 
-extern struct of_device_id __clk_of_table[];
-
 static const struct of_device_id __clk_of_table_sentinel
        __used __section(__clk_of_table_end);
 
@@ -2534,7 +2539,7 @@ void __init of_clk_init(const struct of_device_id *matches)
        struct device_node *np;
 
        if (!matches)
-               matches = __clk_of_table;
+               matches = &__clk_of_table;
 
        for_each_matching_node_and_match(np, matches, &match) {
                of_clk_init_cb_t clk_init_cb = match->data;
index 190d38433202dbe43e0714a72471df03a243c7e6..f60db2ef1aee6a8d9150ec6c896827921a8e803f 100644 (file)
@@ -1,11 +1,11 @@
 obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
 
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-regmap.o
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
-clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
+clk-qcom-y += clk-regmap.o
+clk-qcom-y += clk-pll.o
+clk-qcom-y += clk-rcg.o
+clk-qcom-y += clk-rcg2.o
+clk-qcom-y += clk-branch.o
+clk-qcom-y += reset.o
 
 obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
index 529e11dc2c6b0e8af21506211a7756f04b324123..81e6d2f49aa001a9587b33e848c0b4692d5d82e0 100644 (file)
@@ -375,7 +375,7 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
                break;
        default:
                break;
-       };
+       }
 
        /* Set new configuration. */
        __raw_writel(con1, pll->con_reg + 0x4);
index 659e4ea31893a42bee5fb701d54fcbb34776ed67..abb6c5ac8a10297505a8a7f1cb1cb0d5f8eccf16 100644 (file)
@@ -875,7 +875,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
        if (!clk_data)
                return;
 
-       clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
+       clks = kzalloc((SUNXI_DIVS_MAX_QTY+1) * sizeof(*clks), GFP_KERNEL);
        if (!clks)
                goto free_clkdata;
 
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
new file mode 100644 (file)
index 0000000..4319d40
--- /dev/null
@@ -0,0 +1,11 @@
+ifneq ($(CONFIG_OF),)
+obj-y                                  += clk.o autoidle.o clockdomain.o
+clk-common                             = dpll.o composite.o divider.o gate.o \
+                                         fixed-factor.o mux.o apll.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o
+obj-$(CONFIG_ARCH_OMAP3)               += $(clk-common) interface.o clk-3xxx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o
+obj-$(CONFIG_SOC_DRA7XX)               += $(clk-common) clk-7xx.o
+obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) clk-43xx.o
+endif
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
new file mode 100644 (file)
index 0000000..b986f61
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * OMAP APLL clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * J Keerthy <j-keerthy@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/delay.h>
+
+#define APLL_FORCE_LOCK 0x1
+#define APLL_AUTO_IDLE 0x2
+#define MAX_APLL_WAIT_TRIES            1000000
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static int dra7_apll_enable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       int r = 0, i = 0;
+       struct dpll_data *ad;
+       const char *clk_name;
+       u8 state = 1;
+       u32 v;
+
+       ad = clk->dpll_data;
+       if (!ad)
+               return -EINVAL;
+
+       clk_name = __clk_get_name(clk->hw.clk);
+
+       state <<= __ffs(ad->idlest_mask);
+
+       /* Check is already locked */
+       v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+
+       if ((v & ad->idlest_mask) == state)
+               return r;
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ~ad->enable_mask;
+       v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask);
+       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+
+       state <<= __ffs(ad->idlest_mask);
+
+       while (1) {
+               v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+               if ((v & ad->idlest_mask) == state)
+                       break;
+               if (i > MAX_APLL_WAIT_TRIES)
+                       break;
+               i++;
+               udelay(1);
+       }
+
+       if (i == MAX_APLL_WAIT_TRIES) {
+               pr_warn("clock: %s failed transition to '%s'\n",
+                       clk_name, (state) ? "locked" : "bypassed");
+       } else {
+               pr_debug("clock: %s transition to '%s' in %d loops\n",
+                        clk_name, (state) ? "locked" : "bypassed", i);
+
+               r = 0;
+       }
+
+       return r;
+}
+
+static void dra7_apll_disable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *ad;
+       u8 state = 1;
+       u32 v;
+
+       ad = clk->dpll_data;
+
+       state <<= __ffs(ad->idlest_mask);
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ~ad->enable_mask;
+       v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask);
+       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+}
+
+static int dra7_apll_is_enabled(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *ad;
+       u32 v;
+
+       ad = clk->dpll_data;
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ad->enable_mask;
+
+       v >>= __ffs(ad->enable_mask);
+
+       return v == APLL_AUTO_IDLE ? 0 : 1;
+}
+
+static u8 dra7_init_apll_parent(struct clk_hw *hw)
+{
+       return 0;
+}
+
+static const struct clk_ops apll_ck_ops = {
+       .enable         = &dra7_apll_enable,
+       .disable        = &dra7_apll_disable,
+       .is_enabled     = &dra7_apll_is_enabled,
+       .get_parent     = &dra7_init_apll_parent,
+};
+
+static void __init omap_clk_register_apll(struct clk_hw *hw,
+                                         struct device_node *node)
+{
+       struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+       struct dpll_data *ad = clk_hw->dpll_data;
+       struct clk *clk;
+
+       ad->clk_ref = of_clk_get(node, 0);
+       ad->clk_bypass = of_clk_get(node, 1);
+
+       if (IS_ERR(ad->clk_ref) || IS_ERR(ad->clk_bypass)) {
+               pr_debug("clk-ref or clk-bypass for %s not ready, retry\n",
+                        node->name);
+               if (!ti_clk_retry_init(node, hw, omap_clk_register_apll))
+                       return;
+
+               goto cleanup;
+       }
+
+       clk = clk_register(NULL, &clk_hw->hw);
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               kfree(clk_hw->hw.init->parent_names);
+               kfree(clk_hw->hw.init);
+               return;
+       }
+
+cleanup:
+       kfree(clk_hw->dpll_data);
+       kfree(clk_hw->hw.init->parent_names);
+       kfree(clk_hw->hw.init);
+       kfree(clk_hw);
+}
+
+static void __init of_dra7_apll_setup(struct device_node *node)
+{
+       struct dpll_data *ad = NULL;
+       struct clk_hw_omap *clk_hw = NULL;
+       struct clk_init_data *init = NULL;
+       const char **parent_names = NULL;
+       int i;
+
+       ad = kzalloc(sizeof(*ad), GFP_KERNEL);
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       init = kzalloc(sizeof(*init), GFP_KERNEL);
+       if (!ad || !clk_hw || !init)
+               goto cleanup;
+
+       clk_hw->dpll_data = ad;
+       clk_hw->hw.init = init;
+       clk_hw->flags = MEMMAP_ADDRESSING;
+
+       init->name = node->name;
+       init->ops = &apll_ck_ops;
+
+       init->num_parents = of_clk_get_parent_count(node);
+       if (init->num_parents < 1) {
+               pr_err("dra7 apll %s must have parent(s)\n", node->name);
+               goto cleanup;
+       }
+
+       parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+       if (!parent_names)
+               goto cleanup;
+
+       for (i = 0; i < init->num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(node, i);
+
+       init->parent_names = parent_names;
+
+       ad->control_reg = ti_clk_get_reg_addr(node, 0);
+       ad->idlest_reg = ti_clk_get_reg_addr(node, 1);
+
+       if (!ad->control_reg || !ad->idlest_reg)
+               goto cleanup;
+
+       ad->idlest_mask = 0x1;
+       ad->enable_mask = 0x3;
+
+       omap_clk_register_apll(&clk_hw->hw, node);
+       return;
+
+cleanup:
+       kfree(parent_names);
+       kfree(ad);
+       kfree(clk_hw);
+       kfree(init);
+}
+CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup);
diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c
new file mode 100644 (file)
index 0000000..8912ff8
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * TI clock autoidle support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+struct clk_ti_autoidle {
+       void __iomem            *reg;
+       u8                      shift;
+       u8                      flags;
+       const char              *name;
+       struct list_head        node;
+};
+
+#define AUTOIDLE_LOW           0x1
+
+static LIST_HEAD(autoidle_clks);
+
+static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
+{
+       u32 val;
+
+       val = ti_clk_ll_ops->clk_readl(clk->reg);
+
+       if (clk->flags & AUTOIDLE_LOW)
+               val &= ~(1 << clk->shift);
+       else
+               val |= (1 << clk->shift);
+
+       ti_clk_ll_ops->clk_writel(val, clk->reg);
+}
+
+static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
+{
+       u32 val;
+
+       val = ti_clk_ll_ops->clk_readl(clk->reg);
+
+       if (clk->flags & AUTOIDLE_LOW)
+               val |= (1 << clk->shift);
+       else
+               val &= ~(1 << clk->shift);
+
+       ti_clk_ll_ops->clk_writel(val, clk->reg);
+}
+
+/**
+ * of_ti_clk_allow_autoidle_all - enable autoidle for all clocks
+ *
+ * Enables hardware autoidle for all registered DT clocks, which have
+ * the feature.
+ */
+void of_ti_clk_allow_autoidle_all(void)
+{
+       struct clk_ti_autoidle *c;
+
+       list_for_each_entry(c, &autoidle_clks, node)
+               ti_allow_autoidle(c);
+}
+
+/**
+ * of_ti_clk_deny_autoidle_all - disable autoidle for all clocks
+ *
+ * Disables hardware autoidle for all registered DT clocks, which have
+ * the feature.
+ */
+void of_ti_clk_deny_autoidle_all(void)
+{
+       struct clk_ti_autoidle *c;
+
+       list_for_each_entry(c, &autoidle_clks, node)
+               ti_deny_autoidle(c);
+}
+
+/**
+ * of_ti_clk_autoidle_setup - sets up hardware autoidle for a clock
+ * @node: pointer to the clock device node
+ *
+ * Checks if a clock has hardware autoidle support or not (check
+ * for presence of 'ti,autoidle-shift' property in the device tree
+ * node) and sets up the hardware autoidle feature for the clock
+ * if available. If autoidle is available, the clock is also added
+ * to the autoidle list for later processing. Returns 0 on success,
+ * negative error value on failure.
+ */
+int __init of_ti_clk_autoidle_setup(struct device_node *node)
+{
+       u32 shift;
+       struct clk_ti_autoidle *clk;
+
+       /* Check if this clock has autoidle support or not */
+       if (of_property_read_u32(node, "ti,autoidle-shift", &shift))
+               return 0;
+
+       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+
+       if (!clk)
+               return -ENOMEM;
+
+       clk->shift = shift;
+       clk->name = node->name;
+       clk->reg = ti_clk_get_reg_addr(node, 0);
+
+       if (!clk->reg) {
+               kfree(clk);
+               return -EINVAL;
+       }
+
+       if (of_property_read_bool(node, "ti,invert-autoidle-bit"))
+               clk->flags |= AUTOIDLE_LOW;
+
+       list_add(&clk->node, &autoidle_clks);
+
+       return 0;
+}
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
new file mode 100644 (file)
index 0000000..776ee45
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * AM33XX Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc
+ *     Tero Kristo (t-kristo@ti.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
+
+static struct ti_dt_clk am33xx_clks[] = {
+       DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
+       DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_24000000_ck", "virt_24000000_ck"),
+       DT_CLK(NULL, "virt_25000000_ck", "virt_25000000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"),
+       DT_CLK(NULL, "tclkin_ck", "tclkin_ck"),
+       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
+       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
+       DT_CLK(NULL, "dpll_core_m4_ck", "dpll_core_m4_ck"),
+       DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"),
+       DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"),
+       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
+       DT_CLK("cpu0", NULL, "dpll_mpu_ck"),
+       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
+       DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"),
+       DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"),
+       DT_CLK(NULL, "dpll_ddr_m2_div2_ck", "dpll_ddr_m2_div2_ck"),
+       DT_CLK(NULL, "dpll_disp_ck", "dpll_disp_ck"),
+       DT_CLK(NULL, "dpll_disp_m2_ck", "dpll_disp_m2_ck"),
+       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
+       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
+       DT_CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", "dpll_per_m2_div4_wkupdm_ck"),
+       DT_CLK(NULL, "dpll_per_m2_div4_ck", "dpll_per_m2_div4_ck"),
+       DT_CLK(NULL, "adc_tsc_fck", "adc_tsc_fck"),
+       DT_CLK(NULL, "cefuse_fck", "cefuse_fck"),
+       DT_CLK(NULL, "clkdiv32k_ck", "clkdiv32k_ck"),
+       DT_CLK(NULL, "clkdiv32k_ick", "clkdiv32k_ick"),
+       DT_CLK(NULL, "dcan0_fck", "dcan0_fck"),
+       DT_CLK("481cc000.d_can", NULL, "dcan0_fck"),
+       DT_CLK(NULL, "dcan1_fck", "dcan1_fck"),
+       DT_CLK("481d0000.d_can", NULL, "dcan1_fck"),
+       DT_CLK(NULL, "pruss_ocp_gclk", "pruss_ocp_gclk"),
+       DT_CLK(NULL, "mcasp0_fck", "mcasp0_fck"),
+       DT_CLK(NULL, "mcasp1_fck", "mcasp1_fck"),
+       DT_CLK(NULL, "mmu_fck", "mmu_fck"),
+       DT_CLK(NULL, "smartreflex0_fck", "smartreflex0_fck"),
+       DT_CLK(NULL, "smartreflex1_fck", "smartreflex1_fck"),
+       DT_CLK(NULL, "sha0_fck", "sha0_fck"),
+       DT_CLK(NULL, "aes0_fck", "aes0_fck"),
+       DT_CLK(NULL, "rng_fck", "rng_fck"),
+       DT_CLK(NULL, "timer1_fck", "timer1_fck"),
+       DT_CLK(NULL, "timer2_fck", "timer2_fck"),
+       DT_CLK(NULL, "timer3_fck", "timer3_fck"),
+       DT_CLK(NULL, "timer4_fck", "timer4_fck"),
+       DT_CLK(NULL, "timer5_fck", "timer5_fck"),
+       DT_CLK(NULL, "timer6_fck", "timer6_fck"),
+       DT_CLK(NULL, "timer7_fck", "timer7_fck"),
+       DT_CLK(NULL, "usbotg_fck", "usbotg_fck"),
+       DT_CLK(NULL, "ieee5000_fck", "ieee5000_fck"),
+       DT_CLK(NULL, "wdt1_fck", "wdt1_fck"),
+       DT_CLK(NULL, "l4_rtc_gclk", "l4_rtc_gclk"),
+       DT_CLK(NULL, "l3_gclk", "l3_gclk"),
+       DT_CLK(NULL, "dpll_core_m4_div2_ck", "dpll_core_m4_div2_ck"),
+       DT_CLK(NULL, "l4hs_gclk", "l4hs_gclk"),
+       DT_CLK(NULL, "l3s_gclk", "l3s_gclk"),
+       DT_CLK(NULL, "l4fw_gclk", "l4fw_gclk"),
+       DT_CLK(NULL, "l4ls_gclk", "l4ls_gclk"),
+       DT_CLK(NULL, "clk_24mhz", "clk_24mhz"),
+       DT_CLK(NULL, "sysclk_div_ck", "sysclk_div_ck"),
+       DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"),
+       DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"),
+       DT_CLK(NULL, "gpio0_dbclk_mux_ck", "gpio0_dbclk_mux_ck"),
+       DT_CLK(NULL, "gpio0_dbclk", "gpio0_dbclk"),
+       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
+       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
+       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
+       DT_CLK(NULL, "lcd_gclk", "lcd_gclk"),
+       DT_CLK(NULL, "mmc_clk", "mmc_clk"),
+       DT_CLK(NULL, "gfx_fclk_clksel_ck", "gfx_fclk_clksel_ck"),
+       DT_CLK(NULL, "gfx_fck_div_ck", "gfx_fck_div_ck"),
+       DT_CLK(NULL, "sysclkout_pre_ck", "sysclkout_pre_ck"),
+       DT_CLK(NULL, "clkout2_div_ck", "clkout2_div_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "clkdiv32k_ick"),
+       DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK(NULL, "dbg_sysclk_ck", "dbg_sysclk_ck"),
+       DT_CLK(NULL, "dbg_clka_ck", "dbg_clka_ck"),
+       DT_CLK(NULL, "stm_pmd_clock_mux_ck", "stm_pmd_clock_mux_ck"),
+       DT_CLK(NULL, "trace_pmd_clk_mux_ck", "trace_pmd_clk_mux_ck"),
+       DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"),
+       DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"),
+       DT_CLK(NULL, "clkout2_ck", "clkout2_ck"),
+       DT_CLK("48300200.ehrpwm", "tbclk", "ehrpwm0_tbclk"),
+       DT_CLK("48302200.ehrpwm", "tbclk", "ehrpwm1_tbclk"),
+       DT_CLK("48304200.ehrpwm", "tbclk", "ehrpwm2_tbclk"),
+       { .node_name = NULL },
+};
+
+static const char *enable_init_clks[] = {
+       "dpll_ddr_m2_ck",
+       "dpll_mpu_m2_ck",
+       "l3_gclk",
+       "l4hs_gclk",
+       "l4fw_gclk",
+       "l4ls_gclk",
+       /* Required for external peripherals like, Audio codecs */
+       "clkout2_ck",
+};
+
+int __init am33xx_dt_clk_init(void)
+{
+       struct clk *clk1, *clk2;
+
+       ti_dt_clocks_register(am33xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       omap2_clk_enable_init_clocks(enable_init_clks,
+                                    ARRAY_SIZE(enable_init_clks));
+
+       /* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
+        *    physically present, in such a case HWMOD enabling of
+        *    clock would be failure with default parent. And timer
+        *    probe thinks clock is already enabled, this leads to
+        *    crash upon accessing timer 3 & 6 registers in probe.
+        *    Fix by setting parent of both these timers to master
+        *    oscillator clock.
+        */
+
+       clk1 = clk_get_sys(NULL, "sys_clkin_ck");
+       clk2 = clk_get_sys(NULL, "timer3_fck");
+       clk_set_parent(clk2, clk1);
+
+       clk2 = clk_get_sys(NULL, "timer6_fck");
+       clk_set_parent(clk2, clk1);
+       /*
+        * The On-Chip 32K RC Osc clock is not an accurate clock-source as per
+        * the design/spec, so as a result, for example, timer which supposed
+        * to get expired @60Sec, but will expire somewhere ~@40Sec, which is
+        * not expected by any use-case, so change WDT1 clock source to PRCM
+        * 32KHz clock.
+        */
+       clk1 = clk_get_sys(NULL, "wdt1_fck");
+       clk2 = clk_get_sys(NULL, "clkdiv32k_ick");
+       clk_set_parent(clk1, clk2);
+
+       return 0;
+}
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
new file mode 100644 (file)
index 0000000..d323023
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * OMAP3 Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc
+ *     Tero Kristo (t-kristo@ti.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
+
+
+static struct ti_dt_clk omap3xxx_clks[] = {
+       DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"),
+       DT_CLK(NULL, "omap_32k_fck", "omap_32k_fck"),
+       DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"),
+       DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "virt_38_4m_ck", "virt_38_4m_ck"),
+       DT_CLK(NULL, "osc_sys_ck", "osc_sys_ck"),
+       DT_CLK("twl", "fck", "osc_sys_ck"),
+       DT_CLK(NULL, "sys_ck", "sys_ck"),
+       DT_CLK(NULL, "omap_96m_alwon_fck", "omap_96m_alwon_fck"),
+       DT_CLK("etb", "emu_core_alwon_ck", "emu_core_alwon_ck"),
+       DT_CLK(NULL, "sys_altclk", "sys_altclk"),
+       DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
+       DT_CLK(NULL, "sys_clkout1", "sys_clkout1"),
+       DT_CLK(NULL, "dpll1_ck", "dpll1_ck"),
+       DT_CLK(NULL, "dpll1_x2_ck", "dpll1_x2_ck"),
+       DT_CLK(NULL, "dpll1_x2m2_ck", "dpll1_x2m2_ck"),
+       DT_CLK(NULL, "dpll3_ck", "dpll3_ck"),
+       DT_CLK(NULL, "core_ck", "core_ck"),
+       DT_CLK(NULL, "dpll3_x2_ck", "dpll3_x2_ck"),
+       DT_CLK(NULL, "dpll3_m2_ck", "dpll3_m2_ck"),
+       DT_CLK(NULL, "dpll3_m2x2_ck", "dpll3_m2x2_ck"),
+       DT_CLK(NULL, "dpll3_m3_ck", "dpll3_m3_ck"),
+       DT_CLK(NULL, "dpll3_m3x2_ck", "dpll3_m3x2_ck"),
+       DT_CLK(NULL, "dpll4_ck", "dpll4_ck"),
+       DT_CLK(NULL, "dpll4_x2_ck", "dpll4_x2_ck"),
+       DT_CLK(NULL, "omap_96m_fck", "omap_96m_fck"),
+       DT_CLK(NULL, "cm_96m_fck", "cm_96m_fck"),
+       DT_CLK(NULL, "omap_54m_fck", "omap_54m_fck"),
+       DT_CLK(NULL, "omap_48m_fck", "omap_48m_fck"),
+       DT_CLK(NULL, "omap_12m_fck", "omap_12m_fck"),
+       DT_CLK(NULL, "dpll4_m2_ck", "dpll4_m2_ck"),
+       DT_CLK(NULL, "dpll4_m2x2_ck", "dpll4_m2x2_ck"),
+       DT_CLK(NULL, "dpll4_m3_ck", "dpll4_m3_ck"),
+       DT_CLK(NULL, "dpll4_m3x2_ck", "dpll4_m3x2_ck"),
+       DT_CLK(NULL, "dpll4_m4_ck", "dpll4_m4_ck"),
+       DT_CLK(NULL, "dpll4_m4x2_ck", "dpll4_m4x2_ck"),
+       DT_CLK(NULL, "dpll4_m5_ck", "dpll4_m5_ck"),
+       DT_CLK(NULL, "dpll4_m5x2_ck", "dpll4_m5x2_ck"),
+       DT_CLK(NULL, "dpll4_m6_ck", "dpll4_m6_ck"),
+       DT_CLK(NULL, "dpll4_m6x2_ck", "dpll4_m6x2_ck"),
+       DT_CLK("etb", "emu_per_alwon_ck", "emu_per_alwon_ck"),
+       DT_CLK(NULL, "clkout2_src_ck", "clkout2_src_ck"),
+       DT_CLK(NULL, "sys_clkout2", "sys_clkout2"),
+       DT_CLK(NULL, "corex2_fck", "corex2_fck"),
+       DT_CLK(NULL, "dpll1_fck", "dpll1_fck"),
+       DT_CLK(NULL, "mpu_ck", "mpu_ck"),
+       DT_CLK(NULL, "arm_fck", "arm_fck"),
+       DT_CLK("etb", "emu_mpu_alwon_ck", "emu_mpu_alwon_ck"),
+       DT_CLK(NULL, "l3_ick", "l3_ick"),
+       DT_CLK(NULL, "l4_ick", "l4_ick"),
+       DT_CLK(NULL, "rm_ick", "rm_ick"),
+       DT_CLK(NULL, "gpt10_fck", "gpt10_fck"),
+       DT_CLK(NULL, "gpt11_fck", "gpt11_fck"),
+       DT_CLK(NULL, "core_96m_fck", "core_96m_fck"),
+       DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"),
+       DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"),
+       DT_CLK(NULL, "i2c3_fck", "i2c3_fck"),
+       DT_CLK(NULL, "i2c2_fck", "i2c2_fck"),
+       DT_CLK(NULL, "i2c1_fck", "i2c1_fck"),
+       DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
+       DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
+       DT_CLK(NULL, "core_48m_fck", "core_48m_fck"),
+       DT_CLK(NULL, "mcspi4_fck", "mcspi4_fck"),
+       DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"),
+       DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"),
+       DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"),
+       DT_CLK(NULL, "uart2_fck", "uart2_fck"),
+       DT_CLK(NULL, "uart1_fck", "uart1_fck"),
+       DT_CLK(NULL, "core_12m_fck", "core_12m_fck"),
+       DT_CLK("omap_hdq.0", "fck", "hdq_fck"),
+       DT_CLK(NULL, "hdq_fck", "hdq_fck"),
+       DT_CLK(NULL, "core_l3_ick", "core_l3_ick"),
+       DT_CLK(NULL, "sdrc_ick", "sdrc_ick"),
+       DT_CLK(NULL, "gpmc_fck", "gpmc_fck"),
+       DT_CLK(NULL, "core_l4_ick", "core_l4_ick"),
+       DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"),
+       DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"),
+       DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"),
+       DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"),
+       DT_CLK("omap_hdq.0", "ick", "hdq_ick"),
+       DT_CLK(NULL, "hdq_ick", "hdq_ick"),
+       DT_CLK("omap2_mcspi.4", "ick", "mcspi4_ick"),
+       DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"),
+       DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"),
+       DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"),
+       DT_CLK(NULL, "mcspi4_ick", "mcspi4_ick"),
+       DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"),
+       DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"),
+       DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"),
+       DT_CLK("omap_i2c.3", "ick", "i2c3_ick"),
+       DT_CLK("omap_i2c.2", "ick", "i2c2_ick"),
+       DT_CLK("omap_i2c.1", "ick", "i2c1_ick"),
+       DT_CLK(NULL, "i2c3_ick", "i2c3_ick"),
+       DT_CLK(NULL, "i2c2_ick", "i2c2_ick"),
+       DT_CLK(NULL, "i2c1_ick", "i2c1_ick"),
+       DT_CLK(NULL, "uart2_ick", "uart2_ick"),
+       DT_CLK(NULL, "uart1_ick", "uart1_ick"),
+       DT_CLK(NULL, "gpt11_ick", "gpt11_ick"),
+       DT_CLK(NULL, "gpt10_ick", "gpt10_ick"),
+       DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"),
+       DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"),
+       DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
+       DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
+       DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"),
+       DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"),
+       DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"),
+       DT_CLK(NULL, "dss2_alwon_fck", "dss2_alwon_fck"),
+       DT_CLK(NULL, "utmi_p1_gfclk", "dummy_ck"),
+       DT_CLK(NULL, "utmi_p2_gfclk", "dummy_ck"),
+       DT_CLK(NULL, "xclk60mhsp1_ck", "dummy_ck"),
+       DT_CLK(NULL, "xclk60mhsp2_ck", "dummy_ck"),
+       DT_CLK(NULL, "init_60m_fclk", "dummy_ck"),
+       DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
+       DT_CLK(NULL, "aes2_ick", "aes2_ick"),
+       DT_CLK(NULL, "wkup_32k_fck", "wkup_32k_fck"),
+       DT_CLK(NULL, "gpio1_dbck", "gpio1_dbck"),
+       DT_CLK(NULL, "sha12_ick", "sha12_ick"),
+       DT_CLK(NULL, "wdt2_fck", "wdt2_fck"),
+       DT_CLK("omap_wdt", "ick", "wdt2_ick"),
+       DT_CLK(NULL, "wdt2_ick", "wdt2_ick"),
+       DT_CLK(NULL, "wdt1_ick", "wdt1_ick"),
+       DT_CLK(NULL, "gpio1_ick", "gpio1_ick"),
+       DT_CLK(NULL, "omap_32ksync_ick", "omap_32ksync_ick"),
+       DT_CLK(NULL, "gpt12_ick", "gpt12_ick"),
+       DT_CLK(NULL, "gpt1_ick", "gpt1_ick"),
+       DT_CLK(NULL, "per_96m_fck", "per_96m_fck"),
+       DT_CLK(NULL, "per_48m_fck", "per_48m_fck"),
+       DT_CLK(NULL, "uart3_fck", "uart3_fck"),
+       DT_CLK(NULL, "gpt2_fck", "gpt2_fck"),
+       DT_CLK(NULL, "gpt3_fck", "gpt3_fck"),
+       DT_CLK(NULL, "gpt4_fck", "gpt4_fck"),
+       DT_CLK(NULL, "gpt5_fck", "gpt5_fck"),
+       DT_CLK(NULL, "gpt6_fck", "gpt6_fck"),
+       DT_CLK(NULL, "gpt7_fck", "gpt7_fck"),
+       DT_CLK(NULL, "gpt8_fck", "gpt8_fck"),
+       DT_CLK(NULL, "gpt9_fck", "gpt9_fck"),
+       DT_CLK(NULL, "per_32k_alwon_fck", "per_32k_alwon_fck"),
+       DT_CLK(NULL, "gpio6_dbck", "gpio6_dbck"),
+       DT_CLK(NULL, "gpio5_dbck", "gpio5_dbck"),
+       DT_CLK(NULL, "gpio4_dbck", "gpio4_dbck"),
+       DT_CLK(NULL, "gpio3_dbck", "gpio3_dbck"),
+       DT_CLK(NULL, "gpio2_dbck", "gpio2_dbck"),
+       DT_CLK(NULL, "wdt3_fck", "wdt3_fck"),
+       DT_CLK(NULL, "per_l4_ick", "per_l4_ick"),
+       DT_CLK(NULL, "gpio6_ick", "gpio6_ick"),
+       DT_CLK(NULL, "gpio5_ick", "gpio5_ick"),
+       DT_CLK(NULL, "gpio4_ick", "gpio4_ick"),
+       DT_CLK(NULL, "gpio3_ick", "gpio3_ick"),
+       DT_CLK(NULL, "gpio2_ick", "gpio2_ick"),
+       DT_CLK(NULL, "wdt3_ick", "wdt3_ick"),
+       DT_CLK(NULL, "uart3_ick", "uart3_ick"),
+       DT_CLK(NULL, "uart4_ick", "uart4_ick"),
+       DT_CLK(NULL, "gpt9_ick", "gpt9_ick"),
+       DT_CLK(NULL, "gpt8_ick", "gpt8_ick"),
+       DT_CLK(NULL, "gpt7_ick", "gpt7_ick"),
+       DT_CLK(NULL, "gpt6_ick", "gpt6_ick"),
+       DT_CLK(NULL, "gpt5_ick", "gpt5_ick"),
+       DT_CLK(NULL, "gpt4_ick", "gpt4_ick"),
+       DT_CLK(NULL, "gpt3_ick", "gpt3_ick"),
+       DT_CLK(NULL, "gpt2_ick", "gpt2_ick"),
+       DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"),
+       DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"),
+       DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp4_ick", "mcbsp2_ick"),
+       DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"),
+       DT_CLK(NULL, "mcbsp2_ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"),
+       DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"),
+       DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"),
+       DT_CLK("etb", "emu_src_ck", "emu_src_ck"),
+       DT_CLK(NULL, "emu_src_ck", "emu_src_ck"),
+       DT_CLK(NULL, "pclk_fck", "pclk_fck"),
+       DT_CLK(NULL, "pclkx2_fck", "pclkx2_fck"),
+       DT_CLK(NULL, "atclk_fck", "atclk_fck"),
+       DT_CLK(NULL, "traceclk_src_fck", "traceclk_src_fck"),
+       DT_CLK(NULL, "traceclk_fck", "traceclk_fck"),
+       DT_CLK(NULL, "secure_32k_fck", "secure_32k_fck"),
+       DT_CLK(NULL, "gpt12_fck", "gpt12_fck"),
+       DT_CLK(NULL, "wdt1_fck", "wdt1_fck"),
+       DT_CLK(NULL, "timer_32k_ck", "omap_32k_fck"),
+       DT_CLK(NULL, "timer_sys_ck", "sys_ck"),
+       DT_CLK(NULL, "cpufreq_ck", "dpll1_ck"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap34xx_omap36xx_clks[] = {
+       DT_CLK(NULL, "aes1_ick", "aes1_ick"),
+       DT_CLK("omap_rng", "ick", "rng_ick"),
+       DT_CLK("omap3-rom-rng", "ick", "rng_ick"),
+       DT_CLK(NULL, "sha11_ick", "sha11_ick"),
+       DT_CLK(NULL, "des1_ick", "des1_ick"),
+       DT_CLK(NULL, "cam_mclk", "cam_mclk"),
+       DT_CLK(NULL, "cam_ick", "cam_ick"),
+       DT_CLK(NULL, "csi2_96m_fck", "csi2_96m_fck"),
+       DT_CLK(NULL, "security_l3_ick", "security_l3_ick"),
+       DT_CLK(NULL, "pka_ick", "pka_ick"),
+       DT_CLK(NULL, "icr_ick", "icr_ick"),
+       DT_CLK("omap-aes", "ick", "aes2_ick"),
+       DT_CLK("omap-sham", "ick", "sha12_ick"),
+       DT_CLK(NULL, "des2_ick", "des2_ick"),
+       DT_CLK(NULL, "mspro_ick", "mspro_ick"),
+       DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"),
+       DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"),
+       DT_CLK(NULL, "sr1_fck", "sr1_fck"),
+       DT_CLK(NULL, "sr2_fck", "sr2_fck"),
+       DT_CLK(NULL, "sr_l4_ick", "sr_l4_ick"),
+       DT_CLK(NULL, "security_l4_ick2", "security_l4_ick2"),
+       DT_CLK(NULL, "wkup_l4_ick", "wkup_l4_ick"),
+       DT_CLK(NULL, "dpll2_fck", "dpll2_fck"),
+       DT_CLK(NULL, "iva2_ck", "iva2_ck"),
+       DT_CLK(NULL, "modem_fck", "modem_fck"),
+       DT_CLK(NULL, "sad2d_ick", "sad2d_ick"),
+       DT_CLK(NULL, "mad2d_ick", "mad2d_ick"),
+       DT_CLK(NULL, "mspro_fck", "mspro_fck"),
+       DT_CLK(NULL, "dpll2_ck", "dpll2_ck"),
+       DT_CLK(NULL, "dpll2_m2_ck", "dpll2_m2_ck"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap36xx_omap3430es2plus_clks[] = {
+       DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es2"),
+       DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es2"),
+       DT_CLK("musb-omap2430", "ick", "hsotgusb_ick_3430es2"),
+       DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es2"),
+       DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es2"),
+       DT_CLK(NULL, "usim_fck", "usim_fck"),
+       DT_CLK(NULL, "usim_ick", "usim_ick"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap3430es1_clks[] = {
+       DT_CLK(NULL, "gfx_l3_ck", "gfx_l3_ck"),
+       DT_CLK(NULL, "gfx_l3_fck", "gfx_l3_fck"),
+       DT_CLK(NULL, "gfx_l3_ick", "gfx_l3_ick"),
+       DT_CLK(NULL, "gfx_cg1_ck", "gfx_cg1_ck"),
+       DT_CLK(NULL, "gfx_cg2_ck", "gfx_cg2_ck"),
+       DT_CLK(NULL, "d2d_26m_fck", "d2d_26m_fck"),
+       DT_CLK(NULL, "fshostusb_fck", "fshostusb_fck"),
+       DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es1"),
+       DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es1"),
+       DT_CLK("musb-omap2430", "ick", "hsotgusb_ick_3430es1"),
+       DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es1"),
+       DT_CLK(NULL, "fac_ick", "fac_ick"),
+       DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es1"),
+       DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"),
+       DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es1"),
+       DT_CLK("omapdss_dss", "ick", "dss_ick_3430es1"),
+       DT_CLK(NULL, "dss_ick", "dss_ick_3430es1"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap36xx_am35xx_omap3430es2plus_clks[] = {
+       DT_CLK(NULL, "virt_16_8m_ck", "virt_16_8m_ck"),
+       DT_CLK(NULL, "dpll5_ck", "dpll5_ck"),
+       DT_CLK(NULL, "dpll5_m2_ck", "dpll5_m2_ck"),
+       DT_CLK(NULL, "sgx_fck", "sgx_fck"),
+       DT_CLK(NULL, "sgx_ick", "sgx_ick"),
+       DT_CLK(NULL, "cpefuse_fck", "cpefuse_fck"),
+       DT_CLK(NULL, "ts_fck", "ts_fck"),
+       DT_CLK(NULL, "usbtll_fck", "usbtll_fck"),
+       DT_CLK(NULL, "usbtll_ick", "usbtll_ick"),
+       DT_CLK("omap_hsmmc.2", "ick", "mmchs3_ick"),
+       DT_CLK(NULL, "mmchs3_ick", "mmchs3_ick"),
+       DT_CLK(NULL, "mmchs3_fck", "mmchs3_fck"),
+       DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es2"),
+       DT_CLK("omapdss_dss", "ick", "dss_ick_3430es2"),
+       DT_CLK(NULL, "dss_ick", "dss_ick_3430es2"),
+       DT_CLK(NULL, "usbhost_120m_fck", "usbhost_120m_fck"),
+       DT_CLK(NULL, "usbhost_48m_fck", "usbhost_48m_fck"),
+       DT_CLK(NULL, "usbhost_ick", "usbhost_ick"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk am35xx_clks[] = {
+       DT_CLK(NULL, "ipss_ick", "ipss_ick"),
+       DT_CLK(NULL, "rmii_ck", "rmii_ck"),
+       DT_CLK(NULL, "pclk_ck", "pclk_ck"),
+       DT_CLK(NULL, "emac_ick", "emac_ick"),
+       DT_CLK(NULL, "emac_fck", "emac_fck"),
+       DT_CLK("davinci_emac.0", NULL, "emac_ick"),
+       DT_CLK("davinci_mdio.0", NULL, "emac_fck"),
+       DT_CLK("vpfe-capture", "master", "vpfe_ick"),
+       DT_CLK("vpfe-capture", "slave", "vpfe_fck"),
+       DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_am35xx"),
+       DT_CLK(NULL, "hsotgusb_fck", "hsotgusb_fck_am35xx"),
+       DT_CLK(NULL, "hecc_ck", "hecc_ck"),
+       DT_CLK(NULL, "uart4_ick", "uart4_ick_am35xx"),
+       DT_CLK(NULL, "uart4_fck", "uart4_fck_am35xx"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap36xx_clks[] = {
+       DT_CLK(NULL, "omap_192m_alwon_fck", "omap_192m_alwon_fck"),
+       DT_CLK(NULL, "uart4_fck", "uart4_fck"),
+       { .node_name = NULL },
+};
+
+static const char *enable_init_clks[] = {
+       "sdrc_ick",
+       "gpmc_fck",
+       "omapctrl_ick",
+};
+
+enum {
+       OMAP3_SOC_AM35XX,
+       OMAP3_SOC_OMAP3430_ES1,
+       OMAP3_SOC_OMAP3430_ES2_PLUS,
+       OMAP3_SOC_OMAP3630,
+       OMAP3_SOC_TI81XX,
+};
+
+static int __init omap3xxx_dt_clk_init(int soc_type)
+{
+       if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 ||
+           soc_type == OMAP3_SOC_OMAP3430_ES1 ||
+           soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS)
+               ti_dt_clocks_register(omap3xxx_clks);
+
+       if (soc_type == OMAP3_SOC_AM35XX)
+               ti_dt_clocks_register(am35xx_clks);
+
+       if (soc_type == OMAP3_SOC_OMAP3630 || soc_type == OMAP3_SOC_AM35XX ||
+           soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS)
+               ti_dt_clocks_register(omap36xx_am35xx_omap3430es2plus_clks);
+
+       if (soc_type == OMAP3_SOC_OMAP3430_ES1)
+               ti_dt_clocks_register(omap3430es1_clks);
+
+       if (soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS ||
+           soc_type == OMAP3_SOC_OMAP3630)
+               ti_dt_clocks_register(omap36xx_omap3430es2plus_clks);
+
+       if (soc_type == OMAP3_SOC_OMAP3430_ES1 ||
+           soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS ||
+           soc_type == OMAP3_SOC_OMAP3630)
+               ti_dt_clocks_register(omap34xx_omap36xx_clks);
+
+       if (soc_type == OMAP3_SOC_OMAP3630)
+               ti_dt_clocks_register(omap36xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       omap2_clk_enable_init_clocks(enable_init_clks,
+                                    ARRAY_SIZE(enable_init_clks));
+
+       pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+               (clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 1000000),
+               (clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 100000) % 10,
+               (clk_get_rate(clk_get_sys(NULL, "core_ck")) / 1000000),
+               (clk_get_rate(clk_get_sys(NULL, "arm_fck")) / 1000000));
+
+       if (soc_type != OMAP3_SOC_TI81XX && soc_type != OMAP3_SOC_OMAP3430_ES1)
+               omap3_clk_lock_dpll5();
+
+       return 0;
+}
+
+int __init omap3430_dt_clk_init(void)
+{
+       return omap3xxx_dt_clk_init(OMAP3_SOC_OMAP3430_ES2_PLUS);
+}
+
+int __init omap3630_dt_clk_init(void)
+{
+       return omap3xxx_dt_clk_init(OMAP3_SOC_OMAP3630);
+}
+
+int __init am35xx_dt_clk_init(void)
+{
+       return omap3xxx_dt_clk_init(OMAP3_SOC_AM35XX);
+}
+
+int __init ti81xx_dt_clk_init(void)
+{
+       return omap3xxx_dt_clk_init(OMAP3_SOC_TI81XX);
+}
diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c
new file mode 100644 (file)
index 0000000..67c8de5
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * AM43XX Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc
+ *     Tero Kristo (t-kristo@ti.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
+
+static struct ti_dt_clk am43xx_clks[] = {
+       DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
+       DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_24000000_ck", "virt_24000000_ck"),
+       DT_CLK(NULL, "virt_25000000_ck", "virt_25000000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"),
+       DT_CLK(NULL, "tclkin_ck", "tclkin_ck"),
+       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
+       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
+       DT_CLK(NULL, "dpll_core_m4_ck", "dpll_core_m4_ck"),
+       DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"),
+       DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"),
+       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
+       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
+       DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"),
+       DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"),
+       DT_CLK(NULL, "dpll_disp_ck", "dpll_disp_ck"),
+       DT_CLK(NULL, "dpll_disp_m2_ck", "dpll_disp_m2_ck"),
+       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
+       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
+       DT_CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", "dpll_per_m2_div4_wkupdm_ck"),
+       DT_CLK(NULL, "dpll_per_m2_div4_ck", "dpll_per_m2_div4_ck"),
+       DT_CLK(NULL, "adc_tsc_fck", "adc_tsc_fck"),
+       DT_CLK(NULL, "clkdiv32k_ck", "clkdiv32k_ck"),
+       DT_CLK(NULL, "clkdiv32k_ick", "clkdiv32k_ick"),
+       DT_CLK(NULL, "dcan0_fck", "dcan0_fck"),
+       DT_CLK(NULL, "dcan1_fck", "dcan1_fck"),
+       DT_CLK(NULL, "pruss_ocp_gclk", "pruss_ocp_gclk"),
+       DT_CLK(NULL, "mcasp0_fck", "mcasp0_fck"),
+       DT_CLK(NULL, "mcasp1_fck", "mcasp1_fck"),
+       DT_CLK(NULL, "smartreflex0_fck", "smartreflex0_fck"),
+       DT_CLK(NULL, "smartreflex1_fck", "smartreflex1_fck"),
+       DT_CLK(NULL, "sha0_fck", "sha0_fck"),
+       DT_CLK(NULL, "aes0_fck", "aes0_fck"),
+       DT_CLK(NULL, "timer1_fck", "timer1_fck"),
+       DT_CLK(NULL, "timer2_fck", "timer2_fck"),
+       DT_CLK(NULL, "timer3_fck", "timer3_fck"),
+       DT_CLK(NULL, "timer4_fck", "timer4_fck"),
+       DT_CLK(NULL, "timer5_fck", "timer5_fck"),
+       DT_CLK(NULL, "timer6_fck", "timer6_fck"),
+       DT_CLK(NULL, "timer7_fck", "timer7_fck"),
+       DT_CLK(NULL, "wdt1_fck", "wdt1_fck"),
+       DT_CLK(NULL, "l3_gclk", "l3_gclk"),
+       DT_CLK(NULL, "dpll_core_m4_div2_ck", "dpll_core_m4_div2_ck"),
+       DT_CLK(NULL, "l4hs_gclk", "l4hs_gclk"),
+       DT_CLK(NULL, "l3s_gclk", "l3s_gclk"),
+       DT_CLK(NULL, "l4ls_gclk", "l4ls_gclk"),
+       DT_CLK(NULL, "clk_24mhz", "clk_24mhz"),
+       DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"),
+       DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"),
+       DT_CLK(NULL, "gpio0_dbclk_mux_ck", "gpio0_dbclk_mux_ck"),
+       DT_CLK(NULL, "gpio0_dbclk", "gpio0_dbclk"),
+       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
+       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
+       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
+       DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
+       DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
+       DT_CLK(NULL, "mmc_clk", "mmc_clk"),
+       DT_CLK(NULL, "gfx_fclk_clksel_ck", "gfx_fclk_clksel_ck"),
+       DT_CLK(NULL, "gfx_fck_div_ck", "gfx_fck_div_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "clkdiv32k_ick"),
+       DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK(NULL, "sysclk_div", "sysclk_div"),
+       DT_CLK(NULL, "disp_clk", "disp_clk"),
+       DT_CLK(NULL, "clk_32k_mosc_ck", "clk_32k_mosc_ck"),
+       DT_CLK(NULL, "clk_32k_tpm_ck", "clk_32k_tpm_ck"),
+       DT_CLK(NULL, "dpll_extdev_ck", "dpll_extdev_ck"),
+       DT_CLK(NULL, "dpll_extdev_m2_ck", "dpll_extdev_m2_ck"),
+       DT_CLK(NULL, "mux_synctimer32k_ck", "mux_synctimer32k_ck"),
+       DT_CLK(NULL, "synctimer_32kclk", "synctimer_32kclk"),
+       DT_CLK(NULL, "timer8_fck", "timer8_fck"),
+       DT_CLK(NULL, "timer9_fck", "timer9_fck"),
+       DT_CLK(NULL, "timer10_fck", "timer10_fck"),
+       DT_CLK(NULL, "timer11_fck", "timer11_fck"),
+       DT_CLK(NULL, "cpsw_50m_clkdiv", "cpsw_50m_clkdiv"),
+       DT_CLK(NULL, "cpsw_5m_clkdiv", "cpsw_5m_clkdiv"),
+       DT_CLK(NULL, "dpll_ddr_x2_ck", "dpll_ddr_x2_ck"),
+       DT_CLK(NULL, "dpll_ddr_m4_ck", "dpll_ddr_m4_ck"),
+       DT_CLK(NULL, "dpll_per_clkdcoldo", "dpll_per_clkdcoldo"),
+       DT_CLK(NULL, "dll_aging_clk_div", "dll_aging_clk_div"),
+       DT_CLK(NULL, "div_core_25m_ck", "div_core_25m_ck"),
+       DT_CLK(NULL, "func_12m_clk", "func_12m_clk"),
+       DT_CLK(NULL, "vtp_clk_div", "vtp_clk_div"),
+       DT_CLK(NULL, "usbphy_32khz_clkmux", "usbphy_32khz_clkmux"),
+       { .node_name = NULL },
+};
+
+int __init am43xx_dt_clk_init(void)
+{
+       ti_dt_clocks_register(am43xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       return 0;
+}
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
new file mode 100644 (file)
index 0000000..ae00218
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * OMAP4 Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo (t-kristo@ti.com)
+ *
+ * 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/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/clk/ti.h>
+
+/*
+ * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
+ * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
+ * must be set to 196.608 MHz" and hence, the DPLL locked frequency is
+ * half of this value.
+ */
+#define OMAP4_DPLL_ABE_DEFFREQ                         98304000
+
+/*
+ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
+ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
+ * locked frequency for the USB DPLL is 960MHz.
+ */
+#define OMAP4_DPLL_USB_DEFFREQ                         960000000
+
+static struct ti_dt_clk omap44xx_clks[] = {
+       DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
+       DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
+       DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"),
+       DT_CLK(NULL, "pad_slimbus_core_clks_ck", "pad_slimbus_core_clks_ck"),
+       DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"),
+       DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"),
+       DT_CLK(NULL, "slimbus_clk", "slimbus_clk"),
+       DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+       DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"),
+       DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"),
+       DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"),
+       DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"),
+       DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"),
+       DT_CLK(NULL, "tie_low_clock_ck", "tie_low_clock_ck"),
+       DT_CLK(NULL, "utmi_phy_clkout_ck", "utmi_phy_clkout_ck"),
+       DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"),
+       DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"),
+       DT_CLK(NULL, "xclk60motg_ck", "xclk60motg_ck"),
+       DT_CLK(NULL, "abe_dpll_bypass_clk_mux_ck", "abe_dpll_bypass_clk_mux_ck"),
+       DT_CLK(NULL, "abe_dpll_refclk_mux_ck", "abe_dpll_refclk_mux_ck"),
+       DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"),
+       DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"),
+       DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"),
+       DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"),
+       DT_CLK(NULL, "abe_clk", "abe_clk"),
+       DT_CLK(NULL, "aess_fclk", "aess_fclk"),
+       DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"),
+       DT_CLK(NULL, "core_hsd_byp_clk_mux_ck", "core_hsd_byp_clk_mux_ck"),
+       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
+       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
+       DT_CLK(NULL, "dpll_core_m6x2_ck", "dpll_core_m6x2_ck"),
+       DT_CLK(NULL, "dbgclk_mux_ck", "dbgclk_mux_ck"),
+       DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"),
+       DT_CLK(NULL, "ddrphy_ck", "ddrphy_ck"),
+       DT_CLK(NULL, "dpll_core_m5x2_ck", "dpll_core_m5x2_ck"),
+       DT_CLK(NULL, "div_core_ck", "div_core_ck"),
+       DT_CLK(NULL, "div_iva_hs_clk", "div_iva_hs_clk"),
+       DT_CLK(NULL, "div_mpu_hs_clk", "div_mpu_hs_clk"),
+       DT_CLK(NULL, "dpll_core_m4x2_ck", "dpll_core_m4x2_ck"),
+       DT_CLK(NULL, "dll_clk_div_ck", "dll_clk_div_ck"),
+       DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"),
+       DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"),
+       DT_CLK(NULL, "dpll_core_m7x2_ck", "dpll_core_m7x2_ck"),
+       DT_CLK(NULL, "iva_hsd_byp_clk_mux_ck", "iva_hsd_byp_clk_mux_ck"),
+       DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"),
+       DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"),
+       DT_CLK(NULL, "dpll_iva_m4x2_ck", "dpll_iva_m4x2_ck"),
+       DT_CLK(NULL, "dpll_iva_m5x2_ck", "dpll_iva_m5x2_ck"),
+       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
+       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
+       DT_CLK(NULL, "per_hs_clk_div_ck", "per_hs_clk_div_ck"),
+       DT_CLK(NULL, "per_hsd_byp_clk_mux_ck", "per_hsd_byp_clk_mux_ck"),
+       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
+       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
+       DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"),
+       DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"),
+       DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"),
+       DT_CLK(NULL, "dpll_per_m4x2_ck", "dpll_per_m4x2_ck"),
+       DT_CLK(NULL, "dpll_per_m5x2_ck", "dpll_per_m5x2_ck"),
+       DT_CLK(NULL, "dpll_per_m6x2_ck", "dpll_per_m6x2_ck"),
+       DT_CLK(NULL, "dpll_per_m7x2_ck", "dpll_per_m7x2_ck"),
+       DT_CLK(NULL, "usb_hs_clk_div_ck", "usb_hs_clk_div_ck"),
+       DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"),
+       DT_CLK(NULL, "dpll_usb_clkdcoldo_ck", "dpll_usb_clkdcoldo_ck"),
+       DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"),
+       DT_CLK(NULL, "ducati_clk_mux_ck", "ducati_clk_mux_ck"),
+       DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"),
+       DT_CLK(NULL, "func_24m_clk", "func_24m_clk"),
+       DT_CLK(NULL, "func_24mc_fclk", "func_24mc_fclk"),
+       DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"),
+       DT_CLK(NULL, "func_48mc_fclk", "func_48mc_fclk"),
+       DT_CLK(NULL, "func_64m_fclk", "func_64m_fclk"),
+       DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"),
+       DT_CLK(NULL, "init_60m_fclk", "init_60m_fclk"),
+       DT_CLK(NULL, "l3_div_ck", "l3_div_ck"),
+       DT_CLK(NULL, "l4_div_ck", "l4_div_ck"),
+       DT_CLK(NULL, "lp_clk_div_ck", "lp_clk_div_ck"),
+       DT_CLK(NULL, "l4_wkup_clk_mux_ck", "l4_wkup_clk_mux_ck"),
+       DT_CLK("smp_twd", NULL, "mpu_periphclk"),
+       DT_CLK(NULL, "ocp_abe_iclk", "ocp_abe_iclk"),
+       DT_CLK(NULL, "per_abe_24m_fclk", "per_abe_24m_fclk"),
+       DT_CLK(NULL, "per_abe_nc_fclk", "per_abe_nc_fclk"),
+       DT_CLK(NULL, "syc_clk_div_ck", "syc_clk_div_ck"),
+       DT_CLK(NULL, "aes1_fck", "aes1_fck"),
+       DT_CLK(NULL, "aes2_fck", "aes2_fck"),
+       DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"),
+       DT_CLK(NULL, "func_dmic_abe_gfclk", "func_dmic_abe_gfclk"),
+       DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"),
+       DT_CLK(NULL, "dss_tv_clk", "dss_tv_clk"),
+       DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"),
+       DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"),
+       DT_CLK(NULL, "dss_fck", "dss_fck"),
+       DT_CLK("omapdss_dss", "ick", "dss_fck"),
+       DT_CLK(NULL, "fdif_fck", "fdif_fck"),
+       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
+       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
+       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
+       DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
+       DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
+       DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"),
+       DT_CLK(NULL, "sgx_clk_mux", "sgx_clk_mux"),
+       DT_CLK(NULL, "hsi_fck", "hsi_fck"),
+       DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"),
+       DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"),
+       DT_CLK(NULL, "func_mcasp_abe_gfclk", "func_mcasp_abe_gfclk"),
+       DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"),
+       DT_CLK(NULL, "func_mcbsp1_gfclk", "func_mcbsp1_gfclk"),
+       DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"),
+       DT_CLK(NULL, "func_mcbsp2_gfclk", "func_mcbsp2_gfclk"),
+       DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"),
+       DT_CLK(NULL, "func_mcbsp3_gfclk", "func_mcbsp3_gfclk"),
+       DT_CLK(NULL, "mcbsp4_sync_mux_ck", "mcbsp4_sync_mux_ck"),
+       DT_CLK(NULL, "per_mcbsp4_gfclk", "per_mcbsp4_gfclk"),
+       DT_CLK(NULL, "hsmmc1_fclk", "hsmmc1_fclk"),
+       DT_CLK(NULL, "hsmmc2_fclk", "hsmmc2_fclk"),
+       DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "ocp2scp_usb_phy_phy_48m"),
+       DT_CLK(NULL, "sha2md5_fck", "sha2md5_fck"),
+       DT_CLK(NULL, "slimbus1_fclk_1", "slimbus1_fclk_1"),
+       DT_CLK(NULL, "slimbus1_fclk_0", "slimbus1_fclk_0"),
+       DT_CLK(NULL, "slimbus1_fclk_2", "slimbus1_fclk_2"),
+       DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"),
+       DT_CLK(NULL, "slimbus2_fclk_1", "slimbus2_fclk_1"),
+       DT_CLK(NULL, "slimbus2_fclk_0", "slimbus2_fclk_0"),
+       DT_CLK(NULL, "slimbus2_slimbus_clk", "slimbus2_slimbus_clk"),
+       DT_CLK(NULL, "smartreflex_core_fck", "smartreflex_core_fck"),
+       DT_CLK(NULL, "smartreflex_iva_fck", "smartreflex_iva_fck"),
+       DT_CLK(NULL, "smartreflex_mpu_fck", "smartreflex_mpu_fck"),
+       DT_CLK(NULL, "dmt1_clk_mux", "dmt1_clk_mux"),
+       DT_CLK(NULL, "cm2_dm10_mux", "cm2_dm10_mux"),
+       DT_CLK(NULL, "cm2_dm11_mux", "cm2_dm11_mux"),
+       DT_CLK(NULL, "cm2_dm2_mux", "cm2_dm2_mux"),
+       DT_CLK(NULL, "cm2_dm3_mux", "cm2_dm3_mux"),
+       DT_CLK(NULL, "cm2_dm4_mux", "cm2_dm4_mux"),
+       DT_CLK(NULL, "timer5_sync_mux", "timer5_sync_mux"),
+       DT_CLK(NULL, "timer6_sync_mux", "timer6_sync_mux"),
+       DT_CLK(NULL, "timer7_sync_mux", "timer7_sync_mux"),
+       DT_CLK(NULL, "timer8_sync_mux", "timer8_sync_mux"),
+       DT_CLK(NULL, "cm2_dm9_mux", "cm2_dm9_mux"),
+       DT_CLK(NULL, "usb_host_fs_fck", "usb_host_fs_fck"),
+       DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
+       DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"),
+       DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_func48mclk", "usb_host_hs_func48mclk"),
+       DT_CLK(NULL, "usb_host_hs_fck", "usb_host_hs_fck"),
+       DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
+       DT_CLK(NULL, "otg_60m_gfclk", "otg_60m_gfclk"),
+       DT_CLK(NULL, "usb_otg_hs_xclk", "usb_otg_hs_xclk"),
+       DT_CLK(NULL, "usb_otg_hs_ick", "usb_otg_hs_ick"),
+       DT_CLK("musb-omap2430", "ick", "usb_otg_hs_ick"),
+       DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"),
+       DT_CLK(NULL, "usb_tll_hs_ick", "usb_tll_hs_ick"),
+       DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
+       DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
+       DT_CLK(NULL, "usim_ck", "usim_ck"),
+       DT_CLK(NULL, "usim_fclk", "usim_fclk"),
+       DT_CLK(NULL, "pmd_stm_clock_mux_ck", "pmd_stm_clock_mux_ck"),
+       DT_CLK(NULL, "pmd_trace_clk_mux_ck", "pmd_trace_clk_mux_ck"),
+       DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"),
+       DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"),
+       DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"),
+       DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"),
+       DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"),
+       DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"),
+       DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"),
+       DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"),
+       DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"),
+       DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"),
+       DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"),
+       DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"),
+       DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"),
+       DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"),
+       DT_CLK(NULL, "auxclk4_src_ck", "auxclk4_src_ck"),
+       DT_CLK(NULL, "auxclk4_ck", "auxclk4_ck"),
+       DT_CLK(NULL, "auxclkreq4_ck", "auxclkreq4_ck"),
+       DT_CLK(NULL, "auxclk5_src_ck", "auxclk5_src_ck"),
+       DT_CLK(NULL, "auxclk5_ck", "auxclk5_ck"),
+       DT_CLK(NULL, "auxclkreq5_ck", "auxclkreq5_ck"),
+       DT_CLK("50000000.gpmc", "fck", "dummy_ck"),
+       DT_CLK("omap_i2c.1", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.2", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.3", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "mailboxes_ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.0", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.1", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.2", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.3", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.4", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.1", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.2", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.3", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.4", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.1", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.2", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.3", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "uart1_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart2_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart3_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart4_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbhost_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
+       DT_CLK("usbhs_tll", "usbtll_fck", "dummy_ck"),
+       DT_CLK("omap_wdt", "ick", "dummy_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
+       DT_CLK("omap_timer.1", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.2", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.3", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.4", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.9", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.10", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.11", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("omap_timer.5", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("omap_timer.6", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("omap_timer.7", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("omap_timer.8", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("4a318000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin_ck"),
+       DT_CLK("40138000.timer", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("4013a000.timer", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("4013c000.timer", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK("4013e000.timer", "timer_sys_ck", "syc_clk_div_ck"),
+       DT_CLK(NULL, "cpufreq_ck", "dpll_mpu_ck"),
+       DT_CLK(NULL, "bandgap_fclk", "bandgap_fclk"),
+       DT_CLK(NULL, "div_ts_ck", "div_ts_ck"),
+       DT_CLK(NULL, "bandgap_ts_fclk", "bandgap_ts_fclk"),
+       { .node_name = NULL },
+};
+
+int __init omap4xxx_dt_clk_init(void)
+{
+       int rc;
+       struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
+
+       ti_dt_clocks_register(omap44xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       /*
+        * Lock USB DPLL on OMAP4 devices so that the L3INIT power
+        * domain can transition to retention state when not in use.
+        */
+       usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
+       rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+       /*
+        * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
+        * state when turning the ABE clock domain. Workaround this by
+        * locking the ABE DPLL on boot.
+        * Lock the ABE DPLL in any case to avoid issues with audio.
+        */
+       abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck");
+       sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
+       rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
+       abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
+       if (!rc)
+               rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
+
+       return 0;
+}
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
new file mode 100644 (file)
index 0000000..0ef9f58
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * OMAP5 Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo (t-kristo@ti.com)
+ *
+ * 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/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk/ti.h>
+
+#define OMAP5_DPLL_ABE_DEFFREQ                         98304000
+
+/*
+ * OMAP543x TRM, section "3.6.3.9.5 DPLL_USB Preferred Settings"
+ * states it must be at 960MHz
+ */
+#define OMAP5_DPLL_USB_DEFFREQ                         960000000
+
+static struct ti_dt_clk omap54xx_clks[] = {
+       DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
+       DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"),
+       DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"),
+       DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"),
+       DT_CLK(NULL, "slimbus_clk", "slimbus_clk"),
+       DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+       DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"),
+       DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"),
+       DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"),
+       DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"),
+       DT_CLK(NULL, "sys_clkin", "sys_clkin"),
+       DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"),
+       DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"),
+       DT_CLK(NULL, "abe_dpll_bypass_clk_mux", "abe_dpll_bypass_clk_mux"),
+       DT_CLK(NULL, "abe_dpll_clk_mux", "abe_dpll_clk_mux"),
+       DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"),
+       DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"),
+       DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"),
+       DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"),
+       DT_CLK(NULL, "abe_clk", "abe_clk"),
+       DT_CLK(NULL, "abe_iclk", "abe_iclk"),
+       DT_CLK(NULL, "abe_lp_clk_div", "abe_lp_clk_div"),
+       DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"),
+       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
+       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
+       DT_CLK(NULL, "dpll_core_h21x2_ck", "dpll_core_h21x2_ck"),
+       DT_CLK(NULL, "c2c_fclk", "c2c_fclk"),
+       DT_CLK(NULL, "c2c_iclk", "c2c_iclk"),
+       DT_CLK(NULL, "custefuse_sys_gfclk_div", "custefuse_sys_gfclk_div"),
+       DT_CLK(NULL, "dpll_core_h11x2_ck", "dpll_core_h11x2_ck"),
+       DT_CLK(NULL, "dpll_core_h12x2_ck", "dpll_core_h12x2_ck"),
+       DT_CLK(NULL, "dpll_core_h13x2_ck", "dpll_core_h13x2_ck"),
+       DT_CLK(NULL, "dpll_core_h14x2_ck", "dpll_core_h14x2_ck"),
+       DT_CLK(NULL, "dpll_core_h22x2_ck", "dpll_core_h22x2_ck"),
+       DT_CLK(NULL, "dpll_core_h23x2_ck", "dpll_core_h23x2_ck"),
+       DT_CLK(NULL, "dpll_core_h24x2_ck", "dpll_core_h24x2_ck"),
+       DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"),
+       DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"),
+       DT_CLK(NULL, "iva_dpll_hs_clk_div", "iva_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"),
+       DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"),
+       DT_CLK(NULL, "dpll_iva_h11x2_ck", "dpll_iva_h11x2_ck"),
+       DT_CLK(NULL, "dpll_iva_h12x2_ck", "dpll_iva_h12x2_ck"),
+       DT_CLK(NULL, "mpu_dpll_hs_clk_div", "mpu_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
+       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
+       DT_CLK(NULL, "per_dpll_hs_clk_div", "per_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
+       DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"),
+       DT_CLK(NULL, "dpll_per_h11x2_ck", "dpll_per_h11x2_ck"),
+       DT_CLK(NULL, "dpll_per_h12x2_ck", "dpll_per_h12x2_ck"),
+       DT_CLK(NULL, "dpll_per_h14x2_ck", "dpll_per_h14x2_ck"),
+       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
+       DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"),
+       DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"),
+       DT_CLK(NULL, "dpll_unipro1_ck", "dpll_unipro1_ck"),
+       DT_CLK(NULL, "dpll_unipro1_clkdcoldo", "dpll_unipro1_clkdcoldo"),
+       DT_CLK(NULL, "dpll_unipro1_m2_ck", "dpll_unipro1_m2_ck"),
+       DT_CLK(NULL, "dpll_unipro2_ck", "dpll_unipro2_ck"),
+       DT_CLK(NULL, "dpll_unipro2_clkdcoldo", "dpll_unipro2_clkdcoldo"),
+       DT_CLK(NULL, "dpll_unipro2_m2_ck", "dpll_unipro2_m2_ck"),
+       DT_CLK(NULL, "usb_dpll_hs_clk_div", "usb_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"),
+       DT_CLK(NULL, "dpll_usb_clkdcoldo", "dpll_usb_clkdcoldo"),
+       DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"),
+       DT_CLK(NULL, "dss_syc_gfclk_div", "dss_syc_gfclk_div"),
+       DT_CLK(NULL, "func_128m_clk", "func_128m_clk"),
+       DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"),
+       DT_CLK(NULL, "func_24m_clk", "func_24m_clk"),
+       DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"),
+       DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"),
+       DT_CLK(NULL, "l3_iclk_div", "l3_iclk_div"),
+       DT_CLK(NULL, "gpu_l3_iclk", "gpu_l3_iclk"),
+       DT_CLK(NULL, "l3init_60m_fclk", "l3init_60m_fclk"),
+       DT_CLK(NULL, "wkupaon_iclk_mux", "wkupaon_iclk_mux"),
+       DT_CLK(NULL, "l3instr_ts_gclk_div", "l3instr_ts_gclk_div"),
+       DT_CLK(NULL, "l4_root_clk_div", "l4_root_clk_div"),
+       DT_CLK(NULL, "dss_32khz_clk", "dss_32khz_clk"),
+       DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"),
+       DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"),
+       DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"),
+       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
+       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
+       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
+       DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
+       DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
+       DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"),
+       DT_CLK(NULL, "gpio7_dbclk", "gpio7_dbclk"),
+       DT_CLK(NULL, "gpio8_dbclk", "gpio8_dbclk"),
+       DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"),
+       DT_CLK(NULL, "lli_txphy_clk", "lli_txphy_clk"),
+       DT_CLK(NULL, "lli_txphy_ls_clk", "lli_txphy_ls_clk"),
+       DT_CLK(NULL, "mmc1_32khz_clk", "mmc1_32khz_clk"),
+       DT_CLK(NULL, "sata_ref_clk", "sata_ref_clk"),
+       DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic480m_p3_clk", "usb_host_hs_hsic480m_p3_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_hsic60m_p3_clk", "usb_host_hs_hsic60m_p3_clk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"),
+       DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"),
+       DT_CLK(NULL, "usb_otg_ss_refclk960m", "usb_otg_ss_refclk960m"),
+       DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"),
+       DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"),
+       DT_CLK(NULL, "aess_fclk", "aess_fclk"),
+       DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"),
+       DT_CLK(NULL, "dmic_gfclk", "dmic_gfclk"),
+       DT_CLK(NULL, "fdif_fclk", "fdif_fclk"),
+       DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"),
+       DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"),
+       DT_CLK(NULL, "hsi_fclk", "hsi_fclk"),
+       DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"),
+       DT_CLK(NULL, "mcasp_gfclk", "mcasp_gfclk"),
+       DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"),
+       DT_CLK(NULL, "mcbsp1_gfclk", "mcbsp1_gfclk"),
+       DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"),
+       DT_CLK(NULL, "mcbsp2_gfclk", "mcbsp2_gfclk"),
+       DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"),
+       DT_CLK(NULL, "mcbsp3_gfclk", "mcbsp3_gfclk"),
+       DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"),
+       DT_CLK(NULL, "mmc1_fclk", "mmc1_fclk"),
+       DT_CLK(NULL, "mmc2_fclk_mux", "mmc2_fclk_mux"),
+       DT_CLK(NULL, "mmc2_fclk", "mmc2_fclk"),
+       DT_CLK(NULL, "timer10_gfclk_mux", "timer10_gfclk_mux"),
+       DT_CLK(NULL, "timer11_gfclk_mux", "timer11_gfclk_mux"),
+       DT_CLK(NULL, "timer1_gfclk_mux", "timer1_gfclk_mux"),
+       DT_CLK(NULL, "timer2_gfclk_mux", "timer2_gfclk_mux"),
+       DT_CLK(NULL, "timer3_gfclk_mux", "timer3_gfclk_mux"),
+       DT_CLK(NULL, "timer4_gfclk_mux", "timer4_gfclk_mux"),
+       DT_CLK(NULL, "timer5_gfclk_mux", "timer5_gfclk_mux"),
+       DT_CLK(NULL, "timer6_gfclk_mux", "timer6_gfclk_mux"),
+       DT_CLK(NULL, "timer7_gfclk_mux", "timer7_gfclk_mux"),
+       DT_CLK(NULL, "timer8_gfclk_mux", "timer8_gfclk_mux"),
+       DT_CLK(NULL, "timer9_gfclk_mux", "timer9_gfclk_mux"),
+       DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"),
+       DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"),
+       DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"),
+       DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"),
+       DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"),
+       DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"),
+       DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"),
+       DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"),
+       DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"),
+       DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"),
+       DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"),
+       DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"),
+       DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"),
+       DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"),
+       DT_CLK(NULL, "gpmc_ck", "dummy_ck"),
+       DT_CLK("omap_i2c.1", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.2", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.3", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "mailboxes_ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.0", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.1", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.2", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.3", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.4", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.1", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.2", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.3", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.4", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.1", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.2", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.3", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "uart1_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart2_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart3_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart4_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbhost_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
+       DT_CLK("omap_wdt", "ick", "dummy_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
+       DT_CLK("omap_timer.1", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.2", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.3", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.4", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.9", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.10", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.11", "sys_ck", "sys_clkin"),
+       DT_CLK("omap_timer.5", "sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("omap_timer.6", "sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("omap_timer.7", "sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("omap_timer.8", "sys_ck", "dss_syc_gfclk_div"),
+       { .node_name = NULL },
+};
+
+int __init omap5xxx_dt_clk_init(void)
+{
+       int rc;
+       struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll;
+
+       ti_dt_clocks_register(omap54xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_clk_mux");
+       sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck");
+       rc = clk_set_parent(abe_dpll_ref, sys_32k_ck);
+       abe_dpll = clk_get_sys(NULL, "dpll_abe_ck");
+       if (!rc)
+               rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
+
+       usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
+       rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
+       usb_dpll = clk_get_sys(NULL, "dpll_usb_m2_ck");
+       rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ/2);
+       if (rc)
+               pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__);
+
+       return 0;
+}
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
new file mode 100644 (file)
index 0000000..9977653
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * DRA7 Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo (t-kristo@ti.com)
+ *
+ * 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/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-private.h>
+#include <linux/clkdev.h>
+#include <linux/clk/ti.h>
+
+#define DRA7_DPLL_ABE_DEFFREQ                          361267200
+#define DRA7_DPLL_GMAC_DEFFREQ                         1000000000
+
+
+static struct ti_dt_clk dra7xx_clks[] = {
+       DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
+       DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
+       DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"),
+       DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"),
+       DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"),
+       DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"),
+       DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"),
+       DT_CLK(NULL, "pciesref_acs_clk_ck", "pciesref_acs_clk_ck"),
+       DT_CLK(NULL, "ref_clkin0_ck", "ref_clkin0_ck"),
+       DT_CLK(NULL, "ref_clkin1_ck", "ref_clkin1_ck"),
+       DT_CLK(NULL, "ref_clkin2_ck", "ref_clkin2_ck"),
+       DT_CLK(NULL, "ref_clkin3_ck", "ref_clkin3_ck"),
+       DT_CLK(NULL, "rmii_clk_ck", "rmii_clk_ck"),
+       DT_CLK(NULL, "sdvenc_clkin_ck", "sdvenc_clkin_ck"),
+       DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"),
+       DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+       DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"),
+       DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"),
+       DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_20000000_ck", "virt_20000000_ck"),
+       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
+       DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"),
+       DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"),
+       DT_CLK(NULL, "sys_clkin1", "sys_clkin1"),
+       DT_CLK(NULL, "sys_clkin2", "sys_clkin2"),
+       DT_CLK(NULL, "usb_otg_clkin_ck", "usb_otg_clkin_ck"),
+       DT_CLK(NULL, "video1_clkin_ck", "video1_clkin_ck"),
+       DT_CLK(NULL, "video1_m2_clkin_ck", "video1_m2_clkin_ck"),
+       DT_CLK(NULL, "video2_clkin_ck", "video2_clkin_ck"),
+       DT_CLK(NULL, "video2_m2_clkin_ck", "video2_m2_clkin_ck"),
+       DT_CLK(NULL, "abe_dpll_sys_clk_mux", "abe_dpll_sys_clk_mux"),
+       DT_CLK(NULL, "abe_dpll_bypass_clk_mux", "abe_dpll_bypass_clk_mux"),
+       DT_CLK(NULL, "abe_dpll_clk_mux", "abe_dpll_clk_mux"),
+       DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"),
+       DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"),
+       DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"),
+       DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"),
+       DT_CLK(NULL, "abe_clk", "abe_clk"),
+       DT_CLK(NULL, "aess_fclk", "aess_fclk"),
+       DT_CLK(NULL, "abe_giclk_div", "abe_giclk_div"),
+       DT_CLK(NULL, "abe_lp_clk_div", "abe_lp_clk_div"),
+       DT_CLK(NULL, "abe_sys_clk_div", "abe_sys_clk_div"),
+       DT_CLK(NULL, "adc_gfclk_mux", "adc_gfclk_mux"),
+       DT_CLK(NULL, "dpll_pcie_ref_ck", "dpll_pcie_ref_ck"),
+       DT_CLK(NULL, "dpll_pcie_ref_m2ldo_ck", "dpll_pcie_ref_m2ldo_ck"),
+       DT_CLK(NULL, "apll_pcie_ck", "apll_pcie_ck"),
+       DT_CLK(NULL, "apll_pcie_clkvcoldo", "apll_pcie_clkvcoldo"),
+       DT_CLK(NULL, "apll_pcie_clkvcoldo_div", "apll_pcie_clkvcoldo_div"),
+       DT_CLK(NULL, "apll_pcie_m2_ck", "apll_pcie_m2_ck"),
+       DT_CLK(NULL, "sys_clk1_dclk_div", "sys_clk1_dclk_div"),
+       DT_CLK(NULL, "sys_clk2_dclk_div", "sys_clk2_dclk_div"),
+       DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"),
+       DT_CLK(NULL, "per_abe_x1_dclk_div", "per_abe_x1_dclk_div"),
+       DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"),
+       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
+       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
+       DT_CLK(NULL, "dpll_core_h12x2_ck", "dpll_core_h12x2_ck"),
+       DT_CLK(NULL, "mpu_dpll_hs_clk_div", "mpu_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
+       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
+       DT_CLK(NULL, "mpu_dclk_div", "mpu_dclk_div"),
+       DT_CLK(NULL, "dsp_dpll_hs_clk_div", "dsp_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_dsp_ck", "dpll_dsp_ck"),
+       DT_CLK(NULL, "dpll_dsp_m2_ck", "dpll_dsp_m2_ck"),
+       DT_CLK(NULL, "dsp_gclk_div", "dsp_gclk_div"),
+       DT_CLK(NULL, "iva_dpll_hs_clk_div", "iva_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"),
+       DT_CLK(NULL, "dpll_iva_m2_ck", "dpll_iva_m2_ck"),
+       DT_CLK(NULL, "iva_dclk", "iva_dclk"),
+       DT_CLK(NULL, "dpll_gpu_ck", "dpll_gpu_ck"),
+       DT_CLK(NULL, "dpll_gpu_m2_ck", "dpll_gpu_m2_ck"),
+       DT_CLK(NULL, "gpu_dclk", "gpu_dclk"),
+       DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"),
+       DT_CLK(NULL, "core_dpll_out_dclk_div", "core_dpll_out_dclk_div"),
+       DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"),
+       DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"),
+       DT_CLK(NULL, "emif_phy_dclk_div", "emif_phy_dclk_div"),
+       DT_CLK(NULL, "dpll_gmac_ck", "dpll_gmac_ck"),
+       DT_CLK(NULL, "dpll_gmac_m2_ck", "dpll_gmac_m2_ck"),
+       DT_CLK(NULL, "gmac_250m_dclk_div", "gmac_250m_dclk_div"),
+       DT_CLK(NULL, "video2_dclk_div", "video2_dclk_div"),
+       DT_CLK(NULL, "video1_dclk_div", "video1_dclk_div"),
+       DT_CLK(NULL, "hdmi_dclk_div", "hdmi_dclk_div"),
+       DT_CLK(NULL, "per_dpll_hs_clk_div", "per_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
+       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
+       DT_CLK(NULL, "func_96m_aon_dclk_div", "func_96m_aon_dclk_div"),
+       DT_CLK(NULL, "usb_dpll_hs_clk_div", "usb_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"),
+       DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"),
+       DT_CLK(NULL, "l3init_480m_dclk_div", "l3init_480m_dclk_div"),
+       DT_CLK(NULL, "usb_otg_dclk_div", "usb_otg_dclk_div"),
+       DT_CLK(NULL, "sata_dclk_div", "sata_dclk_div"),
+       DT_CLK(NULL, "dpll_pcie_ref_m2_ck", "dpll_pcie_ref_m2_ck"),
+       DT_CLK(NULL, "pcie2_dclk_div", "pcie2_dclk_div"),
+       DT_CLK(NULL, "pcie_dclk_div", "pcie_dclk_div"),
+       DT_CLK(NULL, "emu_dclk_div", "emu_dclk_div"),
+       DT_CLK(NULL, "secure_32k_dclk_div", "secure_32k_dclk_div"),
+       DT_CLK(NULL, "eve_dpll_hs_clk_div", "eve_dpll_hs_clk_div"),
+       DT_CLK(NULL, "dpll_eve_ck", "dpll_eve_ck"),
+       DT_CLK(NULL, "dpll_eve_m2_ck", "dpll_eve_m2_ck"),
+       DT_CLK(NULL, "eve_dclk_div", "eve_dclk_div"),
+       DT_CLK(NULL, "clkoutmux0_clk_mux", "clkoutmux0_clk_mux"),
+       DT_CLK(NULL, "clkoutmux1_clk_mux", "clkoutmux1_clk_mux"),
+       DT_CLK(NULL, "clkoutmux2_clk_mux", "clkoutmux2_clk_mux"),
+       DT_CLK(NULL, "custefuse_sys_gfclk_div", "custefuse_sys_gfclk_div"),
+       DT_CLK(NULL, "dpll_core_h13x2_ck", "dpll_core_h13x2_ck"),
+       DT_CLK(NULL, "dpll_core_h14x2_ck", "dpll_core_h14x2_ck"),
+       DT_CLK(NULL, "dpll_core_h22x2_ck", "dpll_core_h22x2_ck"),
+       DT_CLK(NULL, "dpll_core_h23x2_ck", "dpll_core_h23x2_ck"),
+       DT_CLK(NULL, "dpll_core_h24x2_ck", "dpll_core_h24x2_ck"),
+       DT_CLK(NULL, "dpll_ddr_x2_ck", "dpll_ddr_x2_ck"),
+       DT_CLK(NULL, "dpll_ddr_h11x2_ck", "dpll_ddr_h11x2_ck"),
+       DT_CLK(NULL, "dpll_dsp_x2_ck", "dpll_dsp_x2_ck"),
+       DT_CLK(NULL, "dpll_dsp_m3x2_ck", "dpll_dsp_m3x2_ck"),
+       DT_CLK(NULL, "dpll_gmac_x2_ck", "dpll_gmac_x2_ck"),
+       DT_CLK(NULL, "dpll_gmac_h11x2_ck", "dpll_gmac_h11x2_ck"),
+       DT_CLK(NULL, "dpll_gmac_h12x2_ck", "dpll_gmac_h12x2_ck"),
+       DT_CLK(NULL, "dpll_gmac_h13x2_ck", "dpll_gmac_h13x2_ck"),
+       DT_CLK(NULL, "dpll_gmac_m3x2_ck", "dpll_gmac_m3x2_ck"),
+       DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"),
+       DT_CLK(NULL, "dpll_per_h11x2_ck", "dpll_per_h11x2_ck"),
+       DT_CLK(NULL, "dpll_per_h12x2_ck", "dpll_per_h12x2_ck"),
+       DT_CLK(NULL, "dpll_per_h13x2_ck", "dpll_per_h13x2_ck"),
+       DT_CLK(NULL, "dpll_per_h14x2_ck", "dpll_per_h14x2_ck"),
+       DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"),
+       DT_CLK(NULL, "dpll_usb_clkdcoldo", "dpll_usb_clkdcoldo"),
+       DT_CLK(NULL, "eve_clk", "eve_clk"),
+       DT_CLK(NULL, "func_128m_clk", "func_128m_clk"),
+       DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"),
+       DT_CLK(NULL, "func_24m_clk", "func_24m_clk"),
+       DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"),
+       DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"),
+       DT_CLK(NULL, "gmii_m_clk_div", "gmii_m_clk_div"),
+       DT_CLK(NULL, "hdmi_clk2_div", "hdmi_clk2_div"),
+       DT_CLK(NULL, "hdmi_div_clk", "hdmi_div_clk"),
+       DT_CLK(NULL, "hdmi_dpll_clk_mux", "hdmi_dpll_clk_mux"),
+       DT_CLK(NULL, "l3_iclk_div", "l3_iclk_div"),
+       DT_CLK(NULL, "l3init_60m_fclk", "l3init_60m_fclk"),
+       DT_CLK(NULL, "l4_root_clk_div", "l4_root_clk_div"),
+       DT_CLK(NULL, "mlb_clk", "mlb_clk"),
+       DT_CLK(NULL, "mlbp_clk", "mlbp_clk"),
+       DT_CLK(NULL, "per_abe_x1_gfclk2_div", "per_abe_x1_gfclk2_div"),
+       DT_CLK(NULL, "timer_sys_clk_div", "timer_sys_clk_div"),
+       DT_CLK(NULL, "video1_clk2_div", "video1_clk2_div"),
+       DT_CLK(NULL, "video1_div_clk", "video1_div_clk"),
+       DT_CLK(NULL, "video1_dpll_clk_mux", "video1_dpll_clk_mux"),
+       DT_CLK(NULL, "video2_clk2_div", "video2_clk2_div"),
+       DT_CLK(NULL, "video2_div_clk", "video2_div_clk"),
+       DT_CLK(NULL, "video2_dpll_clk_mux", "video2_dpll_clk_mux"),
+       DT_CLK(NULL, "wkupaon_iclk_mux", "wkupaon_iclk_mux"),
+       DT_CLK(NULL, "dss_32khz_clk", "dss_32khz_clk"),
+       DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"),
+       DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"),
+       DT_CLK(NULL, "dss_hdmi_clk", "dss_hdmi_clk"),
+       DT_CLK(NULL, "dss_video1_clk", "dss_video1_clk"),
+       DT_CLK(NULL, "dss_video2_clk", "dss_video2_clk"),
+       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
+       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
+       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
+       DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
+       DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
+       DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"),
+       DT_CLK(NULL, "gpio7_dbclk", "gpio7_dbclk"),
+       DT_CLK(NULL, "gpio8_dbclk", "gpio8_dbclk"),
+       DT_CLK(NULL, "mmc1_clk32k", "mmc1_clk32k"),
+       DT_CLK(NULL, "mmc2_clk32k", "mmc2_clk32k"),
+       DT_CLK(NULL, "mmc3_clk32k", "mmc3_clk32k"),
+       DT_CLK(NULL, "mmc4_clk32k", "mmc4_clk32k"),
+       DT_CLK(NULL, "sata_ref_clk", "sata_ref_clk"),
+       DT_CLK(NULL, "usb_otg_ss1_refclk960m", "usb_otg_ss1_refclk960m"),
+       DT_CLK(NULL, "usb_otg_ss2_refclk960m", "usb_otg_ss2_refclk960m"),
+       DT_CLK(NULL, "usb_phy1_always_on_clk32k", "usb_phy1_always_on_clk32k"),
+       DT_CLK(NULL, "usb_phy2_always_on_clk32k", "usb_phy2_always_on_clk32k"),
+       DT_CLK(NULL, "usb_phy3_always_on_clk32k", "usb_phy3_always_on_clk32k"),
+       DT_CLK(NULL, "atl_dpll_clk_mux", "atl_dpll_clk_mux"),
+       DT_CLK(NULL, "atl_gfclk_mux", "atl_gfclk_mux"),
+       DT_CLK(NULL, "dcan1_sys_clk_mux", "dcan1_sys_clk_mux"),
+       DT_CLK(NULL, "gmac_gmii_ref_clk_div", "gmac_gmii_ref_clk_div"),
+       DT_CLK(NULL, "gmac_rft_clk_mux", "gmac_rft_clk_mux"),
+       DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"),
+       DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"),
+       DT_CLK(NULL, "ipu1_gfclk_mux", "ipu1_gfclk_mux"),
+       DT_CLK(NULL, "l3instr_ts_gclk_div", "l3instr_ts_gclk_div"),
+       DT_CLK(NULL, "mcasp1_ahclkr_mux", "mcasp1_ahclkr_mux"),
+       DT_CLK(NULL, "mcasp1_ahclkx_mux", "mcasp1_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp1_aux_gfclk_mux", "mcasp1_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp2_ahclkr_mux", "mcasp2_ahclkr_mux"),
+       DT_CLK(NULL, "mcasp2_ahclkx_mux", "mcasp2_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp2_aux_gfclk_mux", "mcasp2_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp3_ahclkx_mux", "mcasp3_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp3_aux_gfclk_mux", "mcasp3_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp4_ahclkx_mux", "mcasp4_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp4_aux_gfclk_mux", "mcasp4_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp5_ahclkx_mux", "mcasp5_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp5_aux_gfclk_mux", "mcasp5_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp6_ahclkx_mux", "mcasp6_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp6_aux_gfclk_mux", "mcasp6_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp7_ahclkx_mux", "mcasp7_ahclkx_mux"),
+       DT_CLK(NULL, "mcasp7_aux_gfclk_mux", "mcasp7_aux_gfclk_mux"),
+       DT_CLK(NULL, "mcasp8_ahclk_mux", "mcasp8_ahclk_mux"),
+       DT_CLK(NULL, "mcasp8_aux_gfclk_mux", "mcasp8_aux_gfclk_mux"),
+       DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"),
+       DT_CLK(NULL, "mmc1_fclk_div", "mmc1_fclk_div"),
+       DT_CLK(NULL, "mmc2_fclk_mux", "mmc2_fclk_mux"),
+       DT_CLK(NULL, "mmc2_fclk_div", "mmc2_fclk_div"),
+       DT_CLK(NULL, "mmc3_gfclk_mux", "mmc3_gfclk_mux"),
+       DT_CLK(NULL, "mmc3_gfclk_div", "mmc3_gfclk_div"),
+       DT_CLK(NULL, "mmc4_gfclk_mux", "mmc4_gfclk_mux"),
+       DT_CLK(NULL, "mmc4_gfclk_div", "mmc4_gfclk_div"),
+       DT_CLK(NULL, "qspi_gfclk_mux", "qspi_gfclk_mux"),
+       DT_CLK(NULL, "qspi_gfclk_div", "qspi_gfclk_div"),
+       DT_CLK(NULL, "timer10_gfclk_mux", "timer10_gfclk_mux"),
+       DT_CLK(NULL, "timer11_gfclk_mux", "timer11_gfclk_mux"),
+       DT_CLK(NULL, "timer13_gfclk_mux", "timer13_gfclk_mux"),
+       DT_CLK(NULL, "timer14_gfclk_mux", "timer14_gfclk_mux"),
+       DT_CLK(NULL, "timer15_gfclk_mux", "timer15_gfclk_mux"),
+       DT_CLK(NULL, "timer16_gfclk_mux", "timer16_gfclk_mux"),
+       DT_CLK(NULL, "timer1_gfclk_mux", "timer1_gfclk_mux"),
+       DT_CLK(NULL, "timer2_gfclk_mux", "timer2_gfclk_mux"),
+       DT_CLK(NULL, "timer3_gfclk_mux", "timer3_gfclk_mux"),
+       DT_CLK(NULL, "timer4_gfclk_mux", "timer4_gfclk_mux"),
+       DT_CLK(NULL, "timer5_gfclk_mux", "timer5_gfclk_mux"),
+       DT_CLK(NULL, "timer6_gfclk_mux", "timer6_gfclk_mux"),
+       DT_CLK(NULL, "timer7_gfclk_mux", "timer7_gfclk_mux"),
+       DT_CLK(NULL, "timer8_gfclk_mux", "timer8_gfclk_mux"),
+       DT_CLK(NULL, "timer9_gfclk_mux", "timer9_gfclk_mux"),
+       DT_CLK(NULL, "uart10_gfclk_mux", "uart10_gfclk_mux"),
+       DT_CLK(NULL, "uart1_gfclk_mux", "uart1_gfclk_mux"),
+       DT_CLK(NULL, "uart2_gfclk_mux", "uart2_gfclk_mux"),
+       DT_CLK(NULL, "uart3_gfclk_mux", "uart3_gfclk_mux"),
+       DT_CLK(NULL, "uart4_gfclk_mux", "uart4_gfclk_mux"),
+       DT_CLK(NULL, "uart5_gfclk_mux", "uart5_gfclk_mux"),
+       DT_CLK(NULL, "uart6_gfclk_mux", "uart6_gfclk_mux"),
+       DT_CLK(NULL, "uart7_gfclk_mux", "uart7_gfclk_mux"),
+       DT_CLK(NULL, "uart8_gfclk_mux", "uart8_gfclk_mux"),
+       DT_CLK(NULL, "uart9_gfclk_mux", "uart9_gfclk_mux"),
+       DT_CLK(NULL, "vip1_gclk_mux", "vip1_gclk_mux"),
+       DT_CLK(NULL, "vip2_gclk_mux", "vip2_gclk_mux"),
+       DT_CLK(NULL, "vip3_gclk_mux", "vip3_gclk_mux"),
+       DT_CLK(NULL, "gpmc_ck", "dummy_ck"),
+       DT_CLK("omap_i2c.1", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.2", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.3", "ick", "dummy_ck"),
+       DT_CLK("omap_i2c.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "mailboxes_ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.0", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.1", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.2", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.3", "ick", "dummy_ck"),
+       DT_CLK("omap_hsmmc.4", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.1", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.2", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.3", "ick", "dummy_ck"),
+       DT_CLK("omap-mcbsp.4", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.1", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.2", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.3", "ick", "dummy_ck"),
+       DT_CLK("omap2_mcspi.4", "ick", "dummy_ck"),
+       DT_CLK(NULL, "uart1_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart2_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart3_ick", "dummy_ck"),
+       DT_CLK(NULL, "uart4_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbhost_ick", "dummy_ck"),
+       DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
+       DT_CLK("omap_wdt", "ick", "dummy_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
+       DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("48820000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48826000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK(NULL, "sys_clkin", "sys_clkin1"),
+       { .node_name = NULL },
+};
+
+int __init dra7xx_dt_clk_init(void)
+{
+       int rc;
+       struct clk *abe_dpll_mux, *sys_clkin2, *dpll_ck;
+
+       ti_dt_clocks_register(dra7xx_clks);
+
+       omap2_clk_disable_autoidle_all();
+
+       abe_dpll_mux = clk_get_sys(NULL, "abe_dpll_sys_clk_mux");
+       sys_clkin2 = clk_get_sys(NULL, "sys_clkin2");
+       dpll_ck = clk_get_sys(NULL, "dpll_abe_ck");
+
+       rc = clk_set_parent(abe_dpll_mux, sys_clkin2);
+       if (!rc)
+               rc = clk_set_rate(dpll_ck, DRA7_DPLL_ABE_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
+
+       dpll_ck = clk_get_sys(NULL, "dpll_gmac_ck");
+       rc = clk_set_rate(dpll_ck, DRA7_DPLL_GMAC_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure GMAC DPLL!\n", __func__);
+
+       return rc;
+}
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
new file mode 100644 (file)
index 0000000..b1a6f71
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * TI clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/ti.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/list.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static int ti_dt_clk_memmap_index;
+struct ti_clk_ll_ops *ti_clk_ll_ops;
+
+/**
+ * ti_dt_clocks_register - register DT alias clocks during boot
+ * @oclks: list of clocks to register
+ *
+ * Register alias or non-standard DT clock entries during boot. By
+ * default, DT clocks are found based on their node name. If any
+ * additional con-id / dev-id -> clock mapping is required, use this
+ * function to list these.
+ */
+void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
+{
+       struct ti_dt_clk *c;
+       struct device_node *node;
+       struct clk *clk;
+       struct of_phandle_args clkspec;
+
+       for (c = oclks; c->node_name != NULL; c++) {
+               node = of_find_node_by_name(NULL, c->node_name);
+               clkspec.np = node;
+               clk = of_clk_get_from_provider(&clkspec);
+
+               if (!IS_ERR(clk)) {
+                       c->lk.clk = clk;
+                       clkdev_add(&c->lk);
+               } else {
+                       pr_warn("failed to lookup clock node %s\n",
+                               c->node_name);
+               }
+       }
+}
+
+struct clk_init_item {
+       struct device_node *node;
+       struct clk_hw *hw;
+       ti_of_clk_init_cb_t func;
+       struct list_head link;
+};
+
+static LIST_HEAD(retry_list);
+
+/**
+ * ti_clk_retry_init - retries a failed clock init at later phase
+ * @node: device not for the clock
+ * @hw: partially initialized clk_hw struct for the clock
+ * @func: init function to be called for the clock
+ *
+ * Adds a failed clock init to the retry list. The retry list is parsed
+ * once all the other clocks have been initialized.
+ */
+int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+                             ti_of_clk_init_cb_t func)
+{
+       struct clk_init_item *retry;
+
+       pr_debug("%s: adding to retry list...\n", node->name);
+       retry = kzalloc(sizeof(*retry), GFP_KERNEL);
+       if (!retry)
+               return -ENOMEM;
+
+       retry->node = node;
+       retry->func = func;
+       retry->hw = hw;
+       list_add(&retry->link, &retry_list);
+
+       return 0;
+}
+
+/**
+ * ti_clk_get_reg_addr - get register address for a clock register
+ * @node: device node for the clock
+ * @index: register index from the clock node
+ *
+ * Builds clock register address from device tree information. This
+ * is a struct of type clk_omap_reg.
+ */
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
+{
+       struct clk_omap_reg *reg;
+       u32 val;
+       u32 tmp;
+
+       reg = (struct clk_omap_reg *)&tmp;
+       reg->index = ti_dt_clk_memmap_index;
+
+       if (of_property_read_u32_index(node, "reg", index, &val)) {
+               pr_err("%s must have reg[%d]!\n", node->name, index);
+               return NULL;
+       }
+
+       reg->offset = val;
+
+       return (void __iomem *)tmp;
+}
+
+/**
+ * ti_dt_clk_init_provider - init master clock provider
+ * @parent: master node
+ * @index: internal index for clk_reg_ops
+ *
+ * Initializes a master clock IP block and its child clock nodes.
+ * Regmap is provided for accessing the register space for the
+ * IP block and all the clocks under it.
+ */
+void ti_dt_clk_init_provider(struct device_node *parent, int index)
+{
+       const struct of_device_id *match;
+       struct device_node *np;
+       struct device_node *clocks;
+       of_clk_init_cb_t clk_init_cb;
+       struct clk_init_item *retry;
+       struct clk_init_item *tmp;
+
+       ti_dt_clk_memmap_index = index;
+
+       /* get clocks for this parent */
+       clocks = of_get_child_by_name(parent, "clocks");
+       if (!clocks) {
+               pr_err("%s missing 'clocks' child node.\n", parent->name);
+               return;
+       }
+
+       for_each_child_of_node(clocks, np) {
+               match = of_match_node(&__clk_of_table, np);
+               if (!match)
+                       continue;
+               clk_init_cb = (of_clk_init_cb_t)match->data;
+               pr_debug("%s: initializing: %s\n", __func__, np->name);
+               clk_init_cb(np);
+       }
+
+       list_for_each_entry_safe(retry, tmp, &retry_list, link) {
+               pr_debug("retry-init: %s\n", retry->node->name);
+               retry->func(retry->hw, retry->node);
+               list_del(&retry->link);
+               kfree(retry);
+       }
+}
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
new file mode 100644 (file)
index 0000000..f1e0038
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * OMAP clockdomain support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static void __init of_ti_clockdomain_setup(struct device_node *node)
+{
+       struct clk *clk;
+       struct clk_hw *clk_hw;
+       const char *clkdm_name = node->name;
+       int i;
+       int num_clks;
+
+       num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+
+       for (i = 0; i < num_clks; i++) {
+               clk = of_clk_get(node, i);
+               if (__clk_get_flags(clk) & CLK_IS_BASIC) {
+                       pr_warn("can't setup clkdm for basic clk %s\n",
+                               __clk_get_name(clk));
+                       continue;
+               }
+               clk_hw = __clk_get_hw(clk);
+               to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
+               omap2_init_clk_clkdm(clk_hw);
+       }
+}
+
+static struct of_device_id ti_clkdm_match_table[] __initdata = {
+       { .compatible = "ti,clockdomain" },
+       { }
+};
+
+/**
+ * ti_dt_clockdomains_setup - setup device tree clockdomains
+ *
+ * Initializes clockdomain nodes for a SoC. This parses through all the
+ * nodes with compatible = "ti,clockdomain", and add the clockdomain
+ * info for all the clocks listed under these. This function shall be
+ * called after rest of the DT clock init has completed and all
+ * clock nodes have been registered.
+ */
+void __init ti_dt_clockdomains_setup(void)
+{
+       struct device_node *np;
+       for_each_matching_node(np, ti_clkdm_match_table) {
+               of_ti_clockdomain_setup(np);
+       }
+}
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
new file mode 100644 (file)
index 0000000..19d8980
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * TI composite clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+#include <linux/list.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
+                                             unsigned long parent_rate)
+{
+       return ti_clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long *prate)
+{
+       return -EINVAL;
+}
+
+static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       return -EINVAL;
+}
+
+static const struct clk_ops ti_composite_divider_ops = {
+       .recalc_rate    = &ti_composite_recalc_rate,
+       .round_rate     = &ti_composite_round_rate,
+       .set_rate       = &ti_composite_set_rate,
+};
+
+static const struct clk_ops ti_composite_gate_ops = {
+       .enable         = &omap2_dflt_clk_enable,
+       .disable        = &omap2_dflt_clk_disable,
+       .is_enabled     = &omap2_dflt_clk_is_enabled,
+};
+
+struct component_clk {
+       int num_parents;
+       const char **parent_names;
+       struct device_node *node;
+       int type;
+       struct clk_hw *hw;
+       struct list_head link;
+};
+
+static const char * __initconst component_clk_types[] = {
+       "gate", "divider", "mux"
+};
+
+static LIST_HEAD(component_clks);
+
+static struct device_node *_get_component_node(struct device_node *node, int i)
+{
+       int rc;
+       struct of_phandle_args clkspec;
+
+       rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
+                                       &clkspec);
+       if (rc)
+               return NULL;
+
+       return clkspec.np;
+}
+
+static struct component_clk *_lookup_component(struct device_node *node)
+{
+       struct component_clk *comp;
+
+       list_for_each_entry(comp, &component_clks, link) {
+               if (comp->node == node)
+                       return comp;
+       }
+       return NULL;
+}
+
+struct clk_hw_omap_comp {
+       struct clk_hw hw;
+       struct device_node *comp_nodes[CLK_COMPONENT_TYPE_MAX];
+       struct component_clk *comp_clks[CLK_COMPONENT_TYPE_MAX];
+};
+
+static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
+{
+       if (!clk)
+               return NULL;
+
+       if (!clk->comp_clks[idx])
+               return NULL;
+
+       return clk->comp_clks[idx]->hw;
+}
+
+#define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
+
+static void __init ti_clk_register_composite(struct clk_hw *hw,
+                                            struct device_node *node)
+{
+       struct clk *clk;
+       struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
+       struct component_clk *comp;
+       int num_parents = 0;
+       const char **parent_names = NULL;
+       int i;
+
+       /* Check for presence of each component clock */
+       for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
+               if (!cclk->comp_nodes[i])
+                       continue;
+
+               comp = _lookup_component(cclk->comp_nodes[i]);
+               if (!comp) {
+                       pr_debug("component %s not ready for %s, retry\n",
+                                cclk->comp_nodes[i]->name, node->name);
+                       if (!ti_clk_retry_init(node, hw,
+                                              ti_clk_register_composite))
+                               return;
+
+                       goto cleanup;
+               }
+               if (cclk->comp_clks[comp->type] != NULL) {
+                       pr_err("duplicate component types for %s (%s)!\n",
+                              node->name, component_clk_types[comp->type]);
+                       goto cleanup;
+               }
+
+               cclk->comp_clks[comp->type] = comp;
+
+               /* Mark this node as found */
+               cclk->comp_nodes[i] = NULL;
+       }
+
+       /* All components exists, proceed with registration */
+       for (i = CLK_COMPONENT_TYPE_MAX - 1; i >= 0; i--) {
+               comp = cclk->comp_clks[i];
+               if (!comp)
+                       continue;
+               if (comp->num_parents) {
+                       num_parents = comp->num_parents;
+                       parent_names = comp->parent_names;
+                       break;
+               }
+       }
+
+       if (!num_parents) {
+               pr_err("%s: no parents found for %s!\n", __func__, node->name);
+               goto cleanup;
+       }
+
+       clk = clk_register_composite(NULL, node->name,
+                                    parent_names, num_parents,
+                                    _get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
+                                    &ti_clk_mux_ops,
+                                    _get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER),
+                                    &ti_composite_divider_ops,
+                                    _get_hw(cclk, CLK_COMPONENT_TYPE_GATE),
+                                    &ti_composite_gate_ops, 0);
+
+       if (!IS_ERR(clk))
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+cleanup:
+       /* Free component clock list entries */
+       for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
+               if (!cclk->comp_clks[i])
+                       continue;
+               list_del(&cclk->comp_clks[i]->link);
+               kfree(cclk->comp_clks[i]);
+       }
+
+       kfree(cclk);
+}
+
+static void __init of_ti_composite_clk_setup(struct device_node *node)
+{
+       int num_clks;
+       int i;
+       struct clk_hw_omap_comp *cclk;
+
+       /* Number of component clocks to be put inside this clock */
+       num_clks = of_clk_get_parent_count(node);
+
+       if (num_clks < 1) {
+               pr_err("composite clk %s must have component(s)\n", node->name);
+               return;
+       }
+
+       cclk = kzalloc(sizeof(*cclk), GFP_KERNEL);
+       if (!cclk)
+               return;
+
+       /* Get device node pointers for each component clock */
+       for (i = 0; i < num_clks; i++)
+               cclk->comp_nodes[i] = _get_component_node(node, i);
+
+       ti_clk_register_composite(&cclk->hw, node);
+}
+CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
+              of_ti_composite_clk_setup);
+
+/**
+ * ti_clk_add_component - add a component clock to the pool
+ * @node: device node of the component clock
+ * @hw: hardware clock definition for the component clock
+ * @type: type of the component clock
+ *
+ * Adds a component clock to the list of available components, so that
+ * it can be registered by a composite clock.
+ */
+int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
+                               int type)
+{
+       int num_parents;
+       const char **parent_names;
+       struct component_clk *clk;
+       int i;
+
+       num_parents = of_clk_get_parent_count(node);
+
+       if (num_parents < 1) {
+               pr_err("component-clock %s must have parent(s)\n", node->name);
+               return -EINVAL;
+       }
+
+       parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+       if (!parent_names)
+               return -ENOMEM;
+
+       for (i = 0; i < num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(node, i);
+
+       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+       if (!clk) {
+               kfree(parent_names);
+               return -ENOMEM;
+       }
+
+       clk->num_parents = num_parents;
+       clk->parent_names = parent_names;
+       clk->hw = hw;
+       clk->node = node;
+       clk->type = type;
+       list_add(&clk->link, &component_clks);
+
+       return 0;
+}
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
new file mode 100644 (file)
index 0000000..a15e445
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * TI Divider Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+#define div_mask(d)    ((1 << ((d)->width)) - 1)
+
+static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
+{
+       unsigned int maxdiv = 0;
+       const struct clk_div_table *clkt;
+
+       for (clkt = table; clkt->div; clkt++)
+               if (clkt->div > maxdiv)
+                       maxdiv = clkt->div;
+       return maxdiv;
+}
+
+static unsigned int _get_maxdiv(struct clk_divider *divider)
+{
+       if (divider->flags & CLK_DIVIDER_ONE_BASED)
+               return div_mask(divider);
+       if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+               return 1 << div_mask(divider);
+       if (divider->table)
+               return _get_table_maxdiv(divider->table);
+       return div_mask(divider) + 1;
+}
+
+static unsigned int _get_table_div(const struct clk_div_table *table,
+                                  unsigned int val)
+{
+       const struct clk_div_table *clkt;
+
+       for (clkt = table; clkt->div; clkt++)
+               if (clkt->val == val)
+                       return clkt->div;
+       return 0;
+}
+
+static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+{
+       if (divider->flags & CLK_DIVIDER_ONE_BASED)
+               return val;
+       if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+               return 1 << val;
+       if (divider->table)
+               return _get_table_div(divider->table, val);
+       return val + 1;
+}
+
+static unsigned int _get_table_val(const struct clk_div_table *table,
+                                  unsigned int div)
+{
+       const struct clk_div_table *clkt;
+
+       for (clkt = table; clkt->div; clkt++)
+               if (clkt->div == div)
+                       return clkt->val;
+       return 0;
+}
+
+static unsigned int _get_val(struct clk_divider *divider, u8 div)
+{
+       if (divider->flags & CLK_DIVIDER_ONE_BASED)
+               return div;
+       if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+               return __ffs(div);
+       if (divider->table)
+               return  _get_table_val(divider->table, div);
+       return div - 1;
+}
+
+static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       unsigned int div, val;
+
+       val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift;
+       val &= div_mask(divider);
+
+       div = _get_div(divider, val);
+       if (!div) {
+               WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
+                    "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
+                    __clk_get_name(hw->clk));
+               return parent_rate;
+       }
+
+       return parent_rate / div;
+}
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+static bool _is_valid_table_div(const struct clk_div_table *table,
+                               unsigned int div)
+{
+       const struct clk_div_table *clkt;
+
+       for (clkt = table; clkt->div; clkt++)
+               if (clkt->div == div)
+                       return true;
+       return false;
+}
+
+static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+{
+       if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+               return is_power_of_2(div);
+       if (divider->table)
+               return _is_valid_table_div(divider->table, div);
+       return true;
+}
+
+static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+                                 unsigned long *best_parent_rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       int i, bestdiv = 0;
+       unsigned long parent_rate, best = 0, now, maxdiv;
+       unsigned long parent_rate_saved = *best_parent_rate;
+
+       if (!rate)
+               rate = 1;
+
+       maxdiv = _get_maxdiv(divider);
+
+       if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+               parent_rate = *best_parent_rate;
+               bestdiv = DIV_ROUND_UP(parent_rate, rate);
+               bestdiv = bestdiv == 0 ? 1 : bestdiv;
+               bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+               return bestdiv;
+       }
+
+       /*
+        * The maximum divider we can use without overflowing
+        * unsigned long in rate * i below
+        */
+       maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+       for (i = 1; i <= maxdiv; i++) {
+               if (!_is_valid_div(divider, i))
+                       continue;
+               if (rate * i == parent_rate_saved) {
+                       /*
+                        * It's the most ideal case if the requested rate can be
+                        * divided from parent clock without needing to change
+                        * parent rate, so return the divider immediately.
+                        */
+                       *best_parent_rate = parent_rate_saved;
+                       return i;
+               }
+               parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+                               MULT_ROUND_UP(rate, i));
+               now = parent_rate / i;
+               if (now <= rate && now > best) {
+                       bestdiv = i;
+                       best = now;
+                       *best_parent_rate = parent_rate;
+               }
+       }
+
+       if (!bestdiv) {
+               bestdiv = _get_maxdiv(divider);
+               *best_parent_rate =
+                       __clk_round_rate(__clk_get_parent(hw->clk), 1);
+       }
+
+       return bestdiv;
+}
+
+static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long *prate)
+{
+       int div;
+       div = ti_clk_divider_bestdiv(hw, rate, prate);
+
+       return *prate / div;
+}
+
+static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       struct clk_divider *divider = to_clk_divider(hw);
+       unsigned int div, value;
+       unsigned long flags = 0;
+       u32 val;
+
+       div = parent_rate / rate;
+       value = _get_val(divider, div);
+
+       if (value > div_mask(divider))
+               value = div_mask(divider);
+
+       if (divider->lock)
+               spin_lock_irqsave(divider->lock, flags);
+
+       if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
+               val = div_mask(divider) << (divider->shift + 16);
+       } else {
+               val = ti_clk_ll_ops->clk_readl(divider->reg);
+               val &= ~(div_mask(divider) << divider->shift);
+       }
+       val |= value << divider->shift;
+       ti_clk_ll_ops->clk_writel(val, divider->reg);
+
+       if (divider->lock)
+               spin_unlock_irqrestore(divider->lock, flags);
+
+       return 0;
+}
+
+const struct clk_ops ti_clk_divider_ops = {
+       .recalc_rate = ti_clk_divider_recalc_rate,
+       .round_rate = ti_clk_divider_round_rate,
+       .set_rate = ti_clk_divider_set_rate,
+};
+
+static struct clk *_register_divider(struct device *dev, const char *name,
+                                    const char *parent_name,
+                                    unsigned long flags, void __iomem *reg,
+                                    u8 shift, u8 width, u8 clk_divider_flags,
+                                    const struct clk_div_table *table,
+                                    spinlock_t *lock)
+{
+       struct clk_divider *div;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
+               if (width + shift > 16) {
+                       pr_warn("divider value exceeds LOWORD field\n");
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       /* allocate the divider */
+       div = kzalloc(sizeof(*div), GFP_KERNEL);
+       if (!div) {
+               pr_err("%s: could not allocate divider clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = name;
+       init.ops = &ti_clk_divider_ops;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+
+       /* struct clk_divider assignments */
+       div->reg = reg;
+       div->shift = shift;
+       div->width = width;
+       div->flags = clk_divider_flags;
+       div->lock = lock;
+       div->hw.init = &init;
+       div->table = table;
+
+       /* register the clock */
+       clk = clk_register(dev, &div->hw);
+
+       if (IS_ERR(clk))
+               kfree(div);
+
+       return clk;
+}
+
+static struct clk_div_table
+__init *ti_clk_get_div_table(struct device_node *node)
+{
+       struct clk_div_table *table;
+       const __be32 *divspec;
+       u32 val;
+       u32 num_div;
+       u32 valid_div;
+       int i;
+
+       divspec = of_get_property(node, "ti,dividers", &num_div);
+
+       if (!divspec)
+               return NULL;
+
+       num_div /= 4;
+
+       valid_div = 0;
+
+       /* Determine required size for divider table */
+       for (i = 0; i < num_div; i++) {
+               of_property_read_u32_index(node, "ti,dividers", i, &val);
+               if (val)
+                       valid_div++;
+       }
+
+       if (!valid_div) {
+               pr_err("no valid dividers for %s table\n", node->name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+
+       if (!table)
+               return ERR_PTR(-ENOMEM);
+
+       valid_div = 0;
+
+       for (i = 0; i < num_div; i++) {
+               of_property_read_u32_index(node, "ti,dividers", i, &val);
+               if (val) {
+                       table[valid_div].div = val;
+                       table[valid_div].val = i;
+                       valid_div++;
+               }
+       }
+
+       return table;
+}
+
+static int _get_divider_width(struct device_node *node,
+                             const struct clk_div_table *table,
+                             u8 flags)
+{
+       u32 min_div;
+       u32 max_div;
+       u32 val = 0;
+       u32 div;
+
+       if (!table) {
+               /* Clk divider table not provided, determine min/max divs */
+               if (of_property_read_u32(node, "ti,min-div", &min_div))
+                       min_div = 1;
+
+               if (of_property_read_u32(node, "ti,max-div", &max_div)) {
+                       pr_err("no max-div for %s!\n", node->name);
+                       return -EINVAL;
+               }
+
+               /* Determine bit width for the field */
+               if (flags & CLK_DIVIDER_ONE_BASED)
+                       val = 1;
+
+               div = min_div;
+
+               while (div < max_div) {
+                       if (flags & CLK_DIVIDER_POWER_OF_TWO)
+                               div <<= 1;
+                       else
+                               div++;
+                       val++;
+               }
+       } else {
+               div = 0;
+
+               while (table[div].div) {
+                       val = table[div].val;
+                       div++;
+               }
+       }
+
+       return fls(val);
+}
+
+static int __init ti_clk_divider_populate(struct device_node *node,
+       void __iomem **reg, const struct clk_div_table **table,
+       u32 *flags, u8 *div_flags, u8 *width, u8 *shift)
+{
+       u32 val;
+
+       *reg = ti_clk_get_reg_addr(node, 0);
+       if (!*reg)
+               return -EINVAL;
+
+       if (!of_property_read_u32(node, "ti,bit-shift", &val))
+               *shift = val;
+       else
+               *shift = 0;
+
+       *flags = 0;
+       *div_flags = 0;
+
+       if (of_property_read_bool(node, "ti,index-starts-at-one"))
+               *div_flags |= CLK_DIVIDER_ONE_BASED;
+
+       if (of_property_read_bool(node, "ti,index-power-of-two"))
+               *div_flags |= CLK_DIVIDER_POWER_OF_TWO;
+
+       if (of_property_read_bool(node, "ti,set-rate-parent"))
+               *flags |= CLK_SET_RATE_PARENT;
+
+       *table = ti_clk_get_div_table(node);
+
+       if (IS_ERR(*table))
+               return PTR_ERR(*table);
+
+       *width = _get_divider_width(node, *table, *div_flags);
+
+       return 0;
+}
+
+/**
+ * of_ti_divider_clk_setup - Setup function for simple div rate clock
+ * @node: device node for this clock
+ *
+ * Sets up a basic divider clock.
+ */
+static void __init of_ti_divider_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       const char *parent_name;
+       void __iomem *reg;
+       u8 clk_divider_flags = 0;
+       u8 width = 0;
+       u8 shift = 0;
+       const struct clk_div_table *table = NULL;
+       u32 flags = 0;
+
+       parent_name = of_clk_get_parent_name(node, 0);
+
+       if (ti_clk_divider_populate(node, &reg, &table, &flags,
+                                   &clk_divider_flags, &width, &shift))
+               goto cleanup;
+
+       clk = _register_divider(NULL, node->name, parent_name, flags, reg,
+                               shift, width, clk_divider_flags, table, NULL);
+
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               of_ti_clk_autoidle_setup(node);
+               return;
+       }
+
+cleanup:
+       kfree(table);
+}
+CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
+
+static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
+{
+       struct clk_divider *div;
+       u32 val;
+
+       div = kzalloc(sizeof(*div), GFP_KERNEL);
+       if (!div)
+               return;
+
+       if (ti_clk_divider_populate(node, &div->reg, &div->table, &val,
+                                   &div->flags, &div->width, &div->shift) < 0)
+               goto cleanup;
+
+       if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
+               return;
+
+cleanup:
+       kfree(div->table);
+       kfree(div);
+}
+CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
+              of_ti_composite_divider_clk_setup);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
new file mode 100644 (file)
index 0000000..7e498a4
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * OMAP DPLL clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define DPLL_HAS_AUTOIDLE      0x1
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX)
+static const struct clk_ops dpll_m4xen_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .recalc_rate    = &omap4_dpll_regm4xen_recalc,
+       .round_rate     = &omap4_dpll_regm4xen_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+       .get_parent     = &omap2_init_dpll_parent,
+};
+#endif
+
+static const struct clk_ops dpll_core_ck_ops = {
+       .recalc_rate    = &omap3_dpll_recalc,
+       .get_parent     = &omap2_init_dpll_parent,
+};
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_core_ck_ops = {
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+#endif
+
+static const struct clk_ops dpll_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+       .get_parent     = &omap2_init_dpll_parent,
+};
+
+static const struct clk_ops dpll_no_gate_ck_ops = {
+       .recalc_rate    = &omap3_dpll_recalc,
+       .get_parent     = &omap2_init_dpll_parent,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+};
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+
+static const struct clk_ops omap3_dpll_per_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .set_rate       = &omap3_dpll4_set_rate,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+#endif
+
+static const struct clk_ops dpll_x2_ck_ops = {
+       .recalc_rate    = &omap3_clkoutx2_recalc,
+};
+
+/**
+ * ti_clk_register_dpll - low level registration of a DPLL clock
+ * @hw: hardware clock definition for the clock
+ * @node: device node for the clock
+ *
+ * Finalizes DPLL registration process. In case a failure (clk-ref or
+ * clk-bypass is missing), the clock is added to retry list and
+ * the initialization is retried on later stage.
+ */
+static void __init ti_clk_register_dpll(struct clk_hw *hw,
+                                       struct device_node *node)
+{
+       struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
+       struct dpll_data *dd = clk_hw->dpll_data;
+       struct clk *clk;
+
+       dd->clk_ref = of_clk_get(node, 0);
+       dd->clk_bypass = of_clk_get(node, 1);
+
+       if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) {
+               pr_debug("clk-ref or clk-bypass missing for %s, retry later\n",
+                        node->name);
+               if (!ti_clk_retry_init(node, hw, ti_clk_register_dpll))
+                       return;
+
+               goto cleanup;
+       }
+
+       /* register the clock */
+       clk = clk_register(NULL, &clk_hw->hw);
+
+       if (!IS_ERR(clk)) {
+               omap2_init_clk_hw_omap_clocks(clk);
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               kfree(clk_hw->hw.init->parent_names);
+               kfree(clk_hw->hw.init);
+               return;
+       }
+
+cleanup:
+       kfree(clk_hw->dpll_data);
+       kfree(clk_hw->hw.init->parent_names);
+       kfree(clk_hw->hw.init);
+       kfree(clk_hw);
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX)
+/**
+ * ti_clk_register_dpll_x2 - Registers a DPLLx2 clock
+ * @node: device node for this clock
+ * @ops: clk_ops for this clock
+ * @hw_ops: clk_hw_ops for this clock
+ *
+ * Initializes a DPLL x 2 clock from device tree data.
+ */
+static void ti_clk_register_dpll_x2(struct device_node *node,
+                                   const struct clk_ops *ops,
+                                   const struct clk_hw_omap_ops *hw_ops)
+{
+       struct clk *clk;
+       struct clk_init_data init = { NULL };
+       struct clk_hw_omap *clk_hw;
+       const char *name = node->name;
+       const char *parent_name;
+
+       parent_name = of_clk_get_parent_name(node, 0);
+       if (!parent_name) {
+               pr_err("%s must have parent\n", node->name);
+               return;
+       }
+
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       if (!clk_hw)
+               return;
+
+       clk_hw->ops = hw_ops;
+       clk_hw->hw.init = &init;
+
+       init.name = name;
+       init.ops = ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       /* register the clock */
+       clk = clk_register(NULL, &clk_hw->hw);
+
+       if (IS_ERR(clk)) {
+               kfree(clk_hw);
+       } else {
+               omap2_init_clk_hw_omap_clocks(clk);
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       }
+}
+#endif
+
+/**
+ * of_ti_dpll_setup - Setup function for OMAP DPLL clocks
+ * @node: device node containing the DPLL info
+ * @ops: ops for the DPLL
+ * @ddt: DPLL data template to use
+ * @init_flags: flags for controlling init types
+ *
+ * Initializes a DPLL clock from device tree data.
+ */
+static void __init of_ti_dpll_setup(struct device_node *node,
+                                   const struct clk_ops *ops,
+                                   const struct dpll_data *ddt,
+                                   u8 init_flags)
+{
+       struct clk_hw_omap *clk_hw = NULL;
+       struct clk_init_data *init = NULL;
+       const char **parent_names = NULL;
+       struct dpll_data *dd = NULL;
+       int i;
+       u8 dpll_mode = 0;
+
+       dd = kzalloc(sizeof(*dd), GFP_KERNEL);
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       init = kzalloc(sizeof(*init), GFP_KERNEL);
+       if (!dd || !clk_hw || !init)
+               goto cleanup;
+
+       memcpy(dd, ddt, sizeof(*dd));
+
+       clk_hw->dpll_data = dd;
+       clk_hw->ops = &clkhwops_omap3_dpll;
+       clk_hw->hw.init = init;
+       clk_hw->flags = MEMMAP_ADDRESSING;
+
+       init->name = node->name;
+       init->ops = ops;
+
+       init->num_parents = of_clk_get_parent_count(node);
+       if (init->num_parents < 1) {
+               pr_err("%s must have parent(s)\n", node->name);
+               goto cleanup;
+       }
+
+       parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+       if (!parent_names)
+               goto cleanup;
+
+       for (i = 0; i < init->num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(node, i);
+
+       init->parent_names = parent_names;
+
+       dd->control_reg = ti_clk_get_reg_addr(node, 0);
+       dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
+       dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
+
+       if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg)
+               goto cleanup;
+
+       if (init_flags & DPLL_HAS_AUTOIDLE) {
+               dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
+               if (!dd->autoidle_reg)
+                       goto cleanup;
+       }
+
+       if (of_property_read_bool(node, "ti,low-power-stop"))
+               dpll_mode |= 1 << DPLL_LOW_POWER_STOP;
+
+       if (of_property_read_bool(node, "ti,low-power-bypass"))
+               dpll_mode |= 1 << DPLL_LOW_POWER_BYPASS;
+
+       if (of_property_read_bool(node, "ti,lock"))
+               dpll_mode |= 1 << DPLL_LOCKED;
+
+       if (dpll_mode)
+               dd->modes = dpll_mode;
+
+       ti_clk_register_dpll(&clk_hw->hw, node);
+       return;
+
+cleanup:
+       kfree(dd);
+       kfree(parent_names);
+       kfree(init);
+       kfree(clk_hw);
+}
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX)
+static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node)
+{
+       ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
+}
+CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
+              of_ti_omap4_dpll_x2_setup);
+#endif
+
+#ifdef CONFIG_SOC_AM33XX
+static void __init of_ti_am3_dpll_x2_setup(struct device_node *node)
+{
+       ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
+}
+CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock",
+              of_ti_am3_dpll_x2_setup);
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init of_ti_omap3_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .freqsel_mask = 0xf0,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
+              of_ti_omap3_dpll_setup);
+
+static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 16,
+               .div1_mask = 0x7f << 8,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .freqsel_mask = 0xf0,
+       };
+
+       of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
+              of_ti_omap3_core_dpll_setup);
+
+static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1 << 1,
+               .enable_mask = 0x7 << 16,
+               .autoidle_mask = 0x7 << 3,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .freqsel_mask = 0xf00000,
+               .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
+              of_ti_omap3_per_dpll_setup);
+
+static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1 << 1,
+               .enable_mask = 0x7 << 16,
+               .autoidle_mask = 0x7 << 3,
+               .mult_mask = 0xfff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 4095,
+               .max_divider = 128,
+               .min_divider = 1,
+               .sddiv_mask = 0xff << 24,
+               .dco_mask = 0xe << 20,
+               .flags = DPLL_J_TYPE,
+               .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
+              of_ti_omap3_per_jtype_dpll_setup);
+#endif
+
+static void __init of_ti_omap4_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
+              of_ti_omap4_dpll_setup);
+
+static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
+              of_ti_omap4_core_dpll_setup);
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX)
+static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .m4xen_mask = 0x800,
+               .lpmode_mask = 1 << 10,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
+              of_ti_omap4_m4xen_dpll_setup);
+
+static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0xfff << 8,
+               .div1_mask = 0xff,
+               .max_multiplier = 4095,
+               .max_divider = 256,
+               .min_divider = 1,
+               .sddiv_mask = 0xff << 24,
+               .flags = DPLL_J_TYPE,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+}
+CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
+              of_ti_omap4_jtype_dpll_setup);
+#endif
+
+static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
+              of_ti_am3_no_gate_dpll_setup);
+
+static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 4095,
+               .max_divider = 256,
+               .min_divider = 2,
+               .flags = DPLL_J_TYPE,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
+              of_ti_am3_jtype_dpll_setup);
+
+static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .flags = DPLL_J_TYPE,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
+              "ti,am3-dpll-no-gate-j-type-clock",
+              of_ti_am3_no_gate_jtype_dpll_setup);
+
+static void __init of_ti_am3_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
+
+static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0);
+}
+CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
+              of_ti_am3_core_dpll_setup);
diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c
new file mode 100644 (file)
index 0000000..c2c8a28
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * TI Fixed Factor Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+/**
+ * of_ti_fixed_factor_clk_setup - Setup function for TI fixed factor clock
+ * @node: device node for this clock
+ *
+ * Sets up a simple fixed factor clock based on device tree info.
+ */
+static void __init of_ti_fixed_factor_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char *parent_name;
+       u32 div, mult;
+       u32 flags = 0;
+
+       if (of_property_read_u32(node, "ti,clock-div", &div)) {
+               pr_err("%s must have a clock-div property\n", node->name);
+               return;
+       }
+
+       if (of_property_read_u32(node, "ti,clock-mult", &mult)) {
+               pr_err("%s must have a clock-mult property\n", node->name);
+               return;
+       }
+
+       if (of_property_read_bool(node, "ti,set-rate-parent"))
+               flags |= CLK_SET_RATE_PARENT;
+
+       parent_name = of_clk_get_parent_name(node, 0);
+
+       clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags,
+                                       mult, div);
+
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               of_ti_clk_autoidle_setup(node);
+       }
+}
+CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
+              of_ti_fixed_factor_clk_setup);
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
new file mode 100644 (file)
index 0000000..3e2999d
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * OMAP gate clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk);
+
+static const struct clk_ops omap_gate_clkdm_clk_ops = {
+       .init           = &omap2_init_clk_clkdm,
+       .enable         = &omap2_clkops_enable_clkdm,
+       .disable        = &omap2_clkops_disable_clkdm,
+};
+
+static const struct clk_ops omap_gate_clk_ops = {
+       .init           = &omap2_init_clk_clkdm,
+       .enable         = &omap2_dflt_clk_enable,
+       .disable        = &omap2_dflt_clk_disable,
+       .is_enabled     = &omap2_dflt_clk_is_enabled,
+};
+
+static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
+       .init           = &omap2_init_clk_clkdm,
+       .enable         = &omap36xx_gate_clk_enable_with_hsdiv_restore,
+       .disable        = &omap2_dflt_clk_disable,
+       .is_enabled     = &omap2_dflt_clk_is_enabled,
+};
+
+/**
+ * omap36xx_gate_clk_enable_with_hsdiv_restore - enable clocks suffering
+ *         from HSDivider PWRDN problem Implements Errata ID: i556.
+ * @clk: DPLL output struct clk
+ *
+ * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
+ * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
+ * valueafter their respective PWRDN bits are set.  Any dummy write
+ * (Any other value different from the Read value) to the
+ * corresponding CM_CLKSEL register will refresh the dividers.
+ */
+static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
+{
+       struct clk_divider *parent;
+       struct clk_hw *parent_hw;
+       u32 dummy_v, orig_v;
+       int ret;
+
+       /* Clear PWRDN bit of HSDIVIDER */
+       ret = omap2_dflt_clk_enable(clk);
+
+       /* Parent is the x2 node, get parent of parent for the m2 div */
+       parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk)));
+       parent = to_clk_divider(parent_hw);
+
+       /* Restore the dividers */
+       if (!ret) {
+               orig_v = ti_clk_ll_ops->clk_readl(parent->reg);
+               dummy_v = orig_v;
+
+               /* Write any other value different from the Read value */
+               dummy_v ^= (1 << parent->shift);
+               ti_clk_ll_ops->clk_writel(dummy_v, parent->reg);
+
+               /* Write the original divider */
+               ti_clk_ll_ops->clk_writel(orig_v, parent->reg);
+       }
+
+       return ret;
+}
+
+static void __init _of_ti_gate_clk_setup(struct device_node *node,
+                                        const struct clk_ops *ops,
+                                        const struct clk_hw_omap_ops *hw_ops)
+{
+       struct clk *clk;
+       struct clk_init_data init = { NULL };
+       struct clk_hw_omap *clk_hw;
+       const char *clk_name = node->name;
+       const char *parent_name;
+       u32 val;
+
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       if (!clk_hw)
+               return;
+
+       clk_hw->hw.init = &init;
+
+       init.name = clk_name;
+       init.ops = ops;
+
+       if (ops != &omap_gate_clkdm_clk_ops) {
+               clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0);
+               if (!clk_hw->enable_reg)
+                       goto cleanup;
+
+               if (!of_property_read_u32(node, "ti,bit-shift", &val))
+                       clk_hw->enable_bit = val;
+       }
+
+       clk_hw->ops = hw_ops;
+
+       clk_hw->flags = MEMMAP_ADDRESSING;
+
+       if (of_clk_get_parent_count(node) != 1) {
+               pr_err("%s must have 1 parent\n", clk_name);
+               goto cleanup;
+       }
+
+       parent_name = of_clk_get_parent_name(node, 0);
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       if (of_property_read_bool(node, "ti,set-rate-parent"))
+               init.flags |= CLK_SET_RATE_PARENT;
+
+       if (of_property_read_bool(node, "ti,set-bit-to-disable"))
+               clk_hw->flags |= INVERT_ENABLE;
+
+       clk = clk_register(NULL, &clk_hw->hw);
+
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               return;
+       }
+
+cleanup:
+       kfree(clk_hw);
+}
+
+static void __init
+_of_ti_composite_gate_clk_setup(struct device_node *node,
+                               const struct clk_hw_omap_ops *hw_ops)
+{
+       struct clk_hw_omap *gate;
+       u32 val = 0;
+
+       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+       if (!gate)
+               return;
+
+       gate->enable_reg = ti_clk_get_reg_addr(node, 0);
+       if (!gate->enable_reg)
+               goto cleanup;
+
+       of_property_read_u32(node, "ti,bit-shift", &val);
+
+       gate->enable_bit = val;
+       gate->ops = hw_ops;
+       gate->flags = MEMMAP_ADDRESSING;
+
+       if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
+               return;
+
+cleanup:
+       kfree(gate);
+}
+
+static void __init
+of_ti_composite_no_wait_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_composite_gate_clk_setup(node, NULL);
+}
+CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock",
+              of_ti_composite_no_wait_gate_clk_setup);
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init of_ti_composite_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait);
+}
+CLK_OF_DECLARE(ti_composite_interface_clk, "ti,composite-interface-clock",
+              of_ti_composite_interface_clk_setup);
+#endif
+
+static void __init of_ti_composite_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_composite_gate_clk_setup(node, &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_composite_gate_clk, "ti,composite-gate-clock",
+              of_ti_composite_gate_clk_setup);
+
+
+static void __init of_ti_clkdm_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clkdm_clk_ops, NULL);
+}
+CLK_OF_DECLARE(ti_clkdm_gate_clk, "ti,clkdm-gate-clock",
+              of_ti_clkdm_gate_clk_setup);
+
+static void __init of_ti_hsdiv_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clk_hsdiv_restore_ops,
+                             &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_hsdiv_gate_clk, "ti,hsdiv-gate-clock",
+              of_ti_hsdiv_gate_clk_setup);
+
+static void __init of_ti_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clk_ops, NULL);
+}
+CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup)
+
+static void __init of_ti_wait_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clk_ops, &clkhwops_wait);
+}
+CLK_OF_DECLARE(ti_wait_gate_clk, "ti,wait-gate-clock",
+              of_ti_wait_gate_clk_setup);
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init of_ti_am35xx_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clk_ops,
+                             &clkhwops_am35xx_ipss_module_wait);
+}
+CLK_OF_DECLARE(ti_am35xx_gate_clk, "ti,am35xx-gate-clock",
+              of_ti_am35xx_gate_clk_setup);
+
+static void __init of_ti_dss_gate_clk_setup(struct device_node *node)
+{
+       _of_ti_gate_clk_setup(node, &omap_gate_clk_ops,
+                             &clkhwops_omap3430es2_dss_usbhost_wait);
+}
+CLK_OF_DECLARE(ti_dss_gate_clk, "ti,dss-gate-clock",
+              of_ti_dss_gate_clk_setup);
+#endif
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
new file mode 100644 (file)
index 0000000..320a2b1
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * OMAP interface clock support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+static const struct clk_ops ti_interface_clk_ops = {
+       .init           = &omap2_init_clk_clkdm,
+       .enable         = &omap2_dflt_clk_enable,
+       .disable        = &omap2_dflt_clk_disable,
+       .is_enabled     = &omap2_dflt_clk_is_enabled,
+};
+
+static void __init _of_ti_interface_clk_setup(struct device_node *node,
+                                             const struct clk_hw_omap_ops *ops)
+{
+       struct clk *clk;
+       struct clk_init_data init = { NULL };
+       struct clk_hw_omap *clk_hw;
+       const char *parent_name;
+       u32 val;
+
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       if (!clk_hw)
+               return;
+
+       clk_hw->hw.init = &init;
+       clk_hw->ops = ops;
+       clk_hw->flags = MEMMAP_ADDRESSING;
+
+       clk_hw->enable_reg = ti_clk_get_reg_addr(node, 0);
+       if (!clk_hw->enable_reg)
+               goto cleanup;
+
+       if (!of_property_read_u32(node, "ti,bit-shift", &val))
+               clk_hw->enable_bit = val;
+
+       init.name = node->name;
+       init.ops = &ti_interface_clk_ops;
+       init.flags = 0;
+
+       parent_name = of_clk_get_parent_name(node, 0);
+       if (!parent_name) {
+               pr_err("%s must have a parent\n", node->name);
+               goto cleanup;
+       }
+
+       init.num_parents = 1;
+       init.parent_names = &parent_name;
+
+       clk = clk_register(NULL, &clk_hw->hw);
+
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               omap2_init_clk_hw_omap_clocks(clk);
+               return;
+       }
+
+cleanup:
+       kfree(clk_hw);
+}
+
+static void __init of_ti_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node, &clkhwops_iclk_wait);
+}
+CLK_OF_DECLARE(ti_interface_clk, "ti,omap3-interface-clock",
+              of_ti_interface_clk_setup);
+
+static void __init of_ti_no_wait_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node, &clkhwops_iclk);
+}
+CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock",
+              of_ti_no_wait_interface_clk_setup);
+
+static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node,
+                                  &clkhwops_omap3430es2_iclk_hsotgusb_wait);
+}
+CLK_OF_DECLARE(ti_hsotgusb_interface_clk, "ti,omap3-hsotgusb-interface-clock",
+              of_ti_hsotgusb_interface_clk_setup);
+
+static void __init of_ti_dss_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node,
+                                  &clkhwops_omap3430es2_iclk_dss_usbhost_wait);
+}
+CLK_OF_DECLARE(ti_dss_interface_clk, "ti,omap3-dss-interface-clock",
+              of_ti_dss_interface_clk_setup);
+
+static void __init of_ti_ssi_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node, &clkhwops_omap3430es2_iclk_ssi_wait);
+}
+CLK_OF_DECLARE(ti_ssi_interface_clk, "ti,omap3-ssi-interface-clock",
+              of_ti_ssi_interface_clk_setup);
+
+static void __init of_ti_am35xx_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node, &clkhwops_am35xx_ipss_wait);
+}
+CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock",
+              of_ti_am35xx_interface_clk_setup);
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
new file mode 100644 (file)
index 0000000..0197a47
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * TI Multiplexer Clock
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Tero Kristo <t-kristo@ti.com>
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/ti.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+
+static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       int num_parents = __clk_get_num_parents(hw->clk);
+       u32 val;
+
+       /*
+        * FIXME need a mux-specific flag to determine if val is bitwise or
+        * numeric. e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges
+        * from 0x1 to 0x7 (index starts at one)
+        * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+        * val = 0x4 really means "bit 2, index starts at bit 0"
+        */
+       val = ti_clk_ll_ops->clk_readl(mux->reg) >> mux->shift;
+       val &= mux->mask;
+
+       if (mux->table) {
+               int i;
+
+               for (i = 0; i < num_parents; i++)
+                       if (mux->table[i] == val)
+                               return i;
+               return -EINVAL;
+       }
+
+       if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+               val = ffs(val) - 1;
+
+       if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+               val--;
+
+       if (val >= num_parents)
+               return -EINVAL;
+
+       return val;
+}
+
+static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_mux *mux = to_clk_mux(hw);
+       u32 val;
+       unsigned long flags = 0;
+
+       if (mux->table) {
+               index = mux->table[index];
+       } else {
+               if (mux->flags & CLK_MUX_INDEX_BIT)
+                       index = (1 << ffs(index));
+
+               if (mux->flags & CLK_MUX_INDEX_ONE)
+                       index++;
+       }
+
+       if (mux->lock)
+               spin_lock_irqsave(mux->lock, flags);
+
+       if (mux->flags & CLK_MUX_HIWORD_MASK) {
+               val = mux->mask << (mux->shift + 16);
+       } else {
+               val = ti_clk_ll_ops->clk_readl(mux->reg);
+               val &= ~(mux->mask << mux->shift);
+       }
+       val |= index << mux->shift;
+       ti_clk_ll_ops->clk_writel(val, mux->reg);
+
+       if (mux->lock)
+               spin_unlock_irqrestore(mux->lock, flags);
+
+       return 0;
+}
+
+const struct clk_ops ti_clk_mux_ops = {
+       .get_parent = ti_clk_mux_get_parent,
+       .set_parent = ti_clk_mux_set_parent,
+       .determine_rate = __clk_mux_determine_rate,
+};
+
+static struct clk *_register_mux(struct device *dev, const char *name,
+                                const char **parent_names, u8 num_parents,
+                                unsigned long flags, void __iomem *reg,
+                                u8 shift, u32 mask, u8 clk_mux_flags,
+                                u32 *table, spinlock_t *lock)
+{
+       struct clk_mux *mux;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       /* allocate the mux */
+       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+       if (!mux) {
+               pr_err("%s: could not allocate mux clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = name;
+       init.ops = &ti_clk_mux_ops;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       /* struct clk_mux assignments */
+       mux->reg = reg;
+       mux->shift = shift;
+       mux->mask = mask;
+       mux->flags = clk_mux_flags;
+       mux->lock = lock;
+       mux->table = table;
+       mux->hw.init = &init;
+
+       clk = clk_register(dev, &mux->hw);
+
+       if (IS_ERR(clk))
+               kfree(mux);
+
+       return clk;
+}
+
+/**
+ * of_mux_clk_setup - Setup function for simple mux rate clock
+ * @node: DT node for the clock
+ *
+ * Sets up a basic clock multiplexer.
+ */
+static void of_mux_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       void __iomem *reg;
+       int num_parents;
+       const char **parent_names;
+       int i;
+       u8 clk_mux_flags = 0;
+       u32 mask = 0;
+       u32 shift = 0;
+       u32 flags = 0;
+
+       num_parents = of_clk_get_parent_count(node);
+       if (num_parents < 2) {
+               pr_err("mux-clock %s must have parents\n", node->name);
+               return;
+       }
+       parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
+       if (!parent_names)
+               goto cleanup;
+
+       for (i = 0; i < num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(node, i);
+
+       reg = ti_clk_get_reg_addr(node, 0);
+
+       if (!reg)
+               goto cleanup;
+
+       of_property_read_u32(node, "ti,bit-shift", &shift);
+
+       if (of_property_read_bool(node, "ti,index-starts-at-one"))
+               clk_mux_flags |= CLK_MUX_INDEX_ONE;
+
+       if (of_property_read_bool(node, "ti,set-rate-parent"))
+               flags |= CLK_SET_RATE_PARENT;
+
+       /* Generate bit-mask based on parent info */
+       mask = num_parents;
+       if (!(clk_mux_flags & CLK_MUX_INDEX_ONE))
+               mask--;
+
+       mask = (1 << fls(mask)) - 1;
+
+       clk = _register_mux(NULL, node->name, parent_names, num_parents, flags,
+                           reg, shift, mask, clk_mux_flags, NULL, NULL);
+
+       if (!IS_ERR(clk))
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+cleanup:
+       kfree(parent_names);
+}
+CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
+
+static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
+{
+       struct clk_mux *mux;
+       int num_parents;
+       u32 val;
+
+       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+       if (!mux)
+               return;
+
+       mux->reg = ti_clk_get_reg_addr(node, 0);
+
+       if (!mux->reg)
+               goto cleanup;
+
+       if (!of_property_read_u32(node, "ti,bit-shift", &val))
+               mux->shift = val;
+
+       if (of_property_read_bool(node, "ti,index-starts-at-one"))
+               mux->flags |= CLK_MUX_INDEX_ONE;
+
+       num_parents = of_clk_get_parent_count(node);
+
+       if (num_parents < 2) {
+               pr_err("%s must have parents\n", node->name);
+               goto cleanup;
+       }
+
+       mux->mask = num_parents - 1;
+       mux->mask = (1 << fls(mux->mask)) - 1;
+
+       if (!ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX))
+               return;
+
+cleanup:
+       kfree(mux);
+}
+CLK_OF_DECLARE(ti_composite_mux_clk_setup, "ti,composite-mux-clock",
+              of_ti_composite_mux_clk_setup);
index 0e799516a2ab998ae80c28fb8662ee0384120f9f..eb6935c8ad9449bb1c557ac8c596940fc2919096 100644 (file)
@@ -523,11 +523,11 @@ static DEFINE_SPINLOCK(address_handler_list_lock);
 static LIST_HEAD(address_handler_list);
 
 const struct fw_address_region fw_high_memory_region =
-       { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL,  };
+       { .start = FW_MAX_PHYSICAL_RANGE, .end = 0xffffe0000000ULL, };
 EXPORT_SYMBOL(fw_high_memory_region);
 
 static const struct fw_address_region low_memory_region =
-       { .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
+       { .start = 0x000000000000ULL, .end = FW_MAX_PHYSICAL_RANGE, };
 
 #if 0
 const struct fw_address_region fw_private_region =
@@ -1217,7 +1217,7 @@ static void handle_low_memory(struct fw_card *card, struct fw_request *request,
 }
 
 static struct fw_address_handler low_memory = {
-       .length                 = 0x000100000000ULL,
+       .length                 = FW_MAX_PHYSICAL_RANGE,
        .address_callback       = handle_low_memory,
 };
 
index 515a42c786d0250e580f63ecf12971428592a387..c98764aeeec6112928fcde7ac0907949aab001ea 100644 (file)
@@ -237,6 +237,9 @@ static inline bool is_next_generation(int new_generation, int old_generation)
 
 #define LOCAL_BUS 0xffc0
 
+/* arbitrarily chosen maximum range for physical DMA: 128 TB */
+#define FW_MAX_PHYSICAL_RANGE          (128ULL << 40)
+
 void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
 void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
 int fw_get_response_length(struct fw_request *request);
index 6aa8a86cb83b33223aa7e2d26db2308aa440bdd8..6f74d8d3f70015a089f02948294454863cb6bcd7 100644 (file)
@@ -370,6 +370,10 @@ MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
        ", busReset events = "  __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
        ", or a combination, or all = -1)");
 
+static bool param_remote_dma;
+module_param_named(remote_dma, param_remote_dma, bool, 0444);
+MODULE_PARM_DESC(remote_dma, "Enable unfiltered remote DMA (default = N)");
+
 static void log_irqs(struct fw_ohci *ohci, u32 evt)
 {
        if (likely(!(param_debug &
@@ -2050,10 +2054,10 @@ static void bus_reset_work(struct work_struct *work)
                          be32_to_cpu(ohci->next_header));
        }
 
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
-       reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
-       reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
-#endif
+       if (param_remote_dma) {
+               reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
+               reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
+       }
 
        spin_unlock_irq(&ohci->lock);
 
@@ -2363,7 +2367,7 @@ static int ohci_enable(struct fw_card *card,
        reg_write(ohci, OHCI1394_FairnessControl, 0);
        card->priority_budget_implemented = ohci->pri_req_max != 0;
 
-       reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+       reg_write(ohci, OHCI1394_PhyUpperBound, FW_MAX_PHYSICAL_RANGE >> 16);
        reg_write(ohci, OHCI1394_IntEventClear, ~0);
        reg_write(ohci, OHCI1394_IntMaskClear, ~0);
 
@@ -2587,13 +2591,13 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
 static int ohci_enable_phys_dma(struct fw_card *card,
                                int node_id, int generation)
 {
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
-       return 0;
-#else
        struct fw_ohci *ohci = fw_ohci(card);
        unsigned long flags;
        int n, ret = 0;
 
+       if (param_remote_dma)
+               return 0;
+
        /*
         * FIXME:  Make sure this bitmask is cleared when we clear the busReset
         * interrupt bit.  Clear physReqResourceAllBuses on bus reset.
@@ -2622,7 +2626,6 @@ static int ohci_enable_phys_dma(struct fw_card *card,
        spin_unlock_irqrestore(&ohci->lock, flags);
 
        return ret;
-#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
 }
 
 static u32 ohci_read_csr(struct fw_card *card, int csr_offset)
@@ -3720,9 +3723,11 @@ static int pci_probe(struct pci_dev *dev,
        version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
        ohci_notice(ohci,
                    "added OHCI v%x.%x device as card %d, "
-                   "%d IR + %d IT contexts, quirks 0x%x\n",
+                   "%d IR + %d IT contexts, quirks 0x%x%s\n",
                    version >> 16, version & 0xff, ohci->card.index,
-                   ohci->n_ir, ohci->n_it, ohci->quirks);
+                   ohci->n_ir, ohci->n_it, ohci->quirks,
+                   reg_read(ohci, OHCI1394_PhyUpperBound) ?
+                       ", >4 GB phys DMA" : "");
 
        return 0;
 
index 2f21b0bfe6534c6478b6ee6ec8fbd8c86351329e..29c8cdda82a11dd423c4c5683c0244eaebf0de8f 100644 (file)
@@ -12,8 +12,7 @@ menu "Google Firmware Drivers"
 
 config GOOGLE_SMI
        tristate "SMI interface for Google platforms"
-       depends on ACPI && DMI
-       select EFI
+       depends on ACPI && DMI && EFI
        select EFI_VARS
        help
          Say Y here if you want to enable SMI callbacks for Google
index 6490a2dea96b01526657615ceb7139d9b1603a55..f079ca2f260b605ae5f20b7f1010d653baad22e2 100644 (file)
@@ -9,7 +9,9 @@
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
 #include <linux/cdrom.h>
+#include <linux/ide.h>
 #include <scsi/scsi.h>
+#include "ide-cd.h"
 
 #ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS
 void ide_cd_log_error(const char *name, struct request *failed_command,
index a8c2c8f8660a6a312c7d6767f9a0fee14abf79e1..40e683a84ff91b61ebd7487cd6e074528c7d3c67 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/string.h>
+#include <linux/ide.h>
 
 static struct ide_pio_info {
        const char      *name;
index 3c972b2f989335e4df54aa8436cbd99a7f19ba09..e387f41a9cb7667f3542f510b4a954d299e1d316 100644 (file)
@@ -242,18 +242,14 @@ EXPORT_SYMBOL_GPL(led_trigger_unregister);
 void led_trigger_event(struct led_trigger *trig,
                        enum led_brightness brightness)
 {
-       struct list_head *entry;
+       struct led_classdev *led_cdev;
 
        if (!trig)
                return;
 
        read_lock(&trig->leddev_list_lock);
-       list_for_each(entry, &trig->led_cdevs) {
-               struct led_classdev *led_cdev;
-
-               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+       list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list)
                led_set_brightness(led_cdev, brightness);
-       }
        read_unlock(&trig->leddev_list_lock);
 }
 EXPORT_SYMBOL_GPL(led_trigger_event);
@@ -264,16 +260,13 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
                             int oneshot,
                             int invert)
 {
-       struct list_head *entry;
+       struct led_classdev *led_cdev;
 
        if (!trig)
                return;
 
        read_lock(&trig->leddev_list_lock);
-       list_for_each(entry, &trig->led_cdevs) {
-               struct led_classdev *led_cdev;
-
-               led_cdev = list_entry(entry, struct led_classdev, trig_list);
+       list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
                if (oneshot)
                        led_blink_set_oneshot(led_cdev, delay_on, delay_off,
                                              invert);
index a97263e902ffc6b927db6b935cb290902909f21e..2ec34cfcedcee613aebd97bae8c06966b826f404 100644 (file)
@@ -152,12 +152,26 @@ static void lp5521_load_engine(struct lp55xx_chip *chip)
        lp5521_wait_opmode_done();
 }
 
-static void lp5521_stop_engine(struct lp55xx_chip *chip)
+static void lp5521_stop_all_engines(struct lp55xx_chip *chip)
 {
        lp55xx_write(chip, LP5521_REG_OP_MODE, 0);
        lp5521_wait_opmode_done();
 }
 
+static void lp5521_stop_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP5521_MODE_R_M,
+               [LP55XX_ENGINE_2] = LP5521_MODE_G_M,
+               [LP55XX_ENGINE_3] = LP5521_MODE_B_M,
+       };
+
+       lp55xx_update_bits(chip, LP5521_REG_OP_MODE, mask[idx], 0);
+
+       lp5521_wait_opmode_done();
+}
+
 static void lp5521_run_engine(struct lp55xx_chip *chip, bool start)
 {
        int ret;
@@ -564,7 +578,7 @@ static int lp5521_remove(struct i2c_client *client)
        struct lp55xx_led *led = i2c_get_clientdata(client);
        struct lp55xx_chip *chip = led->chip;
 
-       lp5521_stop_engine(chip);
+       lp5521_stop_all_engines(chip);
        lp55xx_unregister_sysfs(chip);
        lp55xx_unregister_leds(led, chip);
        lp55xx_deinit_device(chip);
index 3a0bc886a87a2c88782c9b075f0eba935271ebc2..4ade66a2d9d4758b314c45ed52a222ff0cb0aeca 100644 (file)
@@ -195,12 +195,26 @@ static void lp5523_load_engine_and_select_page(struct lp55xx_chip *chip)
        lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, page_sel[idx]);
 }
 
-static void lp5523_stop_engine(struct lp55xx_chip *chip)
+static void lp5523_stop_all_engines(struct lp55xx_chip *chip)
 {
        lp55xx_write(chip, LP5523_REG_OP_MODE, 0);
        lp5523_wait_opmode_done();
 }
 
+static void lp5523_stop_engine(struct lp55xx_chip *chip)
+{
+       enum lp55xx_engine_index idx = chip->engine_idx;
+       u8 mask[] = {
+               [LP55XX_ENGINE_1] = LP5523_MODE_ENG1_M,
+               [LP55XX_ENGINE_2] = LP5523_MODE_ENG2_M,
+               [LP55XX_ENGINE_3] = LP5523_MODE_ENG3_M,
+       };
+
+       lp55xx_update_bits(chip, LP5523_REG_OP_MODE, mask[idx], 0);
+
+       lp5523_wait_opmode_done();
+}
+
 static void lp5523_turn_off_channels(struct lp55xx_chip *chip)
 {
        int i;
@@ -311,7 +325,7 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
        }
 
 out:
-       lp5523_stop_engine(chip);
+       lp5523_stop_all_engines(chip);
        return ret;
 }
 
@@ -782,7 +796,7 @@ static int lp5523_remove(struct i2c_client *client)
        struct lp55xx_led *led = i2c_get_clientdata(client);
        struct lp55xx_chip *chip = led->chip;
 
-       lp5523_stop_engine(chip);
+       lp5523_stop_all_engines(chip);
        lp55xx_unregister_sysfs(chip);
        lp55xx_unregister_leds(led, chip);
        lp55xx_deinit_device(chip);
index 9acc6bb7deef01f153e5c71044ac93be7e983ba9..88317b4f7bf3abf70e4337a12aa682646e8a2e56 100644 (file)
@@ -210,6 +210,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
 {
        struct lp55xx_chip *chip = context;
        struct device *dev = &chip->cl->dev;
+       enum lp55xx_engine_index idx = chip->engine_idx;
 
        if (!fw) {
                dev_err(dev, "firmware request failed\n");
@@ -219,6 +220,7 @@ static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
        /* handling firmware data is chip dependent */
        mutex_lock(&chip->lock);
 
+       chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD;
        chip->fw = fw;
        if (chip->cfg->firmware_cb)
                chip->cfg->firmware_cb(chip);
index fa9b439323bd06d0d126a48a7828e4b47665c6b5..ca87a1b4a0db228896ca19dc410885eaa53eb7f3 100644 (file)
@@ -117,9 +117,7 @@ static void mc13xxx_led_work(struct work_struct *work)
                BUG();
        }
 
-       mc13xxx_lock(led->master);
        mc13xxx_reg_rmw(led->master, reg, mask << shift, value << shift);
-       mc13xxx_unlock(led->master);
 }
 
 static void mc13xxx_led_set(struct led_classdev *led_cdev,
@@ -132,75 +130,6 @@ static void mc13xxx_led_set(struct led_classdev *led_cdev,
        schedule_work(&led->work);
 }
 
-static int __init mc13xxx_led_setup(struct mc13xxx_led *led, int max_current)
-{
-       int shift, mask, reg, ret, bank;
-
-       switch (led->id) {
-       case MC13783_LED_MD:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 0;
-               mask = 0x07;
-               break;
-       case MC13783_LED_AD:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 3;
-               mask = 0x07;
-               break;
-       case MC13783_LED_KP:
-               reg = MC13XXX_REG_LED_CONTROL(2);
-               shift = 6;
-               mask = 0x07;
-               break;
-       case MC13783_LED_R1:
-       case MC13783_LED_G1:
-       case MC13783_LED_B1:
-       case MC13783_LED_R2:
-       case MC13783_LED_G2:
-       case MC13783_LED_B2:
-       case MC13783_LED_R3:
-       case MC13783_LED_G3:
-       case MC13783_LED_B3:
-               bank = (led->id - MC13783_LED_R1) / 3;
-               reg = MC13XXX_REG_LED_CONTROL(3) + bank;
-               shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2;
-               mask = 0x03;
-               break;
-       case MC13892_LED_MD:
-               reg = MC13XXX_REG_LED_CONTROL(0);
-               shift = 9;
-               mask = 0x07;
-               break;
-       case MC13892_LED_AD:
-               reg = MC13XXX_REG_LED_CONTROL(0);
-               shift = 21;
-               mask = 0x07;
-               break;
-       case MC13892_LED_KP:
-               reg = MC13XXX_REG_LED_CONTROL(1);
-               shift = 9;
-               mask = 0x07;
-               break;
-       case MC13892_LED_R:
-       case MC13892_LED_G:
-       case MC13892_LED_B:
-               bank = (led->id - MC13892_LED_R) / 2;
-               reg = MC13XXX_REG_LED_CONTROL(2) + bank;
-               shift = ((led->id - MC13892_LED_R) - bank * 2) * 12 + 9;
-               mask = 0x07;
-               break;
-       default:
-               BUG();
-       }
-
-       mc13xxx_lock(led->master);
-       ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
-                             max_current << shift);
-       mc13xxx_unlock(led->master);
-
-       return ret;
-}
-
 static int __init mc13xxx_led_probe(struct platform_device *pdev)
 {
        struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -233,31 +162,22 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
        leds->num_leds = num_leds;
        platform_set_drvdata(pdev, leds);
 
-       mc13xxx_lock(mcdev);
        for (i = 0; i < devtype->num_regs; i++) {
                reg = pdata->led_control[i];
                WARN_ON(reg >= (1 << 24));
                ret = mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), reg);
                if (ret)
-                       break;
-       }
-       mc13xxx_unlock(mcdev);
-
-       if (ret) {
-               dev_err(&pdev->dev, "Unable to init LED driver\n");
-               return ret;
+                       return ret;
        }
 
        for (i = 0; i < num_leds; i++) {
                const char *name, *trig;
-               char max_current;
 
                ret = -EINVAL;
 
                id = pdata->led[i].id;
                name = pdata->led[i].name;
                trig = pdata->led[i].default_trigger;
-               max_current = pdata->led[i].max_current;
 
                if ((id > devtype->led_max) || (id < devtype->led_min)) {
                        dev_err(&pdev->dev, "Invalid ID %i\n", id);
@@ -280,11 +200,6 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
 
                INIT_WORK(&leds->led[i].work, mc13xxx_led_work);
 
-               ret = mc13xxx_led_setup(&leds->led[i], max_current);
-               if (ret) {
-                       dev_err(&pdev->dev, "Unable to setup LED %i\n", id);
-                       break;
-               }
                ret = led_classdev_register(pdev->dev.parent,
                                            &leds->led[i].cdev);
                if (ret) {
@@ -313,10 +228,8 @@ static int mc13xxx_led_remove(struct platform_device *pdev)
                cancel_work_sync(&leds->led[i].work);
        }
 
-       mc13xxx_lock(mcdev);
        for (i = 0; i < leds->devtype->num_regs; i++)
                mc13xxx_reg_write(mcdev, MC13XXX_REG_LED_CONTROL(i), 0);
-       mc13xxx_unlock(mcdev);
 
        return 0;
 }
index b31d8e99c41992c77610fe5ca1694211035ea592..605047428b5ad75e2d67add0edaecb912d35581a 100644 (file)
@@ -66,9 +66,11 @@ static void led_pwm_set(struct led_classdev *led_cdev,
        struct led_pwm_data *led_dat =
                container_of(led_cdev, struct led_pwm_data, cdev);
        unsigned int max = led_dat->cdev.max_brightness;
-       unsigned int period =  led_dat->period;
+       unsigned long long duty =  led_dat->period;
 
-       led_dat->duty = brightness * period / max;
+       duty *= brightness;
+       do_div(duty, max);
+       led_dat->duty = duty;
 
        if (led_dat->can_sleep)
                schedule_work(&led_dat->work);
@@ -85,11 +87,10 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
 static int led_pwm_create_of(struct platform_device *pdev,
                             struct led_pwm_priv *priv)
 {
-       struct device_node *node = pdev->dev.of_node;
        struct device_node *child;
        int ret;
 
-       for_each_child_of_node(node, child) {
+       for_each_child_of_node(pdev->dev.of_node, child) {
                struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
 
                led_dat->cdev.name = of_get_property(child, "label",
index 87cf215af798c97076df857b0609292c1f752cfe..98174e7240ee9f41b8a4d0cddae494ebff99da65 100644 (file)
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 
-#include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 #include <plat/gpio-cfg.h>
-#include <linux/platform_data/leds-s3c24xx.h>
 
 /* our context */
 
index 8cc304f36728a4e217cbf6716f893a3e6f5aed0c..3d9e267a56c428580bfaa074ce08053bd86ae34a 100644 (file)
@@ -4,77 +4,87 @@
  * The TCA6507 is a programmable LED controller that can drive 7
  * separate lines either by holding them low, or by pulsing them
  * with modulated width.
- * The modulation can be varied in a simple pattern to produce a blink or
- * double-blink.
+ * The modulation can be varied in a simple pattern to produce a
+ * blink or double-blink.
  *
- * This driver can configure each line either as a 'GPIO' which is out-only
- * (no pull-up) or as an LED with variable brightness and hardware-assisted
- * blinking.
+ * This driver can configure each line either as a 'GPIO' which is
+ * out-only (pull-up resistor required) or as an LED with variable
+ * brightness and hardware-assisted blinking.
  *
- * Apart from OFF and ON there are three programmable brightness levels which
- * can be programmed from 0 to 15 and indicate how many 500usec intervals in
- * each 8msec that the led is 'on'.  The levels are named MASTER, BANK0 and
- * BANK1.
+ * Apart from OFF and ON there are three programmable brightness
+ * levels which can be programmed from 0 to 15 and indicate how many
+ * 500usec intervals in each 8msec that the led is 'on'.  The levels
+ * are named MASTER, BANK0 and BANK1.
  *
- * There are two different blink rates that can be programmed, each with
- * separate time for rise, on, fall, off and second-off.  Thus if 3 or more
- * different non-trivial rates are required, software must be used for the extra
- * rates. The two different blink rates must align with the two levels BANK0 and
- * BANK1.
- * This driver does not support double-blink so 'second-off' always matches
- * 'off'.
+ * There are two different blink rates that can be programmed, each
+ * with separate time for rise, on, fall, off and second-off.  Thus if
+ * 3 or more different non-trivial rates are required, software must
+ * be used for the extra rates. The two different blink rates must
+ * align with the two levels BANK0 and BANK1.  This driver does not
+ * support double-blink so 'second-off' always matches 'off'.
  *
- * Only 16 different times can be programmed in a roughly logarithmic scale from
- * 64ms to 16320ms.  To be precise the possible times are:
+ * Only 16 different times can be programmed in a roughly logarithmic
+ * scale from 64ms to 16320ms.  To be precise the possible times are:
  *    0, 64, 128, 192, 256, 384, 512, 768,
  *    1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
  *
- * Times that cannot be closely matched with these must be
- * handled in software.  This driver allows 12.5% error in matching.
+ * Times that cannot be closely matched with these must be handled in
+ * software.  This driver allows 12.5% error in matching.
  *
- * This driver does not allow rise/fall rates to be set explicitly.  When trying
- * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
- * 'hold' times are chosen to get a close match.  If the target delay is even,
- * the 'change' number will be the smaller; if odd, the 'hold' number will be
- * the smaller.
-
- * Choosing pairs of delays with 12.5% errors allows us to match delays in the
- * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
- * 26% of the achievable sums can be matched by multiple pairings. For example
- * 1536 == 1536+0, 1024+512, or 768+768.  This driver will always choose the
- * pairing with the least maximum - 768+768 in this case.  Other pairings are
- * not available.
+ * This driver does not allow rise/fall rates to be set explicitly.
+ * When trying to match a given 'on' or 'off' period, an appropriate
+ * pair of 'change' and 'hold' times are chosen to get a close match.
+ * If the target delay is even, the 'change' number will be the
+ * smaller; if odd, the 'hold' number will be the smaller.
+
+ * Choosing pairs of delays with 12.5% errors allows us to match
+ * delays in the ranges: 56-72, 112-144, 168-216, 224-27504,
+ * 28560-36720.
+ * 26% of the achievable sums can be matched by multiple pairings.
+ * For example 1536 == 1536+0, 1024+512, or 768+768.
+ * This driver will always choose the pairing with the least
+ * maximum - 768+768 in this case.  Other pairings are not available.
  *
- * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
- * Access can be shared by multiple leds if they have the same level and
- * either same blink rates, or some don't blink.
- * When a led changes, it relinquishes access and tries again, so it might
- * lose access to hardware blink.
- * If a blink engine cannot be allocated, software blink is used.
- * If the desired brightness cannot be allocated, the closest available non-zero
- * brightness is used.  As 'full' is always available, the worst case would be
- * to have two different blink rates at '1', with Max at '2', then other leds
- * will have to choose between '2' and '16'.  Hopefully this is not likely.
+ * Access to the 3 levels and 2 blinks are on a first-come,
+ * first-served basis.  Access can be shared by multiple leds if they
+ * have the same level and either same blink rates, or some don't
+ * blink.  When a led changes, it relinquishes access and tries again,
+ * so it might lose access to hardware blink.
  *
- * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
- * and LEDs using the blink.  It can only be reprogrammed when the appropriate
- * counter is zero.  The MASTER level has a single usage count.
+ * If a blink engine cannot be allocated, software blink is used.  If
+ * the desired brightness cannot be allocated, the closest available
+ * non-zero brightness is used.  As 'full' is always available, the
+ * worst case would be to have two different blink rates at '1', with
+ * Max at '2', then other leds will have to choose between '2' and
+ * '16'.  Hopefully this is not likely.
  *
- * Each Led has programmable 'on' and 'off' time as milliseconds.  With each
- * there is a flag saying if it was explicitly requested or defaulted.
- * Similarly the banks know if each time was explicit or a default.  Defaults
- * are permitted to be changed freely - they are not recognised when matching.
+ * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the
+ * brightness and LEDs using the blink.  It can only be reprogrammed
+ * when the appropriate counter is zero.  The MASTER level has a
+ * single usage count.
  *
+ * Each LED has programmable 'on' and 'off' time as milliseconds.
+ * With each there is a flag saying if it was explicitly requested or
+ * defaulted.  Similarly the banks know if each time was explicit or a
+ * default.  Defaults are permitted to be changed freely - they are
+ * not recognised when matching.
  *
- * An led-tca6507 device must be provided with platform data.  This data
- * lists for each output: the name, default trigger, and whether the signal
- * is being used as a GPiO rather than an led.  'struct led_plaform_data'
- * is used for this.  If 'name' is NULL, the output isn't used.  If 'flags'
- * is TCA6507_MAKE_CPIO, the output is a GPO.
- * The "struct led_platform_data" can be embedded in a
- * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
- * and a 'setup' callback which is called once the GPiOs are available.
  *
+ * An led-tca6507 device must be provided with platform data or
+ * configured via devicetree.
+ *
+ * The platform-data lists for each output: the name, default trigger,
+ * and whether the signal is being used as a GPIO rather than an LED.
+ * 'struct led_plaform_data' is used for this.  If 'name' is NULL, the
+ * output isn't used.  If 'flags' is TCA6507_MAKE_GPIO, the output is
+ * a GPO.  The "struct led_platform_data" can be embedded in a "struct
+ * tca6507_platform_data" which adds a 'gpio_base' for the GPIOs, and
+ * a 'setup' callback which is called once the GPIOs are available.
+ *
+ * When configured via devicetree there is one child for each output.
+ * The "reg" determines the output number and "compatible" determines
+ * whether it is an LED or a GPIO.  "linux,default-trigger" can set a
+ * default trigger.
  */
 
 #include <linux/module.h>
@@ -192,17 +202,18 @@ MODULE_DEVICE_TABLE(i2c, tca6507_id);
 static int choose_times(int msec, int *c1p, int *c2p)
 {
        /*
-        * Choose two timecodes which add to 'msec' as near as possible.
-        * The first returned is the 'on' or 'off' time.  The second is to be
-        * used as a 'fade-on' or 'fade-off' time.  If 'msec' is even,
-        * the first will not be smaller than the second.  If 'msec' is odd,
-        * the first will not be larger than the second.
-        * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
-        * otherwise return the sum that was achieved, plus 1 if the first is
-        * smaller.
-        * If two possibilities are equally good (e.g. 512+0, 256+256), choose
-        * the first pair so there is more change-time visible (i.e. it is
-        * softer).
+        * Choose two timecodes which add to 'msec' as near as
+        * possible.  The first returned is the 'on' or 'off' time.
+        * The second is to be used as a 'fade-on' or 'fade-off' time.
+        * If 'msec' is even, the first will not be smaller than the
+        * second.  If 'msec' is odd, the first will not be larger
+        * than the second.
+        * If we cannot get a sum within 1/8 of 'msec' fail with
+        * -EINVAL, otherwise return the sum that was achieved, plus 1
+        * if the first is smaller.
+        * If two possibilities are equally good (e.g. 512+0,
+        * 256+256), choose the first pair so there is more
+        * change-time visible (i.e. it is softer).
         */
        int c1, c2;
        int tmax = msec * 9 / 8;
@@ -255,8 +266,8 @@ static int choose_times(int msec, int *c1p, int *c2p)
 }
 
 /*
- * Update the register file with the appropriate 3-bit state for
- * the given led.
+ * Update the register file with the appropriate 3-bit state for the
+ * given led.
  */
 static void set_select(struct tca6507_chip *tca, int led, int val)
 {
@@ -274,9 +285,9 @@ static void set_select(struct tca6507_chip *tca, int led, int val)
        }
 }
 
-/* Update the register file with the appropriate 4-bit code for
- * one bank or other.  This can be used for timers, for levels, or
- * for initialisation.
+/* Update the register file with the appropriate 4-bit code for one
+ * bank or other.  This can be used for timers, for levels, or for
+ * initialization.
  */
 static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
 {
@@ -309,7 +320,7 @@ static void set_level(struct tca6507_chip *tca, int bank, int level)
        tca->bank[bank].level = level;
 }
 
-/* Record all relevant time code for a given bank */
+/* Record all relevant time codes for a given bank */
 static void set_times(struct tca6507_chip *tca, int bank)
 {
        int c1, c2;
@@ -317,7 +328,8 @@ static void set_times(struct tca6507_chip *tca, int bank)
 
        result = choose_times(tca->bank[bank].ontime, &c1, &c2);
        dev_dbg(&tca->client->dev,
-               "Chose on  times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               "Chose on  times %d(%d) %d(%d) for %dms\n",
+               c1, time_codes[c1],
                c2, time_codes[c2], tca->bank[bank].ontime);
        set_code(tca, TCA6507_FADE_ON, bank, c2);
        set_code(tca, TCA6507_FULL_ON, bank, c1);
@@ -325,7 +337,8 @@ static void set_times(struct tca6507_chip *tca, int bank)
 
        result = choose_times(tca->bank[bank].offtime, &c1, &c2);
        dev_dbg(&tca->client->dev,
-               "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
+               "Chose off times %d(%d) %d(%d) for %dms\n",
+               c1, time_codes[c1],
                c2, time_codes[c2], tca->bank[bank].offtime);
        set_code(tca, TCA6507_FADE_OFF, bank, c2);
        set_code(tca, TCA6507_FIRST_OFF, bank, c1);
@@ -373,7 +386,8 @@ static void led_release(struct tca6507_led *led)
 
 static int led_prepare(struct tca6507_led *led)
 {
-       /* Assign this led to a bank, configuring that bank if necessary. */
+       /* Assign this led to a bank, configuring that bank if
+        * necessary. */
        int level = TO_LEVEL(led->led_cdev.brightness);
        struct tca6507_chip *tca = led->chip;
        int c1, c2;
@@ -389,10 +403,10 @@ static int led_prepare(struct tca6507_led *led)
 
        if (led->ontime == 0 || led->offtime == 0) {
                /*
-                * Just set the brightness, choosing first usable bank.
-                * If none perfect, choose best.
-                * Count backwards so we check MASTER bank first
-                * to avoid wasting a timer.
+                * Just set the brightness, choosing first usable
+                * bank.  If none perfect, choose best.  Count
+                * backwards so we check MASTER bank first to avoid
+                * wasting a timer.
                 */
                int best = -1;/* full-on */
                int diff = 15-level;
@@ -433,9 +447,9 @@ static int led_prepare(struct tca6507_led *led)
        }
 
        /*
-        * We have on/off time so we need to try to allocate a timing bank.
-        * First check if times are compatible with hardware and give up if
-        * not.
+        * We have on/off time so we need to try to allocate a timing
+        * bank.  First check if times are compatible with hardware
+        * and give up if not.
         */
        if (choose_times(led->ontime, &c1, &c2) < 0)
                return -EINVAL;
@@ -523,8 +537,8 @@ static int led_assign(struct tca6507_led *led)
        err = led_prepare(led);
        if (err) {
                /*
-                * Can only fail on timer setup.  In that case we need to
-                * re-establish as steady level.
+                * Can only fail on timer setup.  In that case we need
+                * to re-establish as steady level.
                 */
                led->ontime = 0;
                led->offtime = 0;
@@ -594,8 +608,8 @@ static void tca6507_gpio_set_value(struct gpio_chip *gc,
 
        spin_lock_irqsave(&tca->lock, flags);
        /*
-        * 'OFF' is floating high, and 'ON' is pulled down, so it has the
-        * inverse sense of 'val'.
+        * 'OFF' is floating high, and 'ON' is pulled down, so it has
+        * the inverse sense of 'val'.
         */
        set_select(tca, tca->gpio_map[offset],
                   val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
@@ -638,6 +652,9 @@ static int tca6507_probe_gpios(struct i2c_client *client,
        tca->gpio.direction_output = tca6507_gpio_direction_output;
        tca->gpio.set = tca6507_gpio_set_value;
        tca->gpio.dev = &client->dev;
+#ifdef CONFIG_OF_GPIO
+       tca->gpio.of_node = of_node_get(client->dev.of_node);
+#endif
        err = gpiochip_add(&tca->gpio);
        if (err) {
                tca->gpio.ngpio = 0;
@@ -682,7 +699,7 @@ tca6507_led_dt_init(struct i2c_client *client)
                return ERR_PTR(-ENODEV);
 
        tca_leds = devm_kzalloc(&client->dev,
-                       sizeof(struct led_info) * count, GFP_KERNEL);
+                       sizeof(struct led_info) * NUM_LEDS, GFP_KERNEL);
        if (!tca_leds)
                return ERR_PTR(-ENOMEM);
 
@@ -695,9 +712,11 @@ tca6507_led_dt_init(struct i2c_client *client)
                        of_get_property(child, "label", NULL) ? : child->name;
                led.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
-
+               led.flags = 0;
+               if (of_property_match_string(child, "compatible", "gpio") >= 0)
+                       led.flags |= TCA6507_MAKE_GPIO;
                ret = of_property_read_u32(child, "reg", &reg);
-               if (ret != 0)
+               if (ret != 0 || reg < 0 || reg >= NUM_LEDS)
                        continue;
 
                tca_leds[reg] = led;
@@ -708,8 +727,10 @@ tca6507_led_dt_init(struct i2c_client *client)
                return ERR_PTR(-ENOMEM);
 
        pdata->leds.leds = tca_leds;
-       pdata->leds.num_leds = count;
-
+       pdata->leds.num_leds = NUM_LEDS;
+#ifdef CONFIG_GPIOLIB
+       pdata->gpio_base = -1;
+#endif
        return pdata;
 }
 
index 9ef32b3df91f060b0b85d399d207faad7c072384..590214ba736c1778181f3a75cccd1aed0d2f71f9 100644 (file)
@@ -133,7 +133,7 @@ static int wf_lm75_probe(struct i2c_client *client,
        lm->inited = 0;
        lm->ds1775 = ds1775;
        lm->i2c = client;
-       lm->sens.name = (char *)name; /* XXX fix constness in structure */
+       lm->sens.name = name;
        lm->sens.ops = &wf_lm75_ops;
        i2c_set_clientdata(client, lm);
 
index 945a25b2f31ea78b82a746d6beff6407341e5db4..87e439b10318de19bcafe544350c0268d444702a 100644 (file)
@@ -95,7 +95,7 @@ static int wf_max6690_probe(struct i2c_client *client,
        }
 
        max->i2c = client;
-       max->sens.name = (char *)name; /* XXX fix constness in structure */
+       max->sens.name = name;
        max->sens.ops = &wf_max6690_ops;
        i2c_set_clientdata(client, max);
 
index 5fab4e6e83013c033c01d2465b4f25c756f39dce..5ebcda39f55407e146ab06d811edd5825939a41d 100644 (file)
@@ -157,10 +157,11 @@ config MTD_BCM47XX_PARTS
 
 comment "User Modules And Translation Layers"
 
+#
+# MTD block device support is select'ed if needed
+#
 config MTD_BLKDEVS
-       tristate "Common interface to block layer for MTD 'translation layers'"
-       depends on BLOCK
-       default n
+       tristate
 
 config MTD_BLOCK
        tristate "Caching block device access to MTD devices"
index 5a3942bf109cd9ccded20d42fc4ee62b36a3ad8e..96a33e3f7b000394c1480260246585531c88b920 100644 (file)
@@ -264,7 +264,8 @@ static struct mtd_part_parser afs_parser = {
 
 static int __init afs_parser_init(void)
 {
-       return register_mtd_parser(&afs_parser);
+       register_mtd_parser(&afs_parser);
+       return 0;
 }
 
 static void __exit afs_parser_exit(void)
index ddc0a4287a4b89c8124dd3629b9647e3ca800b74..7c9172ad26210e1d25c9506889e0cbb54212dbfe 100644 (file)
@@ -139,7 +139,8 @@ static struct mtd_part_parser ar7_parser = {
 
 static int __init ar7_parser_init(void)
 {
-       return register_mtd_parser(&ar7_parser);
+       register_mtd_parser(&ar7_parser);
+       return 0;
 }
 
 static void __exit ar7_parser_exit(void)
index 7a6384b0962a9de2c92dffb81f1fc45d6d89a490..de1eb92e42f57f15f197c3ba21d1831ab6dac06f 100644 (file)
  * Amount of bytes we read when analyzing each block of flash memory.
  * Set it big enough to allow detecting partition and reading important data.
  */
-#define BCM47XXPART_BYTES_TO_READ      0x404
+#define BCM47XXPART_BYTES_TO_READ      0x4e8
 
 /* Magics */
 #define BOARD_DATA_MAGIC               0x5246504D      /* MPFR */
+#define BOARD_DATA_MAGIC2              0xBD0D0BBD
+#define CFE_MAGIC                      0x43464531      /* 1EFC */
 #define FACTORY_MAGIC                  0x59544346      /* FCTY */
 #define POT_MAGIC1                     0x54544f50      /* POTT */
 #define POT_MAGIC2                     0x504f          /* OP */
@@ -102,8 +104,9 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                        continue;
                }
 
-               /* CFE has small NVRAM at 0x400 */
-               if (buf[0x400 / 4] == NVRAM_HEADER) {
+               /* Magic or small NVRAM at 0x400 */
+               if ((buf[0x4e0 / 4] == CFE_MAGIC && buf[0x4e4 / 4] == CFE_MAGIC) ||
+                   (buf[0x400 / 4] == NVRAM_HEADER)) {
                        bcm47xxpart_add_part(&parts[curr_part++], "boot",
                                             offset, MTD_WRITEABLE);
                        continue;
@@ -190,6 +193,21 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                                             offset, 0);
                        continue;
                }
+
+               /* Read middle of the block */
+               if (mtd_read(master, offset + 0x8000, 0x4,
+                            &bytes_read, (uint8_t *)buf) < 0) {
+                       pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
+                              offset);
+                       continue;
+               }
+
+               /* Some devices (ex. WNDR3700v3) don't have a standard 'MPFR' */
+               if (buf[0x000 / 4] == BOARD_DATA_MAGIC2) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "board_data",
+                                            offset, MTD_WRITEABLE);
+                       continue;
+               }
        }
 
        /* Look for NVRAM at the end of the last block. */
@@ -243,7 +261,8 @@ static struct mtd_part_parser bcm47xxpart_mtd_parser = {
 
 static int __init bcm47xxpart_init(void)
 {
-       return register_mtd_parser(&bcm47xxpart_mtd_parser);
+       register_mtd_parser(&bcm47xxpart_mtd_parser);
+       return 0;
 }
 
 static void __exit bcm47xxpart_exit(void)
index 5c813907661c3415c979b1176bf937f7c086f2c8..b2443f7031c9afb0bda808a37b6da7e8113d0a61 100644 (file)
@@ -221,7 +221,8 @@ static struct mtd_part_parser bcm63xx_cfe_parser = {
 
 static int __init bcm63xx_cfe_parser_init(void)
 {
-       return register_mtd_parser(&bcm63xx_cfe_parser);
+       register_mtd_parser(&bcm63xx_cfe_parser);
+       return 0;
 }
 
 static void __exit bcm63xx_cfe_parser_exit(void)
index 721caebbc5cc21344a58a710d466205f75f845ef..3e829b37af8d0e0d5c73eff2c03e054ed6516eab 100644 (file)
@@ -395,7 +395,8 @@ static int __init cmdline_parser_init(void)
 {
        if (mtdparts)
                mtdpart_setup(mtdparts);
-       return register_mtd_parser(&cmdline_parser);
+       register_mtd_parser(&cmdline_parser);
+       return 0;
 }
 
 static void __exit cmdline_parser_exit(void)
index 4f091c1a9981c060e3ea2cae43960ade8b4bc2f7..dd5e1018d37b39e9301c9c43e01195f4f363a66c 100644 (file)
@@ -2047,21 +2047,21 @@ static int __init docg3_probe(struct platform_device *pdev)
        ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!ress) {
                dev_err(dev, "No I/O memory resource defined\n");
-               goto noress;
+               return ret;
        }
-       base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+       base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE);
 
        ret = -ENOMEM;
-       cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS,
-                         GFP_KERNEL);
+       cascade = devm_kzalloc(dev, sizeof(*cascade) * DOC_MAX_NBFLOORS,
+                              GFP_KERNEL);
        if (!cascade)
-               goto nomem1;
+               return ret;
        cascade->base = base;
        mutex_init(&cascade->lock);
        cascade->bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
                             DOC_ECC_BCH_PRIMPOLY);
        if (!cascade->bch)
-               goto nomem2;
+               return ret;
 
        for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
                mtd = doc_probe_device(cascade, floor, dev);
@@ -2101,11 +2101,6 @@ err_probe:
        for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
                if (cascade->floors[floor])
                        doc_release_device(cascade->floors[floor]);
-nomem2:
-       kfree(cascade);
-nomem1:
-       iounmap(base);
-noress:
        return ret;
 }
 
@@ -2119,7 +2114,6 @@ static int __exit docg3_release(struct platform_device *pdev)
 {
        struct docg3_cascade *cascade = platform_get_drvdata(pdev);
        struct docg3 *docg3 = cascade->floors[0]->priv;
-       void __iomem *base = cascade->base;
        int floor;
 
        doc_unregister_sysfs(pdev, cascade);
@@ -2129,8 +2123,6 @@ static int __exit docg3_release(struct platform_device *pdev)
                        doc_release_device(cascade->floors[floor]);
 
        free_bch(docg3->cascade->bch);
-       kfree(cascade);
-       iounmap(base);
        return 0;
 }
 
index 7eda71dbc183b7aa456e60a41f0490c882d94331..ad19139097025b97839fb7cbe123a1261e6cf876 100644 (file)
@@ -41,6 +41,7 @@
 #define        OPCODE_WRSR             0x01    /* Write status register 1 byte */
 #define        OPCODE_NORM_READ        0x03    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ        0x6b    /* Read data bytes */
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
 #define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
 #define        OPCODE_BE_4K_PMC        0xd7    /* Erase 4KiB block on PMC chips */
 #define        OPCODE_CHIP_ERASE       0xc7    /* Erase whole flash chip */
 #define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
 #define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
+#define        OPCODE_RDCR             0x35    /* Read configuration register */
 
 /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 #define        OPCODE_NORM_READ_4B     0x13    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ_4B     0x0c    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ_4B     0x6c    /* Read data bytes */
 #define        OPCODE_PP_4B            0x12    /* Page program (up to 256 bytes) */
 #define        OPCODE_SE_4B            0xdc    /* Sector erase (usually 64KiB) */
 
 #define        SR_BP2                  0x10    /* Block protect 2 */
 #define        SR_SRWD                 0x80    /* SR write protect */
 
+#define SR_QUAD_EN_MX           0x40    /* Macronix Quad I/O */
+
+/* Configuration Register bits. */
+#define CR_QUAD_EN_SPAN                0x2     /* Spansion Quad I/O */
+
 /* Define max times to check status register before we give up. */
 #define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        MAX_CMD_SIZE            6
 
 /****************************************************************************/
 
+enum read_type {
+       M25P80_NORMAL = 0,
+       M25P80_FAST,
+       M25P80_QUAD,
+};
+
 struct m25p {
        struct spi_device       *spi;
        struct mutex            lock;
@@ -94,7 +108,7 @@ struct m25p {
        u8                      read_opcode;
        u8                      program_opcode;
        u8                      *command;
-       bool                    fast_read;
+       enum read_type          flash_read;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -130,6 +144,26 @@ static int read_sr(struct m25p *flash)
        return val;
 }
 
+/*
+ * Read configuration register, returning its value in the
+ * location. Return the configuration register value.
+ * Returns negative if error occured.
+ */
+static int read_cr(struct m25p *flash)
+{
+       u8 code = OPCODE_RDCR;
+       int ret;
+       u8 val;
+
+       ret = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev, "error %d reading CR\n", ret);
+               return ret;
+       }
+
+       return val;
+}
+
 /*
  * Write status register 1 byte
  * Returns negative if error occurred.
@@ -219,6 +253,93 @@ static int wait_till_ready(struct m25p *flash)
        return 1;
 }
 
+/*
+ * Write status Register and configuration register with 2 bytes
+ * The first byte will be written to the status register, while the
+ * second byte will be written to the configuration register.
+ * Return negative if error occured.
+ */
+static int write_sr_cr(struct m25p *flash, u16 val)
+{
+       flash->command[0] = OPCODE_WRSR;
+       flash->command[1] = val & 0xff;
+       flash->command[2] = (val >> 8);
+
+       return spi_write(flash->spi, flash->command, 3);
+}
+
+static int macronix_quad_enable(struct m25p *flash)
+{
+       int ret, val;
+       u8 cmd[2];
+       cmd[0] = OPCODE_WRSR;
+
+       val = read_sr(flash);
+       cmd[1] = val | SR_QUAD_EN_MX;
+       write_enable(flash);
+
+       spi_write(flash->spi, &cmd, 2);
+
+       if (wait_till_ready(flash))
+               return 1;
+
+       ret = read_sr(flash);
+       if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
+               dev_err(&flash->spi->dev, "Macronix Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int spansion_quad_enable(struct m25p *flash)
+{
+       int ret;
+       int quad_en = CR_QUAD_EN_SPAN << 8;
+
+       write_enable(flash);
+
+       ret = write_sr_cr(flash, quad_en);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev,
+                       "error while writing configuration register\n");
+               return -EINVAL;
+       }
+
+       /* read back and check it */
+       ret = read_cr(flash);
+       if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+               dev_err(&flash->spi->dev, "Spansion Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int set_quad_mode(struct m25p *flash, u32 jedec_id)
+{
+       int status;
+
+       switch (JEDEC_MFR(jedec_id)) {
+       case CFI_MFR_MACRONIX:
+               status = macronix_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Macronix quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       default:
+               status = spansion_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Spansion quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       }
+}
+
 /*
  * Erase the whole flash memory
  *
@@ -349,6 +470,35 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        return 0;
 }
 
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static inline int m25p80_dummy_cycles_read(struct m25p *flash)
+{
+       switch (flash->flash_read) {
+       case M25P80_FAST:
+       case M25P80_QUAD:
+               return 1;
+       case M25P80_NORMAL:
+               return 0;
+       default:
+               dev_err(&flash->spi->dev, "No valid read type supported\n");
+               return -1;
+       }
+}
+
+static inline unsigned int m25p80_rx_nbits(const struct m25p *flash)
+{
+       switch (flash->flash_read) {
+       case M25P80_QUAD:
+               return 4;
+       default:
+               return 0;
+       }
+}
+
 /*
  * Read an address range from the flash chip.  The address range
  * may be any size provided it is within the physical boundaries.
@@ -360,6 +510,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer t[2];
        struct spi_message m;
        uint8_t opcode;
+       int dummy;
 
        pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
                        __func__, (u32)from, len);
@@ -367,11 +518,18 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        spi_message_init(&m);
        memset(t, 0, (sizeof t));
 
+       dummy =  m25p80_dummy_cycles_read(flash);
+       if (dummy < 0) {
+               dev_err(&flash->spi->dev, "No valid read command supported\n");
+               return -EINVAL;
+       }
+
        t[0].tx_buf = flash->command;
-       t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
+       t[0].len = m25p_cmdsz(flash) + dummy;
        spi_message_add_tail(&t[0], &m);
 
        t[1].rx_buf = buf;
+       t[1].rx_nbits = m25p80_rx_nbits(flash);
        t[1].len = len;
        spi_message_add_tail(&t[1], &m);
 
@@ -391,8 +549,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        spi_sync(flash->spi, &m);
 
-       *retlen = m.actual_length - m25p_cmdsz(flash) -
-                       (flash->fast_read ? 1 : 0);
+       *retlen = m.actual_length - m25p_cmdsz(flash) - dummy;
 
        mutex_unlock(&flash->lock);
 
@@ -698,6 +855,7 @@ struct flash_info {
 #define        SST_WRITE       0x04            /* use SST byte programming */
 #define        M25P_NO_FR      0x08            /* Can't do fastread */
 #define        SECT_4K_PMC     0x10            /* OPCODE_BE_4K_PMC works uniformly */
+#define        M25P80_QUAD_READ        0x20    /* Flash supports Quad Read */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)     \
@@ -775,7 +933,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
+       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) },
 
        /* Micron */
        { "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
@@ -795,8 +953,8 @@ static const struct spi_device_id m25p_ids[] = {
        { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 0) },
        { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 0) },
        { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 0) },
-       { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
+       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, M25P80_QUAD_READ) },
+       { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, M25P80_QUAD_READ) },
        { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
        { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
        { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
@@ -851,6 +1009,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
        { "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
+       { "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, SECT_4K) },
        { "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
@@ -937,6 +1096,7 @@ static int m25p_probe(struct spi_device *spi)
        unsigned                        i;
        struct mtd_part_parser_data     ppdata;
        struct device_node *np = spi->dev.of_node;
+       int ret;
 
        /* Platform data helps sort out which chip type we have, as
         * well as how this board partitions it.  If we don't have
@@ -1051,22 +1211,46 @@ static int m25p_probe(struct spi_device *spi)
        flash->page_size = info->page_size;
        flash->mtd.writebufsize = flash->page_size;
 
-       if (np)
+       if (np) {
                /* If we were instantiated by DT, use it */
-               flash->fast_read = of_property_read_bool(np, "m25p,fast-read");
-       else
+               if (of_property_read_bool(np, "m25p,fast-read"))
+                       flash->flash_read = M25P80_FAST;
+               else
+                       flash->flash_read = M25P80_NORMAL;
+       } else {
                /* If we weren't instantiated by DT, default to fast-read */
-               flash->fast_read = true;
+               flash->flash_read = M25P80_FAST;
+       }
 
        /* Some devices cannot do fast-read, no matter what DT tells us */
        if (info->flags & M25P_NO_FR)
-               flash->fast_read = false;
+               flash->flash_read = M25P80_NORMAL;
+
+       /* Quad-read mode takes precedence over fast/normal */
+       if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) {
+               ret = set_quad_mode(flash, info->jedec_id);
+               if (ret) {
+                       dev_err(&flash->spi->dev, "quad mode not supported\n");
+                       return ret;
+               }
+               flash->flash_read = M25P80_QUAD;
+       }
 
        /* Default commands */
-       if (flash->fast_read)
+       switch (flash->flash_read) {
+       case M25P80_QUAD:
+               flash->read_opcode = OPCODE_QUAD_READ;
+               break;
+       case M25P80_FAST:
                flash->read_opcode = OPCODE_FAST_READ;
-       else
+               break;
+       case M25P80_NORMAL:
                flash->read_opcode = OPCODE_NORM_READ;
+               break;
+       default:
+               dev_err(&flash->spi->dev, "No Read opcode defined\n");
+               return -EINVAL;
+       }
 
        flash->program_opcode = OPCODE_PP;
 
@@ -1077,9 +1261,17 @@ static int m25p_probe(struct spi_device *spi)
                flash->addr_width = 4;
                if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
                        /* Dedicated 4-byte command set */
-                       flash->read_opcode = flash->fast_read ?
-                               OPCODE_FAST_READ_4B :
-                               OPCODE_NORM_READ_4B;
+                       switch (flash->flash_read) {
+                       case M25P80_QUAD:
+                               flash->read_opcode = OPCODE_QUAD_READ_4B;
+                               break;
+                       case M25P80_FAST:
+                               flash->read_opcode = OPCODE_FAST_READ_4B;
+                               break;
+                       case M25P80_NORMAL:
+                               flash->read_opcode = OPCODE_NORM_READ_4B;
+                               break;
+                       }
                        flash->program_opcode = OPCODE_PP_4B;
                        /* No small sector erase for 4-byte command set */
                        flash->erase_opcode = OPCODE_SE_4B;
index 182849d39c61acb34c40a79ab6bf04e30162da79..5c8b322ba904b1691bf204efc3f4523106dc8f67 100644 (file)
@@ -205,7 +205,7 @@ static int __init ms02nv_init_one(ulong addr)
        mtd->type = MTD_RAM;
        mtd->flags = MTD_CAP_RAM;
        mtd->size = fixsize;
-       mtd->name = (char *)ms02nv_name;
+       mtd->name = ms02nv_name;
        mtd->owner = THIS_MODULE;
        mtd->_read = ms02nv_read;
        mtd->_write = ms02nv_write;
index 4a47b0266d4e587761a2db5c1cd2e1613fc710bc..624069de4f28c067260fc4fec75c35b713fc5c84 100644 (file)
@@ -669,7 +669,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
        if (!err)
                return 0;
 
-       spi_set_drvdata(spi, NULL);
        kfree(priv);
        return err;
 }
@@ -899,10 +898,8 @@ static int dataflash_remove(struct spi_device *spi)
        pr_debug("%s: remove\n", dev_name(&spi->dev));
 
        status = mtd_device_unregister(&flash->mtd);
-       if (status == 0) {
-               spi_set_drvdata(spi, NULL);
+       if (status == 0)
                kfree(flash);
-       }
        return status;
 }
 
index ec59d65897fbe38976112ab071741b6c2d3b9189..8e285089229c364ee29c6b4f7c90a872d6e7c693 100644 (file)
@@ -92,7 +92,7 @@ static void __exit cleanup_mtdram(void)
 }
 
 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
-               unsigned long size, char *name)
+               unsigned long size, const char *name)
 {
        memset(mtd, 0, sizeof(*mtd));
 
index 2ef19aa0086bee62d51a9986ea50f5983461869c..d38b6460d50565c21fa46978d3f2383d13299e6f 100644 (file)
@@ -388,7 +388,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
        wake_up(&chip->wq);
 }
 
-int do_write_buffer(struct map_info *map, struct flchip *chip,
+static int do_write_buffer(struct map_info *map, struct flchip *chip,
                        unsigned long adr, const struct kvec **pvec,
                        unsigned long *pvec_seek, int len)
 {
@@ -469,7 +469,7 @@ int do_write_buffer(struct map_info *map, struct flchip *chip,
        return ret;
 }
 
-int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
+static int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
 {
        struct map_info *map = mtd->priv;
        struct lpddr_private *lpddr = map->fldrv_priv;
@@ -748,34 +748,6 @@ static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK);
 }
 
-int word_program(struct map_info *map, loff_t adr, uint32_t curval)
-{
-    int ret;
-       struct lpddr_private *lpddr = map->fldrv_priv;
-       int chipnum = adr >> lpddr->chipshift;
-       struct flchip *chip = &lpddr->chips[chipnum];
-
-       mutex_lock(&chip->mutex);
-       ret = get_chip(map, chip, FL_WRITING);
-       if (ret) {
-               mutex_unlock(&chip->mutex);
-               return ret;
-       }
-
-       send_pfow_command(map, LPDDR_WORD_PROGRAM, adr, 0x00, (map_word *)&curval);
-
-       ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->SingleWordProgTime));
-       if (ret)        {
-               printk(KERN_WARNING"%s word_program error at: %llx; val: %x\n",
-                       map->name, adr, curval);
-               goto out;
-       }
-
-out:   put_chip(map, chip);
-       mutex_unlock(&chip->mutex);
-       return ret;
-}
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>");
 MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");
index 10debfea81e7147c25fa00e4913bd2d336c24b6a..d6b2451eab1d9f0db5808c3ad837ac2f6f604499 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -162,13 +163,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
                mtd_device_unregister(info->mtd);
                map_destroy(info->mtd);
        }
-       if (info->map.virt)
-               iounmap(info->map.virt);
-
-       if (info->res) {
-               release_resource(info->res);
-               kfree(info->res);
-       }
 
        if (plat->exit)
                plat->exit();
@@ -194,7 +188,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
                        return err;
        }
 
-       info = kzalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
+       info = devm_kzalloc(&dev->dev, sizeof(struct ixp4xx_flash_info),
+                           GFP_KERNEL);
        if(!info) {
                err = -ENOMEM;
                goto Error;
@@ -220,20 +215,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
        info->map.write = ixp4xx_probe_write16;
        info->map.copy_from = ixp4xx_copy_from;
 
-       info->res = request_mem_region(dev->resource->start,
-                       resource_size(dev->resource),
-                       "IXP4XXFlash");
-       if (!info->res) {
-               printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
-               err = -ENOMEM;
-               goto Error;
-       }
-
-       info->map.virt = ioremap(dev->resource->start,
-                                resource_size(dev->resource));
-       if (!info->map.virt) {
-               printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
-               err = -EIO;
+       info->map.virt = devm_ioremap_resource(&dev->dev, dev->resource);
+       if (IS_ERR(info->map.virt)) {
+               err = PTR_ERR(info->map.virt);
                goto Error;
        }
 
index d7ac65d1d569dee08e325480501e29cc550ef012..93c507a6f86245024d6b1e79a54ca2f8ad8d78b1 100644 (file)
@@ -123,24 +123,28 @@ ltq_mtd_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL);
+       ltq_mtd = devm_kzalloc(&pdev->dev, sizeof(struct ltq_mtd), GFP_KERNEL);
+       if (!ltq_mtd)
+               return -ENOMEM;
+
        platform_set_drvdata(pdev, ltq_mtd);
 
        ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!ltq_mtd->res) {
                dev_err(&pdev->dev, "failed to get memory resource\n");
-               err = -ENOENT;
-               goto err_out;
+               return -ENOENT;
        }
 
-       ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+       ltq_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info),
+                                   GFP_KERNEL);
+       if (!ltq_mtd->map)
+               return -ENOMEM;
+
        ltq_mtd->map->phys = ltq_mtd->res->start;
        ltq_mtd->map->size = resource_size(ltq_mtd->res);
        ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res);
-       if (IS_ERR(ltq_mtd->map->virt)) {
-               err = PTR_ERR(ltq_mtd->map->virt);
-               goto err_out;
-       }
+       if (IS_ERR(ltq_mtd->map->virt))
+               return PTR_ERR(ltq_mtd->map->virt);
 
        ltq_mtd->map->name = ltq_map_name;
        ltq_mtd->map->bankwidth = 2;
@@ -155,8 +159,7 @@ ltq_mtd_probe(struct platform_device *pdev)
 
        if (!ltq_mtd->mtd) {
                dev_err(&pdev->dev, "probing failed\n");
-               err = -ENXIO;
-               goto err_free;
+               return -ENXIO;
        }
 
        ltq_mtd->mtd->owner = THIS_MODULE;
@@ -177,10 +180,6 @@ ltq_mtd_probe(struct platform_device *pdev)
 
 err_destroy:
        map_destroy(ltq_mtd->mtd);
-err_free:
-       kfree(ltq_mtd->map);
-err_out:
-       kfree(ltq_mtd);
        return err;
 }
 
@@ -189,13 +188,9 @@ ltq_mtd_remove(struct platform_device *pdev)
 {
        struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
 
-       if (ltq_mtd) {
-               if (ltq_mtd->mtd) {
-                       mtd_device_unregister(ltq_mtd->mtd);
-                       map_destroy(ltq_mtd->mtd);
-               }
-               kfree(ltq_mtd->map);
-               kfree(ltq_mtd);
+       if (ltq_mtd && ltq_mtd->mtd) {
+               mtd_device_unregister(ltq_mtd->mtd);
+               map_destroy(ltq_mtd->mtd);
        }
        return 0;
 }
index 0f55589a56b815af4c00bc521c504db468774fa5..9aad854fe9121aaa821181bffe64e819ec0e8498 100644 (file)
@@ -61,7 +61,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
        if (!info)
                return -ENOMEM;
 
-       info->map.name = (char *) flash->name;
+       info->map.name = flash->name;
        info->map.bankwidth = flash->width;
        info->map.phys = res->start;
        info->map.size = resource_size(res);
index d467f3b11c96c72ded5f3019cc823eb50fc6bd0b..39cc4181f02538a438b8fc427e00e19c1074fde3 100644 (file)
@@ -75,7 +75,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
 
        up->name = of_get_property(dp, "model", NULL);
        if (up->name && 0 < strlen(up->name))
-               up->map.name = (char *)up->name;
+               up->map.name = up->name;
 
        up->map.phys = op->resource[0].start;
 
index 92311a56939fca8d53e05e178054520f80b3bcec..34c0b16aed5c4e2f7d61a22d3fdeaf2ca066a632 100644 (file)
@@ -313,15 +313,7 @@ static struct attribute *mtd_attrs[] = {
        &dev_attr_bitflip_threshold.attr,
        NULL,
 };
-
-static struct attribute_group mtd_group = {
-       .attrs          = mtd_attrs,
-};
-
-static const struct attribute_group *mtd_groups[] = {
-       &mtd_group,
-       NULL,
-};
+ATTRIBUTE_GROUPS(mtd);
 
 static struct device_type mtd_devtype = {
        .name           = "mtd",
index 6e732c3820c14bf9d07b693a0c1de9bfff0088f0..3c7d6d7623c1cd5557b4dfeb38e80e03fc6e2abc 100644 (file)
@@ -534,7 +534,7 @@ out_register:
        return slave;
 }
 
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length)
 {
        struct mtd_partition part;
@@ -672,22 +672,19 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while (0)
 
-int register_mtd_parser(struct mtd_part_parser *p)
+void register_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_add(&p->list, &part_parsers);
        spin_unlock(&part_parser_lock);
-
-       return 0;
 }
 EXPORT_SYMBOL_GPL(register_mtd_parser);
 
-int deregister_mtd_parser(struct mtd_part_parser *p)
+void deregister_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_del(&p->list);
        spin_unlock(&part_parser_lock);
-       return 0;
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
index 93ae6a6d94f713d6352abd612efd1fed05f43dfd..90ff447bf0437707fe763133532fbb6b89bae7b7 100644 (file)
@@ -95,7 +95,7 @@ config MTD_NAND_OMAP2
          platforms.
 
 config MTD_NAND_OMAP_BCH
-       depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
+       depends on MTD_NAND_OMAP2
        tristate "Support hardware based BCH error correction"
        default n
        select BCH
@@ -326,11 +326,11 @@ config MTD_NAND_ATMEL
          on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-       tristate "Support for NAND flash devices on PXA3xx"
+       tristate "NAND support on PXA3xx and Armada 370/XP"
        depends on PXA3xx || ARCH_MMP || PLAT_ORION
        help
          This enables the driver for the NAND flash device found on
-         PXA3xx processors
+         PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
 
 config MTD_NAND_SLC_LPC32XX
        tristate "NXP LPC32xx SLC Controller"
@@ -458,17 +458,17 @@ config MTD_NAND_MXC
 
 config MTD_NAND_SH_FLCTL
        tristate "Support for NAND on Renesas SuperH FLCTL"
-       depends on SUPERH || ARCH_SHMOBILE
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        help
          Several Renesas SuperH CPU has FLCTL. This option enables support
          for NAND Flash using FLCTL.
 
 config MTD_NAND_DAVINCI
-        tristate "Support NAND on DaVinci SoC"
-        depends on ARCH_DAVINCI
+        tristate "Support NAND on DaVinci/Keystone SoC"
+        depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF)
         help
          Enable the driver for NAND flash chips on Texas Instruments
-         DaVinci processors.
+         DaVinci/Keystone processors.
 
 config MTD_NAND_TXX9NDFMC
        tristate "NAND Flash support for TXx9 SoC"
index 59f08c44abdbc9be920ea62974d19bcdc7884889..c36e9b84487cd36b55d96efd1d17c6db9494c0fc 100644 (file)
@@ -1961,10 +1961,8 @@ static int atmel_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        res = platform_driver_register(&atmel_nand_nfc_driver);
        if (res)
@@ -2062,14 +2060,14 @@ static int atmel_nand_probe(struct platform_device *pdev)
                }
 
                if (gpio_get_value(host->board.det_pin)) {
-                       printk(KERN_INFO "No SmartMedia card inserted.\n");
+                       dev_info(&pdev->dev, "No SmartMedia card inserted.\n");
                        res = -ENXIO;
                        goto err_no_card;
                }
        }
 
        if (host->board.on_flash_bbt || on_flash_bbt) {
-               printk(KERN_INFO "atmel_nand: Use On Flash BBT\n");
+               dev_info(&pdev->dev, "Use On Flash BBT\n");
                nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
        }
 
index ae8dd7c4103922fc760786be079b7576ad648893..2880d888cfc5c260aefcdd5caba743d05a292ae6 100644 (file)
@@ -418,10 +418,8 @@ static int au1550nd_probe(struct platform_device *pdev)
        }
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx) {
-               dev_err(&pdev->dev, "no memory for NAND context\n");
+       if (!ctx)
                return -ENOMEM;
-       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
@@ -480,6 +478,8 @@ static int au1550nd_probe(struct platform_device *pdev)
 
        mtd_device_register(&ctx->info, pd->parts, pd->num_parts);
 
+       platform_set_drvdata(pdev, ctx);
+
        return 0;
 
 out3:
index 2c42e125720f2141258e064e1fc024fef092057b..94f55dbde995974213b48158048a92553bfc7475 100644 (file)
@@ -745,7 +745,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
-               dev_err(&pdev->dev, "no memory for flash info\n");
                err = -ENOMEM;
                goto out_err_kzalloc;
        }
index c34985a55101b0606f76ed580f1e13ac562913e2..f2f64addb5e87119d8b72e9122565ae3ec9150f9 100644 (file)
@@ -640,10 +640,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
        pci_set_master(pdev);
 
        mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL);
-       if (!mtd) {
-               dev_warn(&pdev->dev, "failed to alloc mtd_info\n");
+       if (!mtd)
                return  -ENOMEM;
-       }
        cafe = (void *)(&mtd[1]);
 
        mtd->dev.parent = &pdev->dev;
index 39b2ef848811a5d1cf1c7fea98ef8f6168e98c5f..66ec95e6ca6c760c2713a621d14ec09a51446d66 100644 (file)
@@ -164,7 +164,6 @@ static int __init cmx270_init(void)
                                  sizeof(struct nand_chip),
                                  GFP_KERNEL);
        if (!cmx270_nand_mtd) {
-               pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
                ret = -ENOMEM;
                goto err_kzalloc;
        }
index d469a9a1dea0de7ea5f31172995c6e79411e7822..88109d375ae7f65546a2225e894e19ade98c41ba 100644 (file)
@@ -199,7 +199,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
        /* Allocate memory for MTD device structure and private data */
        new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!new_mtd) {
-               printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
                err = -ENOMEM;
                goto out;
        }
index b77a01efb4837ea325988ee6e58e82bd128d7892..a4989ec6292efa0127ba4cc84d13fd07ad09fe4b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/of.h>
+#include <linux/of_mtd.h>
 
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
@@ -487,7 +488,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
  * ten ECC bytes plus the manufacturer's bad block marker byte, and
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_small __initconst = {
+static struct nand_ecclayout hwecc4_small = {
        .eccbytes = 10,
        .eccpos = { 0, 1, 2, 3, 4,
                /* offset 5 holds the badblock marker */
@@ -503,7 +504,7 @@ static struct nand_ecclayout hwecc4_small __initconst = {
  * storing ten ECC bytes plus the manufacturer's bad block marker byte,
  * and not overlapping the default BBT markers.
  */
-static struct nand_ecclayout hwecc4_2048 __initconst = {
+static struct nand_ecclayout hwecc4_2048 = {
        .eccbytes = 40,
        .eccpos = {
                /* at the end of spare sector */
@@ -534,17 +535,19 @@ static struct davinci_nand_pdata
                struct davinci_nand_pdata *pdata;
                const char *mode;
                u32 prop;
-               int len;
 
                pdata =  devm_kzalloc(&pdev->dev,
                                sizeof(struct davinci_nand_pdata),
                                GFP_KERNEL);
                pdev->dev.platform_data = pdata;
                if (!pdata)
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-chipselect", &prop))
                        pdev->id = prop;
+               else
+                       return ERR_PTR(-EINVAL);
+
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-mask-ale", &prop))
                        pdata->mask_ale = prop;
@@ -555,6 +558,8 @@ static struct davinci_nand_pdata
                        "ti,davinci-mask-chipsel", &prop))
                        pdata->mask_chipsel = prop;
                if (!of_property_read_string(pdev->dev.of_node,
+                       "nand-ecc-mode", &mode) ||
+                   !of_property_read_string(pdev->dev.of_node,
                        "ti,davinci-ecc-mode", &mode)) {
                        if (!strncmp("none", mode, 4))
                                pdata->ecc_mode = NAND_ECC_NONE;
@@ -566,12 +571,16 @@ static struct davinci_nand_pdata
                if (!of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-ecc-bits", &prop))
                        pdata->ecc_bits = prop;
-               if (!of_property_read_u32(pdev->dev.of_node,
+
+               prop = of_get_nand_bus_width(pdev->dev.of_node);
+               if (0 < prop || !of_property_read_u32(pdev->dev.of_node,
                        "ti,davinci-nand-buswidth", &prop))
                        if (prop == 16)
                                pdata->options |= NAND_BUSWIDTH_16;
-               if (of_find_property(pdev->dev.of_node,
-                       "ti,davinci-nand-use-bbt", &len))
+               if (of_property_read_bool(pdev->dev.of_node,
+                       "nand-on-flash-bbt") ||
+                   of_property_read_bool(pdev->dev.of_node,
+                       "ti,davinci-nand-use-bbt"))
                        pdata->bbt_options = NAND_BBT_USE_FLASH;
        }
 
@@ -585,7 +594,7 @@ static struct davinci_nand_pdata
 }
 #endif
 
-static int __init nand_davinci_probe(struct platform_device *pdev)
+static int nand_davinci_probe(struct platform_device *pdev)
 {
        struct davinci_nand_pdata       *pdata;
        struct davinci_nand_info        *info;
@@ -598,6 +607,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        nand_ecc_modes_t                ecc_mode;
 
        pdata = nand_davinci_get_pdata(pdev);
+       if (IS_ERR(pdata))
+               return PTR_ERR(pdata);
+
        /* insist on board-specific configuration */
        if (!pdata)
                return -ENODEV;
@@ -607,11 +619,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                return -ENODEV;
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               dev_err(&pdev->dev, "unable to allocate memory\n");
-               ret = -ENOMEM;
-               goto err_nomem;
-       }
+       if (!info)
+               return -ENOMEM;
 
        platform_set_drvdata(pdev, info);
 
@@ -619,19 +628,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!res1 || !res2) {
                dev_err(&pdev->dev, "resource missing\n");
-               ret = -EINVAL;
-               goto err_nomem;
+               return -EINVAL;
        }
 
        vaddr = devm_ioremap_resource(&pdev->dev, res1);
-       if (IS_ERR(vaddr)) {
-               ret = PTR_ERR(vaddr);
-               goto err_ioremap;
-       }
-       base = devm_ioremap_resource(&pdev->dev, res2);
-       if (IS_ERR(base)) {
-               ret = PTR_ERR(base);
-               goto err_ioremap;
+       if (IS_ERR(vaddr))
+               return PTR_ERR(vaddr);
+
+       /*
+        * This registers range is used to setup NAND settings. In case with
+        * TI AEMIF driver, the same memory address range is requested already
+        * by AEMIF, so we cannot request it twice, just ioremap.
+        * The AEMIF and NAND drivers not use the same registers in this range.
+        */
+       base = devm_ioremap(&pdev->dev, res2->start, resource_size(res2));
+       if (!base) {
+               dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res2);
+               return -EADDRNOTAVAIL;
        }
 
        info->dev               = &pdev->dev;
@@ -699,7 +712,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                        spin_unlock_irq(&davinci_nand_lock);
 
                        if (ret == -EBUSY)
-                               goto err_ecc;
+                               return ret;
 
                        info->chip.ecc.calculate = nand_davinci_calculate_4bit;
                        info->chip.ecc.correct = nand_davinci_correct_4bit;
@@ -715,8 +728,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                info->chip.ecc.strength = pdata->ecc_bits;
                break;
        default:
-               ret = -EINVAL;
-               goto err_ecc;
+               return -EINVAL;
        }
        info->chip.ecc.mode = ecc_mode;
 
@@ -724,7 +736,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        if (IS_ERR(info->clk)) {
                ret = PTR_ERR(info->clk);
                dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
-               goto err_clk;
+               return ret;
        }
 
        ret = clk_prepare_enable(info->clk);
@@ -753,7 +765,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                                                        info->core_chipsel);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-               goto err_timing;
+               goto err;
        }
 
        spin_lock_irq(&davinci_nand_lock);
@@ -769,7 +781,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL);
        if (ret < 0) {
                dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
-               goto err_scan;
+               goto err;
        }
 
        /* Update ECC layout if needed ... for 1-bit HW ECC, the default
@@ -783,7 +795,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                if (!chunks || info->mtd.oobsize < 16) {
                        dev_dbg(&pdev->dev, "too small\n");
                        ret = -EINVAL;
-                       goto err_scan;
+                       goto err;
                }
 
                /* For small page chips, preserve the manufacturer's
@@ -814,7 +826,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                dev_warn(&pdev->dev, "no 4-bit ECC support yet "
                                "for 4KiB-page NAND\n");
                ret = -EIO;
-               goto err_scan;
+               goto err;
 
 syndrome_done:
                info->chip.ecc.layout = &info->ecclayout;
@@ -822,7 +834,7 @@ syndrome_done:
 
        ret = nand_scan_tail(&info->mtd);
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        if (pdata->parts)
                ret = mtd_device_parse_register(&info->mtd, NULL, NULL,
@@ -835,7 +847,7 @@ syndrome_done:
                                                NULL, 0);
        }
        if (ret < 0)
-               goto err_scan;
+               goto err;
 
        val = davinci_nand_readl(info, NRCSR_OFFSET);
        dev_info(&pdev->dev, "controller rev. %d.%d\n",
@@ -843,8 +855,7 @@ syndrome_done:
 
        return 0;
 
-err_scan:
-err_timing:
+err:
        clk_disable_unprepare(info->clk);
 
 err_clk_enable:
@@ -852,15 +863,10 @@ err_clk_enable:
        if (ecc_mode == NAND_ECC_HW_SYNDROME)
                ecc4_busy = false;
        spin_unlock_irq(&davinci_nand_lock);
-
-err_ecc:
-err_clk:
-err_ioremap:
-err_nomem:
        return ret;
 }
 
-static int __exit nand_davinci_remove(struct platform_device *pdev)
+static int nand_davinci_remove(struct platform_device *pdev)
 {
        struct davinci_nand_info *info = platform_get_drvdata(pdev);
 
@@ -877,7 +883,8 @@ static int __exit nand_davinci_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver nand_davinci_driver = {
-       .remove         = __exit_p(nand_davinci_remove),
+       .probe          = nand_davinci_probe,
+       .remove         = nand_davinci_remove,
        .driver         = {
                .name   = "davinci_nand",
                .owner  = THIS_MODULE,
@@ -886,7 +893,7 @@ static struct platform_driver nand_davinci_driver = {
 };
 MODULE_ALIAS("platform:davinci_nand");
 
-module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe);
+module_platform_driver(nand_davinci_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Texas Instruments");
index 370b9dd7a2786841f3180d732321c99416030559..c07cd573ad3af0dd4fa1e91f36c4a44259bbd5e7 100644 (file)
@@ -125,7 +125,6 @@ static void reset_buf(struct denali_nand_info *denali)
 
 static void write_byte_to_buf(struct denali_nand_info *denali, uint8_t byte)
 {
-       BUG_ON(denali->buf.tail >= sizeof(denali->buf.buf));
        denali->buf.buf[denali->buf.tail++] = byte;
 }
 
@@ -897,7 +896,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 /* this function examines buffers to see if they contain data that
  * indicate that the buffer is part of an erased region of flash.
  */
-bool is_erased(uint8_t *buf, int len)
+static bool is_erased(uint8_t *buf, int len)
 {
        int i = 0;
        for (i = 0; i < len; i++)
@@ -1429,20 +1428,12 @@ int denali_init(struct denali_nand_info *denali)
                }
        }
 
-       /* Is 32-bit DMA supported? */
-       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
-       if (ret) {
-               pr_err("Spectra: no usable DMA configuration\n");
-               return ret;
-       }
-       denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
-                                            DENALI_BUF_SIZE,
-                                            DMA_BIDIRECTIONAL);
+       /* allocate a temporary buffer for nand_scan_ident() */
+       denali->buf.buf = devm_kzalloc(denali->dev, PAGE_SIZE,
+                                       GFP_DMA | GFP_KERNEL);
+       if (!denali->buf.buf)
+               return -ENOMEM;
 
-       if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
-               dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
-               return -EIO;
-       }
        denali->mtd.dev.parent = denali->dev;
        denali_hw_init(denali);
        denali_drv_init(denali);
@@ -1475,12 +1466,29 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /* MTD supported page sizes vary by kernel. We validate our
-        * kernel supports the device here.
-        */
-       if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
-               ret = -ENODEV;
-               pr_err("Spectra: device size not supported by this version of MTD.");
+       /* allocate the right size buffer now */
+       devm_kfree(denali->dev, denali->buf.buf);
+       denali->buf.buf = devm_kzalloc(denali->dev,
+                            denali->mtd.writesize + denali->mtd.oobsize,
+                            GFP_KERNEL);
+       if (!denali->buf.buf) {
+               ret = -ENOMEM;
+               goto failed_req_irq;
+       }
+
+       /* Is 32-bit DMA supported? */
+       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
+       if (ret) {
+               pr_err("Spectra: no usable DMA configuration\n");
+               goto failed_req_irq;
+       }
+
+       denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
+                            denali->mtd.writesize + denali->mtd.oobsize,
+                            DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
+               dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+               ret = -EIO;
                goto failed_req_irq;
        }
 
@@ -1602,7 +1610,8 @@ EXPORT_SYMBOL(denali_init);
 void denali_remove(struct denali_nand_info *denali)
 {
        denali_irq_cleanup(denali->irq, denali);
-       dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+       dma_unmap_single(denali->dev, denali->buf.dma_buf,
+                       denali->mtd.writesize + denali->mtd.oobsize,
                        DMA_BIDIRECTIONAL);
 }
 EXPORT_SYMBOL(denali_remove);
index cec5712862c9d01c50c417cad96f0bf3aa9a60ec..96681746242171fcbb5fdb4ab6beb6a77be3e54b 100644 (file)
 
 #define ECC_SECTOR_SIZE     512
 
-#define DENALI_BUF_SIZE                (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
-
 struct nand_buf {
        int head;
        int tail;
-       uint8_t buf[DENALI_BUF_SIZE];
+       uint8_t *buf;
        dma_addr_t dma_buf;
 };
 
index 92530244e2cbfdf48ecc2aa2282b90d12a98d0ad..babb02c4b2204ed0c5881a3577084c2ea826d5df 100644 (file)
@@ -108,7 +108,7 @@ static int denali_dt_probe(struct platform_device *ofdev)
                denali->dev->dma_mask = NULL;
        }
 
-       dt->clk = clk_get(&ofdev->dev, NULL);
+       dt->clk = devm_clk_get(&ofdev->dev, NULL);
        if (IS_ERR(dt->clk)) {
                dev_err(&ofdev->dev, "no clk available\n");
                return PTR_ERR(dt->clk);
@@ -124,7 +124,6 @@ static int denali_dt_probe(struct platform_device *ofdev)
 
 out_disable_clk:
        clk_disable_unprepare(dt->clk);
-       clk_put(dt->clk);
 
        return ret;
 }
@@ -135,7 +134,6 @@ static int denali_dt_remove(struct platform_device *ofdev)
 
        denali_remove(&dt->denali);
        clk_disable(dt->clk);
-       clk_put(dt->clk);
 
        return 0;
 }
index 033f177a6369b2d240b499f33df0b6bd925ed4d2..6e2f387b823f694e59e368bc987850a986c7d0c2 100644 (file)
@@ -21,7 +21,7 @@
 #define DENALI_NAND_NAME    "denali-nand-pci"
 
 /* List of platforms this NAND controller has be integrated into */
-static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+static const struct pci_device_id denali_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
        { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
        { /* end: all zeroes */ }
@@ -131,7 +131,6 @@ static struct pci_driver denali_pci_driver = {
 
 static int denali_init_pci(void)
 {
-       pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
        return pci_register_driver(&denali_pci_driver);
 }
 module_init(denali_init_pci);
index b68a4959f700af3e2768af69e6dd9afd0f94c8e1..fec31d71b84e03d7a84cbaf15b4558c16d413e0a 100644 (file)
@@ -1058,7 +1058,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 
        buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
-               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
        if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
@@ -1166,7 +1165,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
 
        buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
-               printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
 
@@ -1440,10 +1438,13 @@ static int __init doc_probe(unsigned long physadr)
        int reg, len, numchips;
        int ret = 0;
 
+       if (!request_mem_region(physadr, DOC_IOREMAP_LEN, NULL))
+               return -EBUSY;
        virtadr = ioremap(physadr, DOC_IOREMAP_LEN);
        if (!virtadr) {
                printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
-               return -EIO;
+               ret = -EIO;
+               goto error_ioremap;
        }
 
        /* It's not possible to cleanly detect the DiskOnChip - the
@@ -1561,7 +1562,6 @@ static int __init doc_probe(unsigned long physadr)
            sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
        mtd = kzalloc(len, GFP_KERNEL);
        if (!mtd) {
-               printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
                ret = -ENOMEM;
                goto fail;
        }
@@ -1629,6 +1629,10 @@ static int __init doc_probe(unsigned long physadr)
        WriteDOC(save_control, virtadr, DOCControl);
  fail:
        iounmap(virtadr);
+
+error_ioremap:
+       release_mem_region(physadr, DOC_IOREMAP_LEN);
+
        return ret;
 }
 
@@ -1645,6 +1649,7 @@ static void release_nanddoc(void)
                nextmtd = doc->nextdoc;
                nand_release(mtd);
                iounmap(doc->virtadr);
+               release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
                kfree(mtd);
        }
 }
index c966fc7474ced5fc8423b9440340f1d9b5072bbc..bcf60800c3ce7f5e0489972ebe7a3e3f83d225df 100644 (file)
@@ -847,7 +847,6 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
        if (!fsl_lbc_ctrl_dev->nand) {
                elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
                if (!elbc_fcm_ctrl) {
-                       dev_err(dev, "failed to allocate memory\n");
                        mutex_unlock(&fsl_elbc_nand_mutex);
                        ret = -ENOMEM;
                        goto err;
@@ -875,7 +874,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
                goto err;
        }
 
-       priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+       priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
        if (!priv->mtd.name) {
                ret = -ENOMEM;
                goto err;
index 43355779cff583975721e5c7bd7770bc055aa1c3..90ca7e75d6f038e4cefb365ee2a436eac4ac8cc2 100644 (file)
@@ -1060,7 +1060,6 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
        if (!fsl_ifc_ctrl_dev->nand) {
                ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL);
                if (!ifc_nand_ctrl) {
-                       dev_err(&dev->dev, "failed to allocate memory\n");
                        mutex_unlock(&fsl_ifc_nand_mutex);
                        return -ENOMEM;
                }
@@ -1101,7 +1100,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
                    IFC_NAND_EVTER_INTR_FTOERIR_EN |
                    IFC_NAND_EVTER_INTR_WPERIR_EN,
                    &ifc->ifc_nand.nand_evter_intr_en);
-       priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
+       priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
        if (!priv->mtd.name) {
                ret = -ENOMEM;
                goto err;
index 8b2752263db9a5549742bb36c3dcee48999b8b62..1550692973dc2ebcaa6864bc3e2c51607872b818 100644 (file)
@@ -889,10 +889,8 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 
        pdata->nand_timings = devm_kzalloc(&pdev->dev,
                                sizeof(*pdata->nand_timings), GFP_KERNEL);
-       if (!pdata->nand_timings) {
-               dev_err(&pdev->dev, "no memory for nand_timing\n");
+       if (!pdata->nand_timings)
                return -ENOMEM;
-       }
        of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
                                                sizeof(*pdata->nand_timings));
 
@@ -950,10 +948,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
        host->data_va = devm_ioremap_resource(&pdev->dev, res);
@@ -1108,8 +1104,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                        host->ecc_place = &fsmc_ecc4_lp_place;
                        break;
                default:
-                       printk(KERN_WARNING "No oob scheme defined for "
-                              "oobsize %d\n", mtd->oobsize);
+                       dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
+                                mtd->oobsize);
                        BUG();
                }
        } else {
@@ -1124,8 +1120,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                        nand->ecc.layout = &fsmc_ecc1_128_layout;
                        break;
                default:
-                       printk(KERN_WARNING "No oob scheme defined for "
-                              "oobsize %d\n", mtd->oobsize);
+                       dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
+                                mtd->oobsize);
                        BUG();
                }
        }
index e826f898241f92b24704ba7103fc0cdd970a63d1..8e6148aa4539a290b4b3a4cda8883f1bbba58f92 100644 (file)
@@ -132,13 +132,17 @@ static int gpio_nand_get_config_of(const struct device *dev,
 
 static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev)
 {
-       struct resource *r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
+       struct resource *r;
        u64 addr;
 
-       if (!r || of_property_read_u64(pdev->dev.of_node,
+       if (of_property_read_u64(pdev->dev.of_node,
                                       "gpio-control-nand,io-sync-reg", &addr))
                return NULL;
 
+       r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL);
+       if (!r)
+               return NULL;
+
        r->start = addr;
        r->end = r->start + 0x3;
        r->flags = IORESOURCE_MEM;
@@ -211,10 +215,8 @@ static int gpio_nand_probe(struct platform_device *pdev)
                return -EINVAL;
 
        gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL);
-       if (!gpiomtd) {
-               dev_err(&pdev->dev, "failed to create NAND MTD\n");
+       if (!gpiomtd)
                return -ENOMEM;
-       }
 
        chip = &gpiomtd->nand_chip;
 
index aaced29727fb0437f6a0c142253b04cbc0ca82d0..dd1df605a1d61ec8a43ffb5515ea50ce2f3c9b69 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/slab.h>
 
 #include "gpmi-nand.h"
 #include "gpmi-regs.h"
@@ -207,30 +208,41 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
        u32 reg;
        int i;
 
-       pr_err("Show GPMI registers :\n");
+       dev_err(this->dev, "Show GPMI registers :\n");
        for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
                reg = readl(r->gpmi_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
 
        /* start to print out the BCH info */
-       pr_err("Show BCH registers :\n");
+       dev_err(this->dev, "Show BCH registers :\n");
        for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
                reg = readl(r->bch_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
-       pr_err("BCH Geometry :\n");
-       pr_err("GF length              : %u\n", geo->gf_len);
-       pr_err("ECC Strength           : %u\n", geo->ecc_strength);
-       pr_err("Page Size in Bytes     : %u\n", geo->page_size);
-       pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size);
-       pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size);
-       pr_err("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
-       pr_err("Payload Size in Bytes  : %u\n", geo->payload_size);
-       pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size);
-       pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
-       pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
-       pr_err("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+       dev_err(this->dev, "BCH Geometry :\n"
+               "GF length              : %u\n"
+               "ECC Strength           : %u\n"
+               "Page Size in Bytes     : %u\n"
+               "Metadata Size in Bytes : %u\n"
+               "ECC Chunk Size in Bytes: %u\n"
+               "ECC Chunk Count        : %u\n"
+               "Payload Size in Bytes  : %u\n"
+               "Auxiliary Size in Bytes: %u\n"
+               "Auxiliary Status Offset: %u\n"
+               "Block Mark Byte Offset : %u\n"
+               "Block Mark Bit Offset  : %u\n",
+               geo->gf_len,
+               geo->ecc_strength,
+               geo->page_size,
+               geo->metadata_size,
+               geo->ecc_chunk_size,
+               geo->ecc_chunk_count,
+               geo->payload_size,
+               geo->auxiliary_size,
+               geo->auxiliary_status_offset,
+               geo->block_mark_byte_offset,
+               geo->block_mark_bit_offset);
 }
 
 /* Configures the geometry for BCH.  */
@@ -265,8 +277,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
        * On the other hand, the MX28 needs the reset, because one case has been
        * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23 yet,
-       * still we don't know if it could happen there as well.
+       * consecutive reboots. The latter case has not been seen on the MX23
+       * yet, still we don't know if it could happen there as well.
        */
        ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
        if (ret)
@@ -353,7 +365,7 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
        improved_timing_is_available =
                (target.tREA_in_ns  >= 0) &&
                (target.tRLOH_in_ns >= 0) &&
-               (target.tRHOH_in_ns >= 0) ;
+               (target.tRHOH_in_ns >= 0);
 
        /* Inspect the clock. */
        nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
@@ -911,10 +923,14 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
        struct resources  *r = &this->resources;
        struct nand_chip *nand = &this->nand;
        struct mtd_info  *mtd = &this->mtd;
-       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+       uint8_t *feature;
        unsigned long rate;
        int ret;
 
+       feature = kzalloc(ONFI_SUBFEATURE_PARAM_LEN, GFP_KERNEL);
+       if (!feature)
+               return -ENOMEM;
+
        nand->select_chip(mtd, 0);
 
        /* [1] send SET FEATURE commond to NAND */
@@ -942,11 +958,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
 
        this->flags |= GPMI_ASYNC_EDO_ENABLED;
        this->timing_mode = mode;
+       kfree(feature);
        dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode);
        return 0;
 
 err_out:
        nand->select_chip(mtd, -1);
+       kfree(feature);
        dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode);
        return -EINVAL;
 }
@@ -986,7 +1004,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* Enable the clock. */
        ret = gpmi_enable_clk(this);
        if (ret) {
-               pr_err("We failed in enable the clk\n");
+               dev_err(this->dev, "We failed in enable the clk\n");
                goto err_out;
        }
 
@@ -1003,7 +1021,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* [1] Set HW_GPMI_TIMING0 */
        reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
                BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
-               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles);
 
        writel(reg, gpmi_regs + HW_GPMI_TIMING0);
 
@@ -1090,7 +1108,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
                mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
                reg = readl(r->gpmi_regs + HW_GPMI_STAT);
        } else
-               pr_err("unknow arch.\n");
+               dev_err(this->dev, "unknow arch.\n");
        return reg & mask;
 }
 
@@ -1121,10 +1139,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
        sgl = &this->cmd_sgl;
@@ -1134,11 +1150,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                sgl, 1, DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_COMMAND);
@@ -1167,20 +1180,17 @@ int gpmi_send_data(struct gpmi_nand_data *this)
        pio[1] = 0;
        desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send DMA request */
        prepare_data_dma(this, DMA_TO_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_WRITE_DATA);
        return start_dma_without_bch_irq(this, desc);
@@ -1204,20 +1214,16 @@ int gpmi_read_data(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] : send DMA request */
        prepare_data_dma(this, DMA_FROM_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] : submit the DMA */
        set_dma_type(this, DMA_FOR_READ_DATA);
@@ -1262,10 +1268,9 @@ int gpmi_send_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
        return start_dma_with_bch_irq(this, desc);
 }
@@ -1297,10 +1302,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
        desc = dmaengine_prep_slave_sg(channel,
                                (struct scatterlist *)pio, 2,
                                DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] Enable the BCH block and read. */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
@@ -1327,10 +1330,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] Disable the BCH block */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
@@ -1348,10 +1349,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                (struct scatterlist *)pio, 3,
                                DMA_TRANS_NONE,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 3 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [4] submit the DMA */
        set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
index dabbc14db5630d8592268012fc067559179aa0f8..ca6369fe91ff31fc89bd382dca62261774310ff0 100644 (file)
@@ -18,9 +18,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -352,6 +349,9 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
+       if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")
+               && set_geometry_by_ecc_info(this))
+               return 0;
        return legacy_set_geometry(this);
 }
 
@@ -367,25 +367,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
        struct scatterlist *sgl = &this->data_sgl;
        int ret;
 
-       this->direct_dma_map_ok = true;
-
        /* first try to map the upper buffer directly */
-       sg_init_one(sgl, this->upper_buf, this->upper_len);
-       ret = dma_map_sg(this->dev, sgl, 1, dr);
-       if (ret == 0) {
-               /* We have to use our own DMA buffer. */
-               sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
-
-               if (dr == DMA_TO_DEVICE)
-                       memcpy(this->data_buffer_dma, this->upper_buf,
-                               this->upper_len);
-
+       if (virt_addr_valid(this->upper_buf) &&
+               !object_is_on_stack(this->upper_buf)) {
+               sg_init_one(sgl, this->upper_buf, this->upper_len);
                ret = dma_map_sg(this->dev, sgl, 1, dr);
                if (ret == 0)
-                       pr_err("DMA mapping failed.\n");
+                       goto map_fail;
 
-               this->direct_dma_map_ok = false;
+               this->direct_dma_map_ok = true;
+               return;
        }
+
+map_fail:
+       /* We have to use our own DMA buffer. */
+       sg_init_one(sgl, this->data_buffer_dma, this->upper_len);
+
+       if (dr == DMA_TO_DEVICE)
+               memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len);
+
+       dma_map_sg(this->dev, sgl, 1, dr);
+
+       this->direct_dma_map_ok = false;
 }
 
 /* This will be called after the DMA operation is finished. */
@@ -416,7 +419,7 @@ static void dma_irq_callback(void *param)
                break;
 
        default:
-               pr_err("in wrong DMA operation.\n");
+               dev_err(this->dev, "in wrong DMA operation.\n");
        }
 
        complete(dma_c);
@@ -438,7 +441,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the DMA block. */
        err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "DMA timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -467,7 +471,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the BCH block. */
        err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "BCH timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -483,70 +488,38 @@ static int acquire_register_block(struct gpmi_nand_data *this,
        void __iomem *p;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
-       if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
-               return -ENODEV;
-       }
-
-       p = ioremap(r->start, resource_size(r));
-       if (!p) {
-               pr_err("Can't remap %s\n", res_name);
-               return -ENOMEM;
-       }
+       p = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
 
        if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
                res->gpmi_regs = p;
        else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
                res->bch_regs = p;
        else
-               pr_err("unknown resource name : %s\n", res_name);
+               dev_err(this->dev, "unknown resource name : %s\n", res_name);
 
        return 0;
 }
 
-static void release_register_block(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       if (res->gpmi_regs)
-               iounmap(res->gpmi_regs);
-       if (res->bch_regs)
-               iounmap(res->bch_regs);
-       res->gpmi_regs = NULL;
-       res->bch_regs = NULL;
-}
-
 static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 {
        struct platform_device *pdev = this->pdev;
-       struct resources *res = &this->resources;
        const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
        struct resource *r;
        int err;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
+               dev_err(this->dev, "Can't get resource for %s\n", res_name);
                return -ENODEV;
        }
 
-       err = request_irq(r->start, irq_h, 0, res_name, this);
-       if (err) {
-               pr_err("Can't own %s\n", res_name);
-               return err;
-       }
-
-       res->bch_low_interrupt = r->start;
-       res->bch_high_interrupt = r->end;
-       return 0;
-}
-
-static void release_bch_irq(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       int i = res->bch_low_interrupt;
+       err = devm_request_irq(this->dev, r->start, irq_h, 0, res_name, this);
+       if (err)
+               dev_err(this->dev, "error requesting BCH IRQ\n");
 
-       for (; i <= res->bch_high_interrupt; i++)
-               free_irq(i, this);
+       return err;
 }
 
 static void release_dma_channels(struct gpmi_nand_data *this)
@@ -567,7 +540,7 @@ static int acquire_dma_channels(struct gpmi_nand_data *this)
        /* request dma channel */
        dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx");
        if (!dma_chan) {
-               pr_err("Failed to request DMA channel.\n");
+               dev_err(this->dev, "Failed to request DMA channel.\n");
                goto acquire_err;
        }
 
@@ -579,21 +552,6 @@ acquire_err:
        return -EINVAL;
 }
 
-static void gpmi_put_clks(struct gpmi_nand_data *this)
-{
-       struct resources *r = &this->resources;
-       struct clk *clk;
-       int i;
-
-       for (i = 0; i < GPMI_CLK_MAX; i++) {
-               clk = r->clock[i];
-               if (clk) {
-                       clk_put(clk);
-                       r->clock[i] = NULL;
-               }
-       }
-}
-
 static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
        "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
 };
@@ -606,7 +564,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
        int err, i;
 
        /* The main clock is stored in the first. */
-       r->clock[0] = clk_get(this->dev, "gpmi_io");
+       r->clock[0] = devm_clk_get(this->dev, "gpmi_io");
        if (IS_ERR(r->clock[0])) {
                err = PTR_ERR(r->clock[0]);
                goto err_clock;
@@ -622,7 +580,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
                if (extra_clks[i - 1] == NULL)
                        break;
 
-               clk = clk_get(this->dev, extra_clks[i - 1]);
+               clk = devm_clk_get(this->dev, extra_clks[i - 1]);
                if (IS_ERR(clk)) {
                        err = PTR_ERR(clk);
                        goto err_clock;
@@ -644,7 +602,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 
 err_clock:
        dev_dbg(this->dev, "failed in finding the clocks.\n");
-       gpmi_put_clks(this);
        return err;
 }
 
@@ -666,7 +623,7 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
        ret = acquire_dma_channels(this);
        if (ret)
-               goto exit_dma_channels;
+               goto exit_regs;
 
        ret = gpmi_get_clks(this);
        if (ret)
@@ -675,18 +632,12 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
 exit_clock:
        release_dma_channels(this);
-exit_dma_channels:
-       release_bch_irq(this);
 exit_regs:
-       release_register_block(this);
        return ret;
 }
 
 static void release_resources(struct gpmi_nand_data *this)
 {
-       gpmi_put_clks(this);
-       release_register_block(this);
-       release_bch_irq(this);
        release_dma_channels(this);
 }
 
@@ -732,8 +683,7 @@ static int read_page_prepare(struct gpmi_nand_data *this,
                                                length, DMA_FROM_DEVICE);
                if (dma_mapping_error(dev, dest_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -783,8 +733,7 @@ static int send_page_prepare(struct gpmi_nand_data *this,
                                                DMA_TO_DEVICE);
                if (dma_mapping_error(dev, source_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -837,14 +786,23 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 {
        struct bch_geometry *geo = &this->bch_geometry;
        struct device *dev = this->dev;
+       struct mtd_info *mtd = &this->mtd;
 
        /* [1] Allocate a command buffer. PAGE_SIZE is enough. */
        this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
        if (this->cmd_buffer == NULL)
                goto error_alloc;
 
-       /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
-       this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
+       /*
+        * [2] Allocate a read/write data buffer.
+        *     The gpmi_alloc_dma_buffer can be called twice.
+        *     We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer
+        *     is called before the nand_scan_ident; and we allocate a buffer
+        *     of the real NAND page size when the gpmi_alloc_dma_buffer is
+        *     called after the nand_scan_ident.
+        */
+       this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
+                                       GFP_DMA | GFP_KERNEL);
        if (this->data_buffer_dma == NULL)
                goto error_alloc;
 
@@ -872,7 +830,6 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 error_alloc:
        gpmi_free_dma_buffer(this);
-       pr_err("Error allocating DMA buffers!\n");
        return -ENOMEM;
 }
 
@@ -904,7 +861,8 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 
        ret = gpmi_send_command(this);
        if (ret)
-               pr_err("Chip: %u, Error %d\n", this->current_chip, ret);
+               dev_err(this->dev, "Chip: %u, Error %d\n",
+                       this->current_chip, ret);
 
        this->command_length = 0;
 }
@@ -935,7 +893,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = buf;
        this->upper_len = len;
 
@@ -947,7 +905,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = (uint8_t *)buf;
        this->upper_len = len;
 
@@ -1026,13 +984,13 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        unsigned int  max_bitflips = 0;
        int           ret;
 
-       pr_debug("page number is : %d\n", page);
+       dev_dbg(this->dev, "page number is : %d\n", page);
        ret = read_page_prepare(this, buf, mtd->writesize,
                                        this->payload_virt, this->payload_phys,
                                        nfc_geo->payload_size,
                                        &payload_virt, &payload_phys);
        if (ret) {
-               pr_err("Inadequate DMA buffer\n");
+               dev_err(this->dev, "Inadequate DMA buffer\n");
                ret = -ENOMEM;
                return ret;
        }
@@ -1046,7 +1004,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
                        nfc_geo->payload_size,
                        payload_virt, payload_phys);
        if (ret) {
-               pr_err("Error in ECC-based read: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based read: %d\n", ret);
                return ret;
        }
 
@@ -1102,7 +1060,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        dma_addr_t auxiliary_phys;
        int        ret;
 
-       pr_debug("ecc write page.\n");
+       dev_dbg(this->dev, "ecc write page.\n");
        if (this->swap_block_mark) {
                /*
                 * If control arrives here, we're doing block mark swapping.
@@ -1132,7 +1090,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->payload_size,
                                &payload_virt, &payload_phys);
                if (ret) {
-                       pr_err("Inadequate payload DMA buffer\n");
+                       dev_err(this->dev, "Inadequate payload DMA buffer\n");
                        return 0;
                }
 
@@ -1142,7 +1100,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->auxiliary_size,
                                &auxiliary_virt, &auxiliary_phys);
                if (ret) {
-                       pr_err("Inadequate auxiliary DMA buffer\n");
+                       dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
                        goto exit_auxiliary;
                }
        }
@@ -1150,7 +1108,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        /* Ask the NFC. */
        ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
        if (ret)
-               pr_err("Error in ECC-based write: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
 
        if (!this->swap_block_mark) {
                send_page_end(this, chip->oob_poi, mtd->oobsize,
@@ -1240,7 +1198,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 {
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("page number is %d\n", page);
+       dev_dbg(this->dev, "page number is %d\n", page);
        /* clear the OOB buffer */
        memset(chip->oob_poi, ~0, mtd->oobsize);
 
@@ -1453,7 +1411,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
 
        /* Write the NCB fingerprint into the page buffer. */
        memset(buffer, ~0, mtd->writesize);
-       memset(chip->oob_poi, ~0, mtd->oobsize);
        memcpy(buffer + 12, fingerprint, strlen(fingerprint));
 
        /* Loop through the first search area, writing NCB fingerprints. */
@@ -1568,7 +1525,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        /* Set up the NFC geometry which is used by BCH. */
        ret = bch_set_geometry(this);
        if (ret) {
-               pr_err("Error setting BCH geometry : %d\n", ret);
+               dev_err(this->dev, "Error setting BCH geometry : %d\n", ret);
                return ret;
        }
 
@@ -1576,20 +1533,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        return gpmi_alloc_dma_buffer(this);
 }
 
-static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
-{
-       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
-       if (GPMI_IS_MX23(this))
-               this->swap_block_mark = false;
-       else
-               this->swap_block_mark = true;
-
-       /* Set up the medium geometry */
-       return gpmi_set_geometry(this);
-
-}
-
-static void gpmi_nfc_exit(struct gpmi_nand_data *this)
+static void gpmi_nand_exit(struct gpmi_nand_data *this)
 {
        nand_release(&this->mtd);
        gpmi_free_dma_buffer(this);
@@ -1603,8 +1547,11 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        struct bch_geometry *bch_geo = &this->bch_geometry;
        int ret;
 
-       /* Prepare for the BBT scan. */
-       ret = gpmi_pre_bbt_scan(this);
+       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+       this->swap_block_mark = !GPMI_IS_MX23(this);
+
+       /* Set up the medium geometry */
+       ret = gpmi_set_geometry(this);
        if (ret)
                return ret;
 
@@ -1629,7 +1576,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        return 0;
 }
 
-static int gpmi_nfc_init(struct gpmi_nand_data *this)
+static int gpmi_nand_init(struct gpmi_nand_data *this)
 {
        struct mtd_info  *mtd = &this->mtd;
        struct nand_chip *chip = &this->nand;
@@ -1693,7 +1640,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
        return 0;
 
 err_out:
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        return ret;
 }
 
@@ -1728,15 +1675,13 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (of_id) {
                pdev->id_entry = of_id->data;
        } else {
-               pr_err("Failed to find the right device id.\n");
+               dev_err(&pdev->dev, "Failed to find the right device id.\n");
                return -ENODEV;
        }
 
        this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
-       if (!this) {
-               pr_err("Failed to allocate per-device memory\n");
+       if (!this)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, this);
        this->pdev  = pdev;
@@ -1750,7 +1695,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (ret)
                goto exit_nfc_init;
 
-       ret = gpmi_nfc_init(this);
+       ret = gpmi_nand_init(this);
        if (ret)
                goto exit_nfc_init;
 
@@ -1770,7 +1715,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
 {
        struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        release_resources(this);
        return 0;
 }
index a7685e3a87486b86713fef19da82e9bbad3c6253..4c801fa1872530e681e801d2adaee333d4acffb4 100644 (file)
@@ -26,8 +26,6 @@
 struct resources {
        void __iomem  *gpmi_regs;
        void __iomem  *bch_regs;
-       unsigned int  bch_low_interrupt;
-       unsigned int  bch_high_interrupt;
        unsigned int  dma_low_channel;
        unsigned int  dma_high_channel;
        struct clk    *clock[GPMI_CLK_MAX];
index a264b888c66cc9153e0f160af0c50e4675826a93..a2c804de156bc71d31407020b9ffb133a408b4f1 100644 (file)
@@ -416,10 +416,8 @@ static int jz_nand_probe(struct platform_device *pdev)
        uint8_t nand_maf_id = 0, nand_dev_id = 0;
 
        nand = kzalloc(sizeof(*nand), GFP_KERNEL);
-       if (!nand) {
-               dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+       if (!nand)
                return -ENOMEM;
-       }
 
        ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
        if (ret)
index 327d96c035050ce178711f03ee8ff4dd527a1fb3..687478c9f09c9a92aee00bdc595f6b5a8757bc0c 100644 (file)
@@ -539,20 +539,6 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd,
        return 0;
 }
 
-static int lpc32xx_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint32_t offset, int data_len, const uint8_t *buf,
-                       int oob_required, int page, int cached, int raw)
-{
-       int res;
-
-       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-       res = lpc32xx_write_page_lowlevel(mtd, chip, buf, oob_required);
-       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-       lpc32xx_waitfunc(mtd, chip);
-
-       return res;
-}
-
 static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
                            int page)
 {
@@ -627,10 +613,8 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
        struct device_node *np = dev->of_node;
 
        ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
-       if (!ncfg) {
-               dev_err(dev, "could not allocate memory for platform data\n");
+       if (!ncfg)
                return NULL;
-       }
 
        of_property_read_u32(np, "nxp,tcea-delay", &ncfg->tcea_delay);
        of_property_read_u32(np, "nxp,busy-delay", &ncfg->busy_delay);
@@ -666,10 +650,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+       if (!host)
                return -ENOMEM;
-       }
 
        rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->io_base = devm_ioremap_resource(&pdev->dev, rc);
@@ -732,9 +714,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        nand_chip->ecc.write_oob = lpc32xx_write_oob;
        nand_chip->ecc.read_oob = lpc32xx_read_oob;
        nand_chip->ecc.strength = 4;
-       nand_chip->write_page = lpc32xx_write_page;
        nand_chip->waitfunc = lpc32xx_waitfunc;
 
+       nand_chip->options = NAND_NO_SUBPAGE_WRITE;
        nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
        nand_chip->bbt_td = &lpc32xx_nand_bbt;
        nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror;
@@ -764,14 +746,12 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
        if (!host->dma_buf) {
-               dev_err(&pdev->dev, "Error allocating dma_buf memory\n");
                res = -ENOMEM;
                goto err_exit3;
        }
 
        host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
        if (!host->dummy_buf) {
-               dev_err(&pdev->dev, "Error allocating dummy_buf memory\n");
                res = -ENOMEM;
                goto err_exit3;
        }
index 23e6974ccd205ec23a7bf19adcea54ffb3304bfa..53a6742e3da39a2e1e43be81cf11be943c07a886 100644 (file)
@@ -725,10 +725,8 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
        struct device_node *np = dev->of_node;
 
        ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL);
-       if (!ncfg) {
-               dev_err(dev, "could not allocate memory for NAND config\n");
+       if (!ncfg)
                return NULL;
-       }
 
        of_property_read_u32(np, "nxp,wdr-clks", &ncfg->wdr_clks);
        of_property_read_u32(np, "nxp,wwidth", &ncfg->wwidth);
@@ -772,10 +770,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host) {
-               dev_err(&pdev->dev, "failed to allocate device structure\n");
+       if (!host)
                return -ENOMEM;
-       }
        host->io_base_dma = rc->start;
 
        host->io_base = devm_ioremap_resource(&pdev->dev, rc);
@@ -791,8 +787,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        }
        if (host->ncfg->wp_gpio == -EPROBE_DEFER)
                return -EPROBE_DEFER;
-       if (gpio_is_valid(host->ncfg->wp_gpio) &&
-                       gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
+       if (gpio_is_valid(host->ncfg->wp_gpio) && devm_gpio_request(&pdev->dev,
+                       host->ncfg->wp_gpio, "NAND WP")) {
                dev_err(&pdev->dev, "GPIO not available\n");
                return -EBUSY;
        }
@@ -808,7 +804,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        mtd->dev.parent = &pdev->dev;
 
        /* Get NAND clock */
-       host->clk = clk_get(&pdev->dev, NULL);
+       host->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->clk)) {
                dev_err(&pdev->dev, "Clock failure\n");
                res = -ENOENT;
@@ -858,7 +854,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        host->data_buf = devm_kzalloc(&pdev->dev, host->dma_buf_len,
                                      GFP_KERNEL);
        if (host->data_buf == NULL) {
-               dev_err(&pdev->dev, "Error allocating memory\n");
                res = -ENOMEM;
                goto err_exit2;
        }
@@ -927,10 +922,8 @@ err_exit3:
        dma_release_channel(host->dma_chan);
 err_exit2:
        clk_disable(host->clk);
-       clk_put(host->clk);
 err_exit1:
        lpc32xx_wp_enable(host);
-       gpio_free(host->ncfg->wp_gpio);
 
        return res;
 }
@@ -953,9 +946,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
        writel(tmp, SLC_CTRL(host->io_base));
 
        clk_disable(host->clk);
-       clk_put(host->clk);
        lpc32xx_wp_enable(host);
-       gpio_free(host->ncfg->wp_gpio);
 
        return 0;
 }
index 439bc389641841dc05f79ab638f7010e4a9cd053..61e2abc216ad321bf742ee2dcc1e57e3693c4192 100644 (file)
@@ -653,10 +653,8 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        }
 
        prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL);
-       if (!prv) {
-               dev_err(dev, "Memory exhausted!\n");
+       if (!prv)
                return -ENOMEM;
-       }
 
        mtd = &prv->mtd;
        chip = &prv->chip;
@@ -786,7 +784,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        /* Detect NAND chips */
        if (nand_scan(mtd, be32_to_cpup(chips_no))) {
                dev_err(dev, "NAND Flash not found !\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -811,7 +808,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 
        default:
                dev_err(dev, "Unsupported NAND flash!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -822,7 +818,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
        if (retval) {
                dev_err(dev, "Error adding MTD device!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                goto error;
        }
 
@@ -836,11 +831,8 @@ static int mpc5121_nfc_remove(struct platform_device *op)
 {
        struct device *dev = &op->dev;
        struct mtd_info *mtd = dev_get_drvdata(dev);
-       struct nand_chip *chip = mtd->priv;
-       struct mpc5121_nfc_prv *prv = chip->priv;
 
        nand_release(mtd);
-       devm_free_irq(dev, prv->irq, mtd);
        mpc5121_nfc_free(dev, mtd);
 
        return 0;
index 9dfdb06c508b05439cd93a71ce5c30ef8558335e..e9a4835c4dd9887f8546c5e95ce298674d5182a3 100644 (file)
@@ -677,7 +677,6 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
                ecc_stat >>= 4;
        } while (--no_subpages);
 
-       mtd->ecc_stats.corrected += ret;
        pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
 
        return ret;
@@ -1400,12 +1399,15 @@ static int mxcnd_probe(struct platform_device *pdev)
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
-                       NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
+       host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host),
+                       GFP_KERNEL);
        if (!host)
                return -ENOMEM;
 
-       host->data_buf = (uint8_t *)(host + 1);
+       /* allocate a temporary buffer for the nand_scan_ident() */
+       host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
+       if (!host->data_buf)
+               return -ENOMEM;
 
        host->dev = &pdev->dev;
        /* structures must be linked */
@@ -1512,7 +1514,9 @@ static int mxcnd_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       clk_prepare_enable(host->clk);
+       err = clk_prepare_enable(host->clk);
+       if (err)
+               return err;
        host->clk_act = 1;
 
        /*
@@ -1531,6 +1535,15 @@ static int mxcnd_probe(struct platform_device *pdev)
                goto escan;
        }
 
+       /* allocate the right size buffer now */
+       devm_kfree(&pdev->dev, (void *)host->data_buf);
+       host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
+                                       GFP_KERNEL);
+       if (!host->data_buf) {
+               err = -ENOMEM;
+               goto escan;
+       }
+
        /* Call preset again, with correct writesize this time */
        host->devtype_data->preset(mtd);
 
@@ -1576,6 +1589,8 @@ static int mxcnd_remove(struct platform_device *pdev)
        struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
        nand_release(&host->mtd);
+       if (host->clk_act)
+               clk_disable_unprepare(host->clk);
 
        return 0;
 }
index bd39f7b67906f65db526cbd0d1d27bb84ad93277..59eba5d2c68574fae787d36d2bd9e5ed29eb9f25 100644 (file)
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -201,6 +203,51 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
        }
 }
 
+/**
+ * nand_write_byte - [DEFAULT] write single byte to chip
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0]
+ */
+static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       chip->write_buf(mtd, &byte, 1);
+}
+
+/**
+ * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
+ * @mtd: MTD device structure
+ * @byte: value to write
+ *
+ * Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
+ */
+static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
+{
+       struct nand_chip *chip = mtd->priv;
+       uint16_t word = byte;
+
+       /*
+        * It's not entirely clear what should happen to I/O[15:8] when writing
+        * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
+        *
+        *    When the host supports a 16-bit bus width, only data is
+        *    transferred at the 16-bit width. All address and command line
+        *    transfers shall use only the lower 8-bits of the data bus. During
+        *    command transfers, the host may place any value on the upper
+        *    8-bits of the data bus. During address transfers, the host shall
+        *    set the upper 8-bits of the data bus to 00h.
+        *
+        * One user of the write_byte callback is nand_onfi_set_features. The
+        * four parameters are specified to be written to I/O[7:0], but this is
+        * neither an address nor a command transfer. Let's assume a 0 on the
+        * upper I/O lines is OK.
+        */
+       chip->write_buf(mtd, (uint8_t *)&word, 2);
+}
+
 /**
  * nand_write_buf - [DEFAULT] write buffer to chip
  * @mtd: MTD device structure
@@ -1407,6 +1454,30 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
        return NULL;
 }
 
+/**
+ * nand_setup_read_retry - [INTERN] Set the READ RETRY mode
+ * @mtd: MTD device structure
+ * @retry_mode: the retry mode to use
+ *
+ * Some vendors supply a special command to shift the Vt threshold, to be used
+ * when there are too many bitflips in a page (i.e., ECC error). After setting
+ * a new threshold, the host should retry reading the page.
+ */
+static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       pr_debug("setting READ RETRY mode %d\n", retry_mode);
+
+       if (retry_mode >= chip->read_retries)
+               return -EINVAL;
+
+       if (!chip->setup_read_retry)
+               return -EOPNOTSUPP;
+
+       return chip->setup_read_retry(mtd, retry_mode);
+}
+
 /**
  * nand_do_read_ops - [INTERN] Read data with ECC
  * @mtd: MTD device structure
@@ -1420,7 +1491,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 {
        int chipnr, page, realpage, col, bytes, aligned, oob_required;
        struct nand_chip *chip = mtd->priv;
-       struct mtd_ecc_stats stats;
        int ret = 0;
        uint32_t readlen = ops->len;
        uint32_t oobreadlen = ops->ooblen;
@@ -1429,8 +1499,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
        uint8_t *bufpoi, *oob, *buf;
        unsigned int max_bitflips = 0;
-
-       stats = mtd->ecc_stats;
+       int retry_mode = 0;
+       bool ecc_fail = false;
 
        chipnr = (int)(from >> chip->chip_shift);
        chip->select_chip(mtd, chipnr);
@@ -1445,6 +1515,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        oob_required = oob ? 1 : 0;
 
        while (1) {
+               unsigned int ecc_failures = mtd->ecc_stats.failed;
+
                bytes = min(mtd->writesize - col, readlen);
                aligned = (bytes == mtd->writesize);
 
@@ -1452,6 +1524,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                if (realpage != chip->pagebuf || oob) {
                        bufpoi = aligned ? buf : chip->buffers->databuf;
 
+read_retry:
                        chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
                        /*
@@ -1481,7 +1554,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        /* Transfer not aligned data */
                        if (!aligned) {
                                if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
-                                   !(mtd->ecc_stats.failed - stats.failed) &&
+                                   !(mtd->ecc_stats.failed - ecc_failures) &&
                                    (ops->mode != MTD_OPS_RAW)) {
                                        chip->pagebuf = realpage;
                                        chip->pagebuf_bitflips = ret;
@@ -1492,8 +1565,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                memcpy(buf, chip->buffers->databuf + col, bytes);
                        }
 
-                       buf += bytes;
-
                        if (unlikely(oob)) {
                                int toread = min(oobreadlen, max_oobsize);
 
@@ -1511,6 +1582,25 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                else
                                        nand_wait_ready(mtd);
                        }
+
+                       if (mtd->ecc_stats.failed - ecc_failures) {
+                               if (retry_mode + 1 <= chip->read_retries) {
+                                       retry_mode++;
+                                       ret = nand_setup_read_retry(mtd,
+                                                       retry_mode);
+                                       if (ret < 0)
+                                               break;
+
+                                       /* Reset failures; retry */
+                                       mtd->ecc_stats.failed = ecc_failures;
+                                       goto read_retry;
+                               } else {
+                                       /* No more retry modes; real failure */
+                                       ecc_fail = true;
+                               }
+                       }
+
+                       buf += bytes;
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -1520,6 +1610,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 
                readlen -= bytes;
 
+               /* Reset to retry mode 0 */
+               if (retry_mode) {
+                       ret = nand_setup_read_retry(mtd, 0);
+                       if (ret < 0)
+                               break;
+                       retry_mode = 0;
+               }
+
                if (!readlen)
                        break;
 
@@ -1545,7 +1643,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
        if (ret < 0)
                return ret;
 
-       if (mtd->ecc_stats.failed - stats.failed)
+       if (ecc_fail)
                return -EBADMSG;
 
        return max_bitflips;
@@ -2716,6 +2814,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
                        int addr, uint8_t *subfeature_param)
 {
        int status;
+       int i;
 
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
@@ -2723,7 +2822,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
                return -EINVAL;
 
        chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
-       chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+               chip->write_byte(mtd, subfeature_param[i]);
+
        status = chip->waitfunc(mtd, chip);
        if (status & NAND_STATUS_FAIL)
                return -EIO;
@@ -2740,6 +2841,8 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
                        int addr, uint8_t *subfeature_param)
 {
+       int i;
+
        if (!chip->onfi_version ||
            !(le16_to_cpu(chip->onfi_params.opt_cmd)
              & ONFI_OPT_CMD_SET_GET_FEATURES))
@@ -2749,7 +2852,8 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
        memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
 
        chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
-       chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
+       for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
+               *subfeature_param++ = chip->read_byte(mtd);
        return 0;
 }
 
@@ -2812,6 +2916,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                chip->block_markbad = nand_default_block_markbad;
        if (!chip->write_buf || chip->write_buf == nand_write_buf)
                chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+       if (!chip->write_byte || chip->write_byte == nand_write_byte)
+               chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
        if (!chip->read_buf || chip->read_buf == nand_read_buf)
                chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
        if (!chip->scan_bbt)
@@ -2926,6 +3032,30 @@ ext_out:
        return ret;
 }
 
+static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd->priv;
+       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
+
+       return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
+                       feature);
+}
+
+/*
+ * Configure chip properties from Micron vendor-specific ONFI table
+ */
+static void nand_onfi_detect_micron(struct nand_chip *chip,
+               struct nand_onfi_params *p)
+{
+       struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
+
+       if (le16_to_cpu(p->vendor_revision) < 1)
+               return;
+
+       chip->read_retries = micron->read_retry_options;
+       chip->setup_read_retry = nand_setup_read_retry_micron;
+}
+
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
@@ -2979,7 +3109,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                chip->onfi_version = 10;
 
        if (!chip->onfi_version) {
-               pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
+               pr_info("unsupported ONFI version: %d\n", val);
                return 0;
        }
 
@@ -3032,6 +3162,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                pr_warn("Could not retrieve ONFI ECC requirements\n");
        }
 
+       if (p->jedec_id == NAND_MFR_MICRON)
+               nand_onfi_detect_micron(chip, p);
+
        return 1;
 }
 
@@ -3152,9 +3285,12 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
                        mtd->oobsize = 512;
                        break;
                case 6:
-               default: /* Other cases are "reserved" (unknown) */
                        mtd->oobsize = 640;
                        break;
+               case 7:
+               default: /* Other cases are "reserved" (unknown) */
+                       mtd->oobsize = 1024;
+                       break;
                }
                extid >>= 2;
                /* Calc blocksize */
@@ -3325,6 +3461,9 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
 
                *busw = type->options & NAND_BUSWIDTH_16;
 
+               if (!mtd->name)
+                       mtd->name = type->name;
+
                return true;
        }
        return false;
@@ -3372,8 +3511,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                id_data[i] = chip->read_byte(mtd);
 
        if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-               pr_info("%s: second ID read did not match "
-                       "%02x,%02x against %02x,%02x\n", __func__,
+               pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
                        *maf_id, *dev_id, id_data[0], id_data[1]);
                return ERR_PTR(-ENODEV);
        }
@@ -3440,10 +3578,10 @@ ident_done:
                 * Check, if buswidth is correct. Hardware drivers should set
                 * chip correct!
                 */
-               pr_info("NAND device: Manufacturer ID:"
-                       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
-                       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-               pr_warn("NAND bus width %d instead %d bit\n",
+               pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+                       *maf_id, *dev_id);
+               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
+               pr_warn("bus width %d instead %d bit\n",
                           (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
                           busw ? 16 : 8);
                return ERR_PTR(-EINVAL);
@@ -3472,14 +3610,13 @@ ident_done:
        if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
                chip->cmdfunc = nand_command_lp;
 
-       pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)\n",
-               *maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
+       pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+               *maf_id, *dev_id);
+       pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
                chip->onfi_version ? chip->onfi_params.model : type->name);
-
-       pr_info("NAND device: %dMiB, %s, page size: %d, OOB size: %d\n",
+       pr_info("%dMiB, %s, page size: %d, OOB size: %d\n",
                (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
                mtd->writesize, mtd->oobsize);
-
        return type;
 }
 
@@ -3535,7 +3672,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                chip->select_chip(mtd, -1);
        }
        if (i > 1)
-               pr_info("%d NAND chips detected\n", i);
+               pr_info("%d chips detected\n", i);
 
        /* Store the number of chips and calc total size for mtd */
        chip->numchips = i;
index a87b0a3afa351a1b8f8991836cb99af930d858da..daa2faacd7d09f99422fa3f64fc6947a7f4f92cc 100644 (file)
@@ -169,6 +169,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
        {NAND_MFR_AMD, "AMD/Spansion"},
        {NAND_MFR_MACRONIX, "Macronix"},
        {NAND_MFR_EON, "Eon"},
+       {NAND_MFR_SANDISK, "SanDisk"},
+       {NAND_MFR_INTEL, "Intel"},
        {0x0, "Unknown"}
 };
 
index 52115151e4a7f325491a3dbf6f16ccd87221b37a..9ee09a8177c67feae055da60dcb033e9bf76f4c4 100644 (file)
@@ -241,12 +241,10 @@ static int nuc900_nand_probe(struct platform_device *pdev)
 {
        struct nuc900_nand *nuc900_nand;
        struct nand_chip *chip;
-       int retval;
        struct resource *res;
 
-       retval = 0;
-
-       nuc900_nand = kzalloc(sizeof(struct nuc900_nand), GFP_KERNEL);
+       nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand),
+                                  GFP_KERNEL);
        if (!nuc900_nand)
                return -ENOMEM;
        chip = &(nuc900_nand->chip);
@@ -255,11 +253,9 @@ static int nuc900_nand_probe(struct platform_device *pdev)
        nuc900_nand->mtd.owner  = THIS_MODULE;
        spin_lock_init(&nuc900_nand->lock);
 
-       nuc900_nand->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(nuc900_nand->clk)) {
-               retval = -ENOENT;
-               goto fail1;
-       }
+       nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(nuc900_nand->clk))
+               return -ENOENT;
        clk_enable(nuc900_nand->clk);
 
        chip->cmdfunc           = nuc900_nand_command_lp;
@@ -272,57 +268,29 @@ static int nuc900_nand_probe(struct platform_device *pdev)
        chip->ecc.mode          = NAND_ECC_SOFT;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               retval = -ENXIO;
-               goto fail1;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               retval = -EBUSY;
-               goto fail1;
-       }
-
-       nuc900_nand->reg = ioremap(res->start, resource_size(res));
-       if (!nuc900_nand->reg) {
-               retval = -ENOMEM;
-               goto fail2;
-       }
+       nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(nuc900_nand->reg))
+               return PTR_ERR(nuc900_nand->reg);
 
        nuc900_nand_enable(nuc900_nand);
 
-       if (nand_scan(&(nuc900_nand->mtd), 1)) {
-               retval = -ENXIO;
-               goto fail3;
-       }
+       if (nand_scan(&(nuc900_nand->mtd), 1))
+               return -ENXIO;
 
        mtd_device_register(&(nuc900_nand->mtd), partitions,
                            ARRAY_SIZE(partitions));
 
        platform_set_drvdata(pdev, nuc900_nand);
 
-       return retval;
-
-fail3: iounmap(nuc900_nand->reg);
-fail2: release_mem_region(res->start, resource_size(res));
-fail1: kfree(nuc900_nand);
-       return retval;
+       return 0;
 }
 
 static int nuc900_nand_remove(struct platform_device *pdev)
 {
        struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
-       struct resource *res;
 
        nand_release(&nuc900_nand->mtd);
-       iounmap(nuc900_nand->reg);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
        clk_disable(nuc900_nand->clk);
-       clk_put(nuc900_nand->clk);
-
-       kfree(nuc900_nand);
 
        return 0;
 }
index f77725009907751e62963f02a6ce52b10e41e366..ef4190a02b7bd591af7c97be8ee1e3caecf6f83c 100644 (file)
@@ -1730,13 +1730,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                break;
 
        case NAND_OMAP_POLLED:
-               if (nand_chip->options & NAND_BUSWIDTH_16) {
-                       nand_chip->read_buf   = omap_read_buf16;
-                       nand_chip->write_buf  = omap_write_buf16;
-               } else {
-                       nand_chip->read_buf   = omap_read_buf8;
-                       nand_chip->write_buf  = omap_write_buf8;
-               }
+               /* Use nand_base defaults for {read,write}_buf */
                break;
 
        case NAND_OMAP_PREFETCH_DMA:
index a393a5b6ce1e5028155a415ae33db88067a7bfff..dd7fe817eafb319ebc9ae92b2cbbac8613b38add 100644 (file)
@@ -87,7 +87,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 
        nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
        if (!nc) {
-               printk(KERN_ERR "orion_nand: failed to allocate device structure.\n");
                ret = -ENOMEM;
                goto no_res;
        }
@@ -101,7 +100,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 
        io_base = ioremap(res->start, resource_size(res));
        if (!io_base) {
-               printk(KERN_ERR "orion_nand: ioremap failed\n");
+               dev_err(&pdev->dev, "ioremap failed\n");
                ret = -EIO;
                goto no_res;
        }
@@ -110,7 +109,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
                board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data),
                                        GFP_KERNEL);
                if (!board) {
-                       printk(KERN_ERR "orion_nand: failed to allocate board structure.\n");
                        ret = -ENOMEM;
                        goto no_res;
                }
index 4d174366a0f09ec2ebecd99fc8241fc978a05caa..90f871acb0efec737c918532bbdd350ca7969220 100644 (file)
@@ -223,7 +223,7 @@ MODULE_DEVICE_TABLE(of, pasemi_nand_match);
 static struct platform_driver pasemi_nand_driver =
 {
        .driver = {
-               .name = (char*)driver_name,
+               .name = driver_name,
                .owner = THIS_MODULE,
                .of_match_table = pasemi_nand_match,
        },
index cad4cdc9df399a70c77640be5a634b837996790d..0b068a5c0bff3c05aa2eba8e1ae93a01f6b8db98 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -47,30 +48,16 @@ static int plat_nand_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
-
        /* Allocate memory for the device structure (and zero it) */
-       data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
-       if (!data) {
-               dev_err(&pdev->dev, "failed to allocate device structure.\n");
+       data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data),
+                           GFP_KERNEL);
+       if (!data)
                return -ENOMEM;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res),
-                               dev_name(&pdev->dev))) {
-               dev_err(&pdev->dev, "request_mem_region failed\n");
-               err = -EBUSY;
-               goto out_free;
-       }
 
-       data->io_base = ioremap(res->start, resource_size(res));
-       if (data->io_base == NULL) {
-               dev_err(&pdev->dev, "ioremap failed\n");
-               err = -EIO;
-               goto out_release_io;
-       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->io_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(data->io_base))
+               return PTR_ERR(data->io_base);
 
        data->chip.priv = &data;
        data->mtd.priv = &data->chip;
@@ -122,11 +109,6 @@ static int plat_nand_probe(struct platform_device *pdev)
 out:
        if (pdata->ctrl.remove)
                pdata->ctrl.remove(pdev);
-       iounmap(data->io_base);
-out_release_io:
-       release_mem_region(res->start, resource_size(res));
-out_free:
-       kfree(data);
        return err;
 }
 
@@ -137,16 +119,10 @@ static int plat_nand_remove(struct platform_device *pdev)
 {
        struct plat_nand_data *data = platform_get_drvdata(pdev);
        struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
        nand_release(&data->mtd);
        if (pdata->ctrl.remove)
                pdata->ctrl.remove(pdev);
-       iounmap(data->io_base);
-       release_mem_region(res->start, resource_size(res));
-       kfree(data);
 
        return 0;
 }
index 4b3aaa898a8b6b3a4975d2218370711981cb59c4..2a7a0b27ac38dccc511abd296742a767ef183133 100644 (file)
@@ -7,6 +7,8 @@
  * 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.
+ *
+ * See Documentation/mtd/nand/pxa3xx-nand.txt for more details.
  */
 
 #include <linux/kernel.h>
@@ -24,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mtd.h>
 
 #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
 #define ARCH_HAS_DMA
@@ -35,6 +38,7 @@
 
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
 
+#define NAND_DEV_READY_TIMEOUT  50
 #define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
 #define NAND_STOP_DELAY                (2 * HZ/50)
 #define PAGE_CHUNK_SIZE                (2048)
@@ -54,6 +58,7 @@
 #define NDPCR          (0x18) /* Page Count Register */
 #define NDBDR0         (0x1C) /* Bad Block Register 0 */
 #define NDBDR1         (0x20) /* Bad Block Register 1 */
+#define NDECCCTRL      (0x28) /* ECC control */
 #define NDDB           (0x40) /* Data Buffer */
 #define NDCB0          (0x48) /* Command Buffer0 */
 #define NDCB1          (0x4C) /* Command Buffer1 */
@@ -80,6 +85,9 @@
 #define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK              (0xfff)
+#define NDSR_ERR_CNT_OFF       (16)
+#define NDSR_ERR_CNT_MASK       (0x1f)
+#define NDSR_ERR_CNT(sr)       ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED         (0x1 << 10)
@@ -88,8 +96,8 @@
 #define NDSR_CS1_CMDD          (0x1 << 7)
 #define NDSR_CS0_BBD           (0x1 << 6)
 #define NDSR_CS1_BBD           (0x1 << 5)
-#define NDSR_DBERR             (0x1 << 4)
-#define NDSR_SBERR             (0x1 << 3)
+#define NDSR_UNCORERR          (0x1 << 4)
+#define NDSR_CORERR            (0x1 << 3)
 #define NDSR_WRDREQ            (0x1 << 2)
 #define NDSR_RDDREQ            (0x1 << 1)
 #define NDSR_WRCMDREQ          (0x1)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS          (0x1 << 25)
 #define NDCB0_CSEL             (0x1 << 24)
+#define NDCB0_EXT_CMD_TYPE_MASK        (0x7 << 29)
+#define NDCB0_EXT_CMD_TYPE(x)  (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK    (0x7 << 21)
 #define NDCB0_CMD_TYPE(x)      (((x) << 21) & NDCB0_CMD_TYPE_MASK)
 #define NDCB0_NC               (0x1 << 20)
 #define NDCB0_CMD1_MASK                (0xff)
 #define NDCB0_ADDR_CYC_SHIFT   (16)
 
+#define EXT_CMD_TYPE_DISPATCH  6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW  5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ      4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR   4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL     3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW   1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO      0 /* Monolithic read/write */
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)    \
        __raw_writel((val), (info)->mmio_base + (off))
@@ -120,9 +138,9 @@ enum {
        ERR_NONE        = 0,
        ERR_DMABUSERR   = -1,
        ERR_SENDCMD     = -2,
-       ERR_DBERR       = -3,
+       ERR_UNCORERR    = -3,
        ERR_BBERR       = -4,
-       ERR_SBERR       = -5,
+       ERR_CORERR      = -5,
 };
 
 enum {
@@ -149,7 +167,6 @@ struct pxa3xx_nand_host {
        void                    *info_data;
 
        /* page size of attached chip */
-       unsigned int            page_size;
        int                     use_ecc;
        int                     cs;
 
@@ -167,11 +184,13 @@ struct pxa3xx_nand_info {
        struct clk              *clk;
        void __iomem            *mmio_base;
        unsigned long           mmio_phys;
-       struct completion       cmd_complete;
+       struct completion       cmd_complete, dev_ready;
 
        unsigned int            buf_start;
        unsigned int            buf_count;
        unsigned int            buf_size;
+       unsigned int            data_buff_pos;
+       unsigned int            oob_buff_pos;
 
        /* DMA information */
        int                     drcmr_dat;
@@ -195,13 +214,18 @@ struct pxa3xx_nand_info {
 
        int                     cs;
        int                     use_ecc;        /* use HW ECC ? */
+       int                     ecc_bch;        /* using BCH ECC? */
        int                     use_dma;        /* use DMA ? */
        int                     use_spare;      /* use spare ? */
-       int                     is_ready;
+       int                     need_wait;
 
-       unsigned int            page_size;      /* page size of attached chip */
-       unsigned int            data_size;      /* data size in FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
+       unsigned int            chunk_size;     /* split commands chunk size */
        unsigned int            oob_size;
+       unsigned int            spare_size;
+       unsigned int            ecc_size;
+       unsigned int            ecc_err_cnt;
+       unsigned int            max_bitflips;
        int                     retcode;
 
        /* cached register value */
@@ -239,6 +263,64 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
 };
 
+static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
+static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_mirror_pattern
+};
+
+static struct nand_ecclayout ecc_layout_2KB_bch4bit = {
+       .eccbytes = 32,
+       .eccpos = {
+               32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47,
+               48, 49, 50, 51, 52, 53, 54, 55,
+               56, 57, 58, 59, 60, 61, 62, 63},
+       .oobfree = { {2, 30} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
+       .eccbytes = 64,
+       .eccpos = {
+               32,  33,  34,  35,  36,  37,  38,  39,
+               40,  41,  42,  43,  44,  45,  46,  47,
+               48,  49,  50,  51,  52,  53,  54,  55,
+               56,  57,  58,  59,  60,  61,  62,  63,
+               96,  97,  98,  99,  100, 101, 102, 103,
+               104, 105, 106, 107, 108, 109, 110, 111,
+               112, 113, 114, 115, 116, 117, 118, 119,
+               120, 121, 122, 123, 124, 125, 126, 127},
+       /* Bootrom looks in bytes 0 & 5 for bad blocks */
+       .oobfree = { {6, 26}, { 64, 32} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
+       .eccbytes = 128,
+       .eccpos = {
+               32,  33,  34,  35,  36,  37,  38,  39,
+               40,  41,  42,  43,  44,  45,  46,  47,
+               48,  49,  50,  51,  52,  53,  54,  55,
+               56,  57,  58,  59,  60,  61,  62,  63},
+       .oobfree = { }
+};
+
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
@@ -256,6 +338,29 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)      (int)((ns) * (clk / 1000000) / 1000)
 
+static struct of_device_id pxa3xx_nand_dt_ids[] = {
+       {
+               .compatible = "marvell,pxa3xx-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
+       },
+       {
+               .compatible = "marvell,armada370-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
+
+static enum pxa3xx_nand_variant
+pxa3xx_nand_get_variant(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
+       if (!of_id)
+               return PXA3XX_NAND_VARIANT_PXA;
+       return (enum pxa3xx_nand_variant)of_id->data;
+}
+
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
                                   const struct pxa3xx_nand_timing *t)
 {
@@ -280,25 +385,23 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
+/*
+ * Set the data and OOB size, depending on the selected
+ * spare and ECC configuration.
+ * Only applicable to READ0, READOOB and PAGEPROG commands.
+ */
+static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info,
+                               struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_host *host = info->host[info->cs];
        int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
 
-       info->data_size = host->page_size;
-       if (!oob_enable) {
-               info->oob_size = 0;
+       info->data_size = mtd->writesize;
+       if (!oob_enable)
                return;
-       }
 
-       switch (host->page_size) {
-       case 2048:
-               info->oob_size = (info->use_ecc) ? 40 : 64;
-               break;
-       case 512:
-               info->oob_size = (info->use_ecc) ? 8 : 16;
-               break;
-       }
+       info->oob_size = info->spare_size;
+       if (!info->use_ecc)
+               info->oob_size += info->ecc_size;
 }
 
 /**
@@ -313,10 +416,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 
        ndcr = info->reg_ndcr;
 
-       if (info->use_ecc)
+       if (info->use_ecc) {
                ndcr |= NDCR_ECC_EN;
-       else
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x1);
+       } else {
                ndcr &= ~NDCR_ECC_EN;
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x0);
+       }
 
        if (info->use_dma)
                ndcr |= NDCR_DMA_EN;
@@ -375,26 +483,39 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
+       unsigned int do_bytes = min(info->data_size, info->chunk_size);
+
        switch (info->state) {
        case STATE_PIO_WRITING:
-               __raw_writesl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_writesl(info->mmio_base + NDDB,
+                             info->data_buff + info->data_buff_pos,
+                             DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_writesl(info->mmio_base + NDDB,
+                                     info->oob_buff + info->oob_buff_pos,
+                                     DIV_ROUND_UP(info->oob_size, 4));
                break;
        case STATE_PIO_READING:
-               __raw_readsl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_readsl(info->mmio_base + NDDB,
+                            info->data_buff + info->data_buff_pos,
+                            DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_readsl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_readsl(info->mmio_base + NDDB,
+                                    info->oob_buff + info->oob_buff_pos,
+                                    DIV_ROUND_UP(info->oob_size, 4));
                break;
        default:
                dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
+
+       /* Update buffer pointers for multi-page read/write */
+       info->data_buff_pos += do_bytes;
+       info->oob_buff_pos += info->oob_size;
+       info->data_size -= do_bytes;
 }
 
 #ifdef ARCH_HAS_DMA
@@ -452,7 +573,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
-       unsigned int status, is_completed = 0;
+       unsigned int status, is_completed = 0, is_ready = 0;
        unsigned int ready, cmd_done;
 
        if (info->cs == 0) {
@@ -465,10 +586,25 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 
        status = nand_readl(info, NDSR);
 
-       if (status & NDSR_DBERR)
-               info->retcode = ERR_DBERR;
-       if (status & NDSR_SBERR)
-               info->retcode = ERR_SBERR;
+       if (status & NDSR_UNCORERR)
+               info->retcode = ERR_UNCORERR;
+       if (status & NDSR_CORERR) {
+               info->retcode = ERR_CORERR;
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
+                   info->ecc_bch)
+                       info->ecc_err_cnt = NDSR_ERR_CNT(status);
+               else
+                       info->ecc_err_cnt = 1;
+
+               /*
+                * Each chunk composing a page is corrected independently,
+                * and we need to store maximum number of corrected bitflips
+                * to return it to the MTD layer in ecc.read_page().
+                */
+               info->max_bitflips = max_t(unsigned int,
+                                          info->max_bitflips,
+                                          info->ecc_err_cnt);
+       }
        if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
                /* whether use dma to transfer data */
                if (info->use_dma) {
@@ -488,8 +624,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                is_completed = 1;
        }
        if (status & ready) {
-               info->is_ready = 1;
                info->state = STATE_READY;
+               is_ready = 1;
        }
 
        if (status & NDSR_WRCMDREQ) {
@@ -518,6 +654,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
        nand_writel(info, NDSR, status);
        if (is_completed)
                complete(&info->cmd_complete);
+       if (is_ready)
+               complete(&info->dev_ready);
 NORMAL_IRQ_EXIT:
        return IRQ_HANDLED;
 }
@@ -530,51 +668,94 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
        return 1;
 }
 
-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
-               uint16_t column, int page_addr)
+static void set_command_address(struct pxa3xx_nand_info *info,
+               unsigned int page_size, uint16_t column, int page_addr)
 {
-       int addr_cycle, exec_cmd;
-       struct pxa3xx_nand_host *host;
-       struct mtd_info *mtd;
+       /* small page addr setting */
+       if (page_size < PAGE_CHUNK_SIZE) {
+               info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+                               | (column & 0xFF);
 
-       host = info->host[info->cs];
-       mtd = host->mtd;
-       addr_cycle = 0;
-       exec_cmd = 1;
+               info->ndcb2 = 0;
+       } else {
+               info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+                               | (column & 0xFFFF);
+
+               if (page_addr & 0xFF0000)
+                       info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+               else
+                       info->ndcb2 = 0;
+       }
+}
+
+static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
+{
+       struct pxa3xx_nand_host *host = info->host[info->cs];
+       struct mtd_info *mtd = host->mtd;
 
        /* reset data and oob column point to handle data */
        info->buf_start         = 0;
        info->buf_count         = 0;
        info->oob_size          = 0;
+       info->data_buff_pos     = 0;
+       info->oob_buff_pos      = 0;
        info->use_ecc           = 0;
        info->use_spare         = 1;
-       info->is_ready          = 0;
        info->retcode           = ERR_NONE;
-       if (info->cs != 0)
-               info->ndcb0 = NDCB0_CSEL;
-       else
-               info->ndcb0 = 0;
+       info->ecc_err_cnt       = 0;
+       info->ndcb3             = 0;
+       info->need_wait         = 0;
 
        switch (command) {
        case NAND_CMD_READ0:
        case NAND_CMD_PAGEPROG:
                info->use_ecc = 1;
        case NAND_CMD_READOOB:
-               pxa3xx_set_datasize(info);
+               pxa3xx_set_datasize(info, mtd);
                break;
        case NAND_CMD_PARAM:
                info->use_spare = 0;
                break;
-       case NAND_CMD_SEQIN:
-               exec_cmd = 0;
-               break;
        default:
                info->ndcb1 = 0;
                info->ndcb2 = 0;
-               info->ndcb3 = 0;
                break;
        }
 
+       /*
+        * If we are about to issue a read command, or about to set
+        * the write address, then clean the data buffer.
+        */
+       if (command == NAND_CMD_READ0 ||
+           command == NAND_CMD_READOOB ||
+           command == NAND_CMD_SEQIN) {
+
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xFF, info->buf_count);
+       }
+
+}
+
+static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
+               int ext_cmd_type, uint16_t column, int page_addr)
+{
+       int addr_cycle, exec_cmd;
+       struct pxa3xx_nand_host *host;
+       struct mtd_info *mtd;
+
+       host = info->host[info->cs];
+       mtd = host->mtd;
+       addr_cycle = 0;
+       exec_cmd = 1;
+
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+       else
+               info->ndcb0 = 0;
+
+       if (command == NAND_CMD_SEQIN)
+               exec_cmd = 0;
+
        addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
                                    + host->col_addr_cycles);
 
@@ -589,30 +770,42 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                if (command == NAND_CMD_READOOB)
                        info->buf_start += mtd->writesize;
 
-               /* Second command setting for large pages */
-               if (host->page_size >= PAGE_CHUNK_SIZE)
+               /*
+                * Multiple page read needs an 'extended command type' field,
+                * which is either naked-read or last-read according to the
+                * state.
+                */
+               if (mtd->writesize == PAGE_CHUNK_SIZE) {
                        info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+               } else if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+               }
+
+               set_command_address(info, mtd->writesize, column, page_addr);
+               break;
 
        case NAND_CMD_SEQIN:
-               /* small page addr setting */
-               if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
-                       info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
-                                       | (column & 0xFF);
 
-                       info->ndcb2 = 0;
-               } else {
-                       info->ndcb1 = ((page_addr & 0xFFFF) << 16)
-                                       | (column & 0xFFFF);
+               info->buf_start = column;
+               set_command_address(info, mtd->writesize, 0, page_addr);
 
-                       if (page_addr & 0xFF0000)
-                               info->ndcb2 = (page_addr & 0xFF0000) >> 16;
-                       else
-                               info->ndcb2 = 0;
+               /*
+                * Multiple page programming needs to execute the initial
+                * SEQIN command that sets the page address.
+                */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                               | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                               | addr_cycle
+                               | command;
+                       /* No data transfer in this case */
+                       info->data_size = 0;
+                       exec_cmd = 1;
                }
-
-               info->buf_count = mtd->writesize + mtd->oobsize;
-               memset(info->data_buff, 0xFF, info->buf_count);
-
                break;
 
        case NAND_CMD_PAGEPROG:
@@ -622,13 +815,40 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                        break;
                }
 
-               info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
-                               | NDCB0_AUTO_RS
-                               | NDCB0_ST_ROW_EN
-                               | NDCB0_DBC
-                               | (NAND_CMD_PAGEPROG << 8)
-                               | NAND_CMD_SEQIN
-                               | addr_cycle;
+               /* Second command setting for large pages */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       /*
+                        * Multiple page write uses the 'extended command'
+                        * field. This can be used to issue a command dispatch
+                        * or a naked-write depending on the current stage.
+                        */
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+
+                       /*
+                        * This is the command dispatch that completes a chunked
+                        * page program operation.
+                        */
+                       if (info->data_size == 0) {
+                               info->ndcb0 = NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                                       | command;
+                               info->ndcb1 = 0;
+                               info->ndcb2 = 0;
+                               info->ndcb3 = 0;
+                       }
+               } else {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_AUTO_RS
+                                       | NDCB0_ST_ROW_EN
+                                       | NDCB0_DBC
+                                       | (NAND_CMD_PAGEPROG << 8)
+                                       | NAND_CMD_SEQIN
+                                       | addr_cycle;
+               }
                break;
 
        case NAND_CMD_PARAM:
@@ -691,8 +911,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
        return exec_cmd;
 }
 
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-                               int column, int page_addr)
+static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+                        int column, int page_addr)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
@@ -717,10 +937,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                nand_writel(info, NDTR1CS0, info->ndtr1cs0);
        }
 
+       prepare_start_command(info, command);
+
        info->state = STATE_PREPARED;
-       exec_cmd = prepare_command_pool(info, command, column, page_addr);
+       exec_cmd = prepare_set_command(info, command, 0, column, page_addr);
+
        if (exec_cmd) {
                init_completion(&info->cmd_complete);
+               init_completion(&info->dev_ready);
+               info->need_wait = 1;
                pxa3xx_nand_start(info);
 
                ret = wait_for_completion_timeout(&info->cmd_complete,
@@ -734,6 +959,117 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
        info->state = STATE_IDLE;
 }
 
+static void nand_cmdfunc_extended(struct mtd_info *mtd,
+                                 const unsigned command,
+                                 int column, int page_addr)
+{
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+       int ret, exec_cmd, ext_cmd_type;
+
+       /*
+        * if this is a x16 device then convert the input
+        * "byte" address into a "word" address appropriate
+        * for indexing a word-oriented device
+        */
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
+               column /= 2;
+
+       /*
+        * There may be different NAND chip hooked to
+        * different chip select, so check whether
+        * chip select has been changed, if yes, reset the timing
+        */
+       if (info->cs != host->cs) {
+               info->cs = host->cs;
+               nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+               nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+       }
+
+       /* Select the extended command for the first command */
+       switch (command) {
+       case NAND_CMD_READ0:
+       case NAND_CMD_READOOB:
+               ext_cmd_type = EXT_CMD_TYPE_MONO;
+               break;
+       case NAND_CMD_SEQIN:
+               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               break;
+       case NAND_CMD_PAGEPROG:
+               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+               break;
+       default:
+               ext_cmd_type = 0;
+               break;
+       }
+
+       prepare_start_command(info, command);
+
+       /*
+        * Prepare the "is ready" completion before starting a command
+        * transaction sequence. If the command is not executed the
+        * completion will be completed, see below.
+        *
+        * We can do that inside the loop because the command variable
+        * is invariant and thus so is the exec_cmd.
+        */
+       info->need_wait = 1;
+       init_completion(&info->dev_ready);
+       do {
+               info->state = STATE_PREPARED;
+               exec_cmd = prepare_set_command(info, command, ext_cmd_type,
+                                              column, page_addr);
+               if (!exec_cmd) {
+                       info->need_wait = 0;
+                       complete(&info->dev_ready);
+                       break;
+               }
+
+               init_completion(&info->cmd_complete);
+               pxa3xx_nand_start(info);
+
+               ret = wait_for_completion_timeout(&info->cmd_complete,
+                               CHIP_DELAY_TIMEOUT);
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Wait time out!!!\n");
+                       /* Stop State Machine for next command cycle */
+                       pxa3xx_nand_stop(info);
+                       break;
+               }
+
+               /* Check if the sequence is complete */
+               if (info->data_size == 0 && command != NAND_CMD_PAGEPROG)
+                       break;
+
+               /*
+                * After a splitted program command sequence has issued
+                * the command dispatch, the command sequence is complete.
+                */
+               if (info->data_size == 0 &&
+                   command == NAND_CMD_PAGEPROG &&
+                   ext_cmd_type == EXT_CMD_TYPE_DISPATCH)
+                       break;
+
+               if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) {
+                       /* Last read: issue a 'last naked read' */
+                       if (info->data_size == info->chunk_size)
+                               ext_cmd_type = EXT_CMD_TYPE_LAST_RW;
+                       else
+                               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+
+               /*
+                * If a splitted program command has no more data to transfer,
+                * the command dispatch must be issued to complete.
+                */
+               } else if (command == NAND_CMD_PAGEPROG &&
+                          info->data_size == 0) {
+                               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               }
+       } while (1);
+
+       info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
                struct nand_chip *chip, const uint8_t *buf, int oob_required)
 {
@@ -753,20 +1089,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-       if (info->retcode == ERR_SBERR) {
-               switch (info->use_ecc) {
-               case 1:
-                       mtd->ecc_stats.corrected++;
-                       break;
-               case 0:
-               default:
-                       break;
-               }
-       } else if (info->retcode == ERR_DBERR) {
+       if (info->retcode == ERR_CORERR && info->use_ecc) {
+               mtd->ecc_stats.corrected += info->ecc_err_cnt;
+
+       } else if (info->retcode == ERR_UNCORERR) {
                /*
                 * for blank page (all 0xff), HW will calculate its ECC as
                 * 0, which is different from the ECC information within
-                * OOB, ignore such double bit errors
+                * OOB, ignore such uncorrectable errors
                 */
                if (is_buf_blank(buf, mtd->writesize))
                        info->retcode = ERR_NONE;
@@ -774,7 +1104,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
                        mtd->ecc_stats.failed++;
        }
 
-       return 0;
+       return info->max_bitflips;
 }
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
@@ -833,21 +1163,27 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
+       int ret;
+
+       if (info->need_wait) {
+               ret = wait_for_completion_timeout(&info->dev_ready,
+                               CHIP_DELAY_TIMEOUT);
+               info->need_wait = 0;
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Ready time out!!!\n");
+                       return NAND_STATUS_FAIL;
+               }
+       }
 
        /* pxa3xx_nand_send_command has waited for command complete */
        if (this->state == FL_WRITING || this->state == FL_ERASING) {
                if (info->retcode == ERR_NONE)
                        return 0;
-               else {
-                       /*
-                        * any error make it return 0x01 which will tell
-                        * the caller the erase and write fail
-                        */
-                       return 0x01;
-               }
+               else
+                       return NAND_STATUS_FAIL;
        }
 
-       return 0;
+       return NAND_STATUS_READY;
 }
 
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
@@ -869,7 +1205,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
        }
 
        /* calculate flash information */
-       host->page_size = f->page_size;
        host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
@@ -906,13 +1241,15 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
        uint32_t ndcr = nand_readl(info, NDCR);
 
        if (ndcr & NDCR_PAGE_SZ) {
-               host->page_size = 2048;
+               /* Controller's FIFO size */
+               info->chunk_size = 2048;
                host->read_id_bytes = 4;
        } else {
-               host->page_size = 512;
+               info->chunk_size = 512;
                host->read_id_bytes = 2;
        }
 
+       /* Set an initial chunk size */
        info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
        info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
        info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
@@ -988,18 +1325,89 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
        struct mtd_info *mtd;
+       struct nand_chip *chip;
        int ret;
+
        mtd = info->host[info->cs]->mtd;
+       chip = mtd->priv;
+
        /* use the common timing to make a try */
        ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
        if (ret)
                return ret;
 
-       pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-       if (info->is_ready)
-               return 0;
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       ret = chip->waitfunc(mtd, chip);
+       if (ret & NAND_STATUS_FAIL)
+               return -ENODEV;
+
+       return 0;
+}
 
-       return -ENODEV;
+static int pxa_ecc_init(struct pxa3xx_nand_info *info,
+                       struct nand_ecc_ctrl *ecc,
+                       int strength, int ecc_stepsize, int page_size)
+{
+       if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
+               info->chunk_size = 2048;
+               info->spare_size = 40;
+               info->ecc_size = 24;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+
+       } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) {
+               info->chunk_size = 512;
+               info->spare_size = 8;
+               info->ecc_size = 8;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+
+       /*
+        * Required ECC: 4-bit correction per 512 bytes
+        * Select: 16-bit correction per 2048 bytes
+        */
+       } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_2KB_bch4bit;
+               ecc->strength = 16;
+               return 1;
+
+       } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch4bit;
+               ecc->strength = 16;
+               return 1;
+
+       /*
+        * Required ECC: 8-bit correction per 512 bytes
+        * Select: 16-bit correction per 1024 bytes
+        */
+       } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 1024;
+               info->spare_size = 0;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch8bit;
+               ecc->strength = 16;
+               return 1;
+       }
+       return 0;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
@@ -1014,6 +1422,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        uint32_t id = -1;
        uint64_t chipsize;
        int i, ret, num;
+       uint16_t ecc_strength, ecc_step;
 
        if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
                goto KEEP_CONFIG;
@@ -1072,15 +1481,60 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        pxa3xx_flash_ids[1].name = NULL;
        def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-       chip->ecc.mode = NAND_ECC_HW;
-       chip->ecc.size = host->page_size;
-       chip->ecc.strength = 1;
-
        if (info->reg_ndcr & NDCR_DWIDTH_M)
                chip->options |= NAND_BUSWIDTH_16;
 
+       /* Device detection must be done with ECC disabled */
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               nand_writel(info, NDECCCTRL, 0x0);
+
        if (nand_scan_ident(mtd, 1, def))
                return -ENODEV;
+
+       if (pdata->flash_bbt) {
+               /*
+                * We'll use a bad block table stored in-flash and don't
+                * allow writing the bad block marker to the flash.
+                */
+               chip->bbt_options |= NAND_BBT_USE_FLASH |
+                                    NAND_BBT_NO_OOB_BBM;
+               chip->bbt_td = &bbt_main_descr;
+               chip->bbt_md = &bbt_mirror_descr;
+       }
+
+       /*
+        * If the page size is bigger than the FIFO size, let's check
+        * we are given the right variant and then switch to the extended
+        * (aka splitted) command handling,
+        */
+       if (mtd->writesize > PAGE_CHUNK_SIZE) {
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
+                       chip->cmdfunc = nand_cmdfunc_extended;
+               } else {
+                       dev_err(&info->pdev->dev,
+                               "unsupported page size on this variant\n");
+                       return -ENODEV;
+               }
+       }
+
+       ecc_strength = chip->ecc_strength_ds;
+       ecc_step = chip->ecc_step_ds;
+
+       /* Set default ECC strength requirements on non-ONFI devices */
+       if (ecc_strength < 1 && ecc_step < 1) {
+               ecc_strength = 1;
+               ecc_step = 512;
+       }
+
+       ret = pxa_ecc_init(info, &chip->ecc, ecc_strength,
+                          ecc_step, mtd->writesize);
+       if (!ret) {
+               dev_err(&info->pdev->dev,
+                       "ECC strength %d at page size %d is not supported\n",
+                       chip->ecc_strength_ds, mtd->writesize);
+               return -ENODEV;
+       }
+
        /* calculate addressing information */
        if (mtd->writesize >= 2048)
                host->col_addr_cycles = 2;
@@ -1121,6 +1575,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
                return -ENOMEM;
 
        info->pdev = pdev;
+       info->variant = pxa3xx_nand_get_variant(pdev);
        for (cs = 0; cs < pdata->num_cs; cs++) {
                mtd = (struct mtd_info *)((unsigned int)&info[1] +
                      (sizeof(*mtd) + sizeof(*host)) * cs);
@@ -1138,11 +1593,12 @@ static int alloc_nand_resource(struct platform_device *pdev)
                chip->controller        = &info->controller;
                chip->waitfunc          = pxa3xx_nand_waitfunc;
                chip->select_chip       = pxa3xx_nand_select_chip;
-               chip->cmdfunc           = pxa3xx_nand_cmdfunc;
                chip->read_word         = pxa3xx_nand_read_word;
                chip->read_byte         = pxa3xx_nand_read_byte;
                chip->read_buf          = pxa3xx_nand_read_buf;
                chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->options           |= NAND_NO_SUBPAGE_WRITE;
+               chip->cmdfunc           = nand_cmdfunc;
        }
 
        spin_lock_init(&chip->controller->lock);
@@ -1254,25 +1710,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id pxa3xx_nand_dt_ids[] = {
-       {
-               .compatible = "marvell,pxa3xx-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
-
-static enum pxa3xx_nand_variant
-pxa3xx_nand_get_variant(struct platform_device *pdev)
-{
-       const struct of_device_id *of_id =
-                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
-       if (!of_id)
-               return PXA3XX_NAND_VARIANT_PXA;
-       return (enum pxa3xx_nand_variant)of_id->data;
-}
-
 static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
 {
        struct pxa3xx_nand_platform_data *pdata;
@@ -1292,6 +1729,7 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
        if (of_get_property(np, "marvell,nand-keep-config", NULL))
                pdata->keep_config = 1;
        of_property_read_u32(np, "num-cs", &pdata->num_cs);
+       pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
 
        pdev->dev.platform_data = pdata;
 
@@ -1329,7 +1767,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        }
 
        info = platform_get_drvdata(pdev);
-       info->variant = pxa3xx_nand_get_variant(pdev);
        probe_success = 0;
        for (cs = 0; cs < pdata->num_cs; cs++) {
                struct mtd_info *mtd = info->host[cs]->mtd;
index d65cbe903d4015e37076f0505db987ee4383e0d5..f0918e7411d99147fd67c26c48a8672cb237437f 100644 (file)
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <plat/regs-nand.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF         S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD          S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR         S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA         S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT         S3C2410_NFREG(0x10)
+#define S3C2410_NFECC          S3C2410_NFREG(0x14)
+#define S3C2440_NFCONT         S3C2410_NFREG(0x04)
+#define S3C2440_NFCMD          S3C2410_NFREG(0x08)
+#define S3C2440_NFADDR         S3C2410_NFREG(0x0C)
+#define S3C2440_NFDATA         S3C2410_NFREG(0x10)
+#define S3C2440_NFSTAT         S3C2410_NFREG(0x20)
+#define S3C2440_NFMECC0                S3C2410_NFREG(0x2C)
+#define S3C2412_NFSTAT         S3C2410_NFREG(0x28)
+#define S3C2412_NFMECC0                S3C2410_NFREG(0x34)
+#define S3C2410_NFCONF_EN              (1<<15)
+#define S3C2410_NFCONF_INITECC         (1<<12)
+#define S3C2410_NFCONF_nFCE            (1<<11)
+#define S3C2410_NFCONF_TACLS(x)                ((x)<<8)
+#define S3C2410_NFCONF_TWRPH0(x)       ((x)<<4)
+#define S3C2410_NFCONF_TWRPH1(x)       ((x)<<0)
+#define S3C2410_NFSTAT_BUSY            (1<<0)
+#define S3C2440_NFCONF_TACLS(x)                ((x)<<12)
+#define S3C2440_NFCONF_TWRPH0(x)       ((x)<<8)
+#define S3C2440_NFCONF_TWRPH1(x)       ((x)<<4)
+#define S3C2440_NFCONT_INITECC         (1<<4)
+#define S3C2440_NFCONT_nFCE            (1<<1)
+#define S3C2440_NFCONT_ENABLE          (1<<0)
+#define S3C2440_NFSTAT_READY           (1<<0)
+#define S3C2412_NFCONF_NANDBOOT                (1<<31)
+#define S3C2412_NFCONT_INIT_MAIN_ECC   (1<<5)
+#define S3C2412_NFCONT_nFCE0           (1<<1)
+#define S3C2412_NFSTAT_READY           (1<<0)
+
 /* new oob placement block for use with hardware ecc generation
  */
 
@@ -919,7 +953,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
-               dev_err(&pdev->dev, "no memory for flash info\n");
                err = -ENOMEM;
                goto exit_error;
        }
@@ -974,7 +1007,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
        size = nr_sets * sizeof(*info->mtds);
        info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
        if (info->mtds == NULL) {
-               dev_err(&pdev->dev, "failed to allocate mtd storage\n");
                err = -ENOMEM;
                goto exit_error;
        }
index a3c84ebbe39227dac06bae3d0f9014849cf48b17..d72783dd7b962f798f1256067e3d4d9f5a1c5366 100644 (file)
@@ -151,7 +151,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
        dma_cap_set(DMA_SLAVE, mask);
 
        flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_tx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_tx);
        dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__,
                flctl->chan_fifo0_tx);
 
@@ -168,7 +168,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
                goto err;
 
        flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_rx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_rx);
        dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__,
                flctl->chan_fifo0_rx);
 
@@ -1021,7 +1021,6 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
 struct flctl_soc_config {
        unsigned long flcmncr_val;
        unsigned has_hwecc:1;
@@ -1059,10 +1058,8 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 
        pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
                                                                GFP_KERNEL);
-       if (!pdata) {
-               dev_err(dev, "%s: failed to allocate config data\n", __func__);
+       if (!pdata)
                return NULL;
-       }
 
        /* set SoC specific options */
        pdata->flcmncr_val = config->flcmncr_val;
@@ -1080,12 +1077,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
 
        return pdata;
 }
-#else /* CONFIG_OF */
-static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
-{
-       return NULL;
-}
-#endif /* CONFIG_OF */
 
 static int flctl_probe(struct platform_device *pdev)
 {
@@ -1094,38 +1085,30 @@ static int flctl_probe(struct platform_device *pdev)
        struct mtd_info *flctl_mtd;
        struct nand_chip *nand;
        struct sh_flctl_platform_data *pdata;
-       int ret = -ENXIO;
+       int ret;
        int irq;
        struct mtd_part_parser_data ppdata = {};
 
-       flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
-       if (!flctl) {
-               dev_err(&pdev->dev, "failed to allocate driver data\n");
+       flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
+       if (!flctl)
                return -ENOMEM;
-       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to get I/O memory\n");
-               goto err_iomap;
-       }
-
-       flctl->reg = ioremap(res->start, resource_size(res));
-       if (flctl->reg == NULL) {
-               dev_err(&pdev->dev, "failed to remap I/O memory\n");
-               goto err_iomap;
-       }
+       flctl->reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(flctl->reg))
+               return PTR_ERR(flctl->reg);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "failed to get flste irq data\n");
-               goto err_flste;
+               return -ENXIO;
        }
 
-       ret = request_irq(irq, flctl_handle_flste, IRQF_SHARED, "flste", flctl);
+       ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
+                              "flste", flctl);
        if (ret) {
                dev_err(&pdev->dev, "request interrupt failed.\n");
-               goto err_flste;
+               return ret;
        }
 
        if (pdev->dev.of_node)
@@ -1135,8 +1118,7 @@ static int flctl_probe(struct platform_device *pdev)
 
        if (!pdata) {
                dev_err(&pdev->dev, "no setup data defined\n");
-               ret = -EINVAL;
-               goto err_pdata;
+               return -EINVAL;
        }
 
        platform_set_drvdata(pdev, flctl);
@@ -1190,12 +1172,6 @@ static int flctl_probe(struct platform_device *pdev)
 err_chip:
        flctl_release_dma(flctl);
        pm_runtime_disable(&pdev->dev);
-err_pdata:
-       free_irq(irq, flctl);
-err_flste:
-       iounmap(flctl->reg);
-err_iomap:
-       kfree(flctl);
        return ret;
 }
 
@@ -1206,9 +1182,6 @@ static int flctl_remove(struct platform_device *pdev)
        flctl_release_dma(flctl);
        nand_release(&flctl->mtd);
        pm_runtime_disable(&pdev->dev);
-       free_irq(platform_get_irq(pdev, 0), flctl);
-       iounmap(flctl->reg);
-       kfree(flctl);
 
        return 0;
 }
index 87908d760feb067c3cb179b35bfa5a3c462ab737..e81059b58382f23af69848211415c4095ea36edf 100644 (file)
@@ -121,10 +121,8 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
 
        /* Allocate memory for MTD device structure and private data */
        sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL);
-       if (!sharpsl) {
-               printk("Unable to allocate SharpSL NAND MTD device structure.\n");
+       if (!sharpsl)
                return -ENOMEM;
-       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
@@ -136,7 +134,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
        /* map physical address */
        sharpsl->io = ioremap(r->start, resource_size(r));
        if (!sharpsl->io) {
-               printk("ioremap to access Sharp SL NAND chip failed\n");
+               dev_err(&pdev->dev, "ioremap to access Sharp SL NAND chip failed\n");
                err = -EIO;
                goto err_ioremap;
        }
index a3747c914d5718abd342f53f8253e2d4c0ea3353..fb8fd35fa668516dcb763037e164691482eca9ea 100644 (file)
@@ -371,11 +371,9 @@ static int tmio_probe(struct platform_device *dev)
        if (data == NULL)
                dev_warn(&dev->dev, "NULL platform data!\n");
 
-       tmio = kzalloc(sizeof *tmio, GFP_KERNEL);
-       if (!tmio) {
-               retval = -ENOMEM;
-               goto err_kzalloc;
-       }
+       tmio = devm_kzalloc(&dev->dev, sizeof(*tmio), GFP_KERNEL);
+       if (!tmio)
+               return -ENOMEM;
 
        tmio->dev = dev;
 
@@ -385,22 +383,18 @@ static int tmio_probe(struct platform_device *dev)
        mtd->priv = nand_chip;
        mtd->name = "tmio-nand";
 
-       tmio->ccr = ioremap(ccr->start, resource_size(ccr));
-       if (!tmio->ccr) {
-               retval = -EIO;
-               goto err_iomap_ccr;
-       }
+       tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr));
+       if (!tmio->ccr)
+               return -EIO;
 
        tmio->fcr_base = fcr->start & 0xfffff;
-       tmio->fcr = ioremap(fcr->start, resource_size(fcr));
-       if (!tmio->fcr) {
-               retval = -EIO;
-               goto err_iomap_fcr;
-       }
+       tmio->fcr = devm_ioremap(&dev->dev, fcr->start, resource_size(fcr));
+       if (!tmio->fcr)
+               return -EIO;
 
        retval = tmio_hw_init(dev, tmio);
        if (retval)
-               goto err_hwinit;
+               return retval;
 
        /* Set address of NAND IO lines */
        nand_chip->IO_ADDR_R = tmio->fcr;
@@ -428,7 +422,8 @@ static int tmio_probe(struct platform_device *dev)
        /* 15 us command delay time */
        nand_chip->chip_delay = 15;
 
-       retval = request_irq(irq, &tmio_irq, 0, dev_name(&dev->dev), tmio);
+       retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0,
+                                 dev_name(&dev->dev), tmio);
        if (retval) {
                dev_err(&dev->dev, "request_irq error %d\n", retval);
                goto err_irq;
@@ -440,7 +435,7 @@ static int tmio_probe(struct platform_device *dev)
        /* Scan to find existence of the device */
        if (nand_scan(mtd, 1)) {
                retval = -ENODEV;
-               goto err_scan;
+               goto err_irq;
        }
        /* Register the partitions */
        retval = mtd_device_parse_register(mtd, NULL, NULL,
@@ -451,18 +446,8 @@ static int tmio_probe(struct platform_device *dev)
 
        nand_release(mtd);
 
-err_scan:
-       if (tmio->irq)
-               free_irq(tmio->irq, tmio);
 err_irq:
        tmio_hw_stop(dev, tmio);
-err_hwinit:
-       iounmap(tmio->fcr);
-err_iomap_fcr:
-       iounmap(tmio->ccr);
-err_iomap_ccr:
-       kfree(tmio);
-err_kzalloc:
        return retval;
 }
 
@@ -471,12 +456,7 @@ static int tmio_remove(struct platform_device *dev)
        struct tmio_nand *tmio = platform_get_drvdata(dev);
 
        nand_release(&tmio->mtd);
-       if (tmio->irq)
-               free_irq(tmio->irq, tmio);
        tmio_hw_stop(dev, tmio);
-       iounmap(tmio->fcr);
-       iounmap(tmio->ccr);
-       kfree(tmio);
        return 0;
 }
 
index 235714a421dd6770851f2f5026522123f46dbefc..c1622a5ba8140710bf7807a31a622c283c45ad4b 100644 (file)
@@ -319,11 +319,8 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
                        continue;
                txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv),
                                    GFP_KERNEL);
-               if (!txx9_priv) {
-                       dev_err(&dev->dev, "Unable to allocate "
-                               "TXx9 NDFMC MTD device structure.\n");
+               if (!txx9_priv)
                        continue;
-               }
                chip = &txx9_priv->chip;
                mtd = &txx9_priv->mtd;
                mtd->owner = THIS_MODULE;
index d64f8c30945fbcd8e2d09a5b8342e75c081cd343..aa26c32e1bc28943426992eba09fddc207cf104d 100644 (file)
@@ -81,7 +81,7 @@ static int parse_ofpart_partitions(struct mtd_info *master,
                partname = of_get_property(pp, "label", &len);
                if (!partname)
                        partname = of_get_property(pp, "name", &len);
-               (*pparts)[i].name = (char *)partname;
+               (*pparts)[i].name = partname;
 
                if (of_get_property(pp, "read-only", &len))
                        (*pparts)[i].mask_flags |= MTD_WRITEABLE;
@@ -152,7 +152,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
                if (names && (plen > 0)) {
                        int len = strlen(names) + 1;
 
-                       (*pparts)[i].name = (char *)names;
+                       (*pparts)[i].name = names;
                        plen -= len;
                        names += len;
                } else {
@@ -173,18 +173,9 @@ static struct mtd_part_parser ofoldpart_parser = {
 
 static int __init ofpart_parser_init(void)
 {
-       int rc;
-       rc = register_mtd_parser(&ofpart_parser);
-       if (rc)
-               goto out;
-
-       rc = register_mtd_parser(&ofoldpart_parser);
-       if (!rc)
-               return 0;
-
-       deregister_mtd_parser(&ofoldpart_parser);
-out:
-       return rc;
+       register_mtd_parser(&ofpart_parser);
+       register_mtd_parser(&ofoldpart_parser);
+       return 0;
 }
 
 static void __exit ofpart_parser_exit(void)
index 63699fffc96de24b3098f629ea495184103386c8..8e1919b6f07449f007c0b1766f4ffcde5db4c0f1 100644 (file)
@@ -58,7 +58,7 @@ static int generic_onenand_probe(struct platform_device *pdev)
                goto out_release_mem_region;
        }
 
-       info->onenand.mmcontrol = pdata ? pdata->mmcontrol : 0;
+       info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
        info->onenand.irq = platform_get_irq(pdev, 0);
 
        info->mtd.name = dev_name(&pdev->dev);
index 580035c803d693eb38b8f37750a85d57f70cadfa..5da911ebdf495152c68c52af72d0784f0a8ede54 100644 (file)
@@ -300,7 +300,8 @@ MODULE_ALIAS("RedBoot");
 
 static int __init redboot_parser_init(void)
 {
-       return register_mtd_parser(&redboot_parser);
+       register_mtd_parser(&redboot_parser);
+       return 0;
 }
 
 static void __exit redboot_parser_exit(void)
index 70106607c247289b6328c9ff99321d64ffc49c81..e579f9027c47d82bb1e4d577ddd13128324a0075 100644 (file)
@@ -19,7 +19,7 @@
  * or detected.
  */
 
-#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 struct nand_ecc_test {
        const char *name;
index cde0fd941f0ce6bbb8364f268a141cc1917d8e41..4be9715904616b3f9c1ff2a3bc38d55b58135e58 100644 (file)
@@ -1275,18 +1275,21 @@ static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev)
 {
        struct net_device *netdev = dev_get_drvdata(&vdev->dev);
        struct ibmveth_adapter *adapter;
+       struct iommu_table *tbl;
        unsigned long ret;
        int i;
        int rxqentries = 1;
 
+       tbl = get_iommu_table_base(&vdev->dev);
+
        /* netdev inits at probe time along with the structures we need below*/
        if (netdev == NULL)
-               return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT);
+               return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT, tbl);
 
        adapter = netdev_priv(netdev);
 
        ret = IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
-       ret += IOMMU_PAGE_ALIGN(netdev->mtu);
+       ret += IOMMU_PAGE_ALIGN(netdev->mtu, tbl);
 
        for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
                /* add the size of the active receive buffers */
@@ -1294,11 +1297,12 @@ static unsigned long ibmveth_get_desired_dma(struct vio_dev *vdev)
                        ret +=
                            adapter->rx_buff_pool[i].size *
                            IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i].
-                                   buff_size);
+                                            buff_size, tbl);
                rxqentries += adapter->rx_buff_pool[i].size;
        }
        /* add the size of the receive queue entries */
-       ret += IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry));
+       ret += IOMMU_PAGE_ALIGN(
+               rxqentries * sizeof(struct ibmveth_rx_q_entry), tbl);
 
        return ret;
 }
index 7acab93d5a47effcb69a94062efb33fe16ffda24..22f2f2857b820675950fdd11f34470789cf81ff0 100644 (file)
@@ -41,6 +41,15 @@ config PWM_AB8500
          To compile this driver as a module, choose M here: the module
          will be called pwm-ab8500.
 
+config PWM_ATMEL
+       tristate "Atmel PWM support"
+       depends on ARCH_AT91
+       help
+         Generic PWM framework driver for Atmel SoC.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-atmel.
+
 config PWM_ATMEL_TCB
        tristate "Atmel TC Block PWM support"
        depends on ATMEL_TCLIB && OF
@@ -122,7 +131,8 @@ config PWM_MXS
 
 config PWM_PCA9685
        tristate "NXP PCA9685 PWM driver"
-       depends on OF && REGMAP_I2C
+       depends on OF && I2C
+       select REGMAP_I2C
        help
          Generic PWM framework driver for NXP PCA9685 LED controller.
 
@@ -149,7 +159,7 @@ config PWM_PXA
 
 config PWM_RENESAS_TPU
        tristate "Renesas TPU PWM support"
-       depends on ARCH_SHMOBILE
+       depends on ARCH_SHMOBILE || COMPILE_TEST
        help
          This driver exposes the Timer Pulse Unit (TPU) PWM controller found
          in Renesas chips through the PWM API.
index 4abf337dcd0231759d0450943516b3d45026c02b..d8906ec699761ac573c74839c83e9eb46b9db767 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_PWM)              += core.o
 obj-$(CONFIG_PWM_SYSFS)                += sysfs.o
 obj-$(CONFIG_PWM_AB8500)       += pwm-ab8500.o
+obj-$(CONFIG_PWM_ATMEL)                += pwm-atmel.o
 obj-$(CONFIG_PWM_ATMEL_TCB)    += pwm-atmel-tcb.o
 obj-$(CONFIG_PWM_BFIN)         += pwm-bfin.o
 obj-$(CONFIG_PWM_EP93XX)       += pwm-ep93xx.o
index 2ca95042a0b93bbe80289675f9aafe36e64031cc..a80471399c20314edb69442bac0fe57cf06efec9 100644 (file)
@@ -808,12 +808,12 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
                seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label);
 
                if (test_bit(PWMF_REQUESTED, &pwm->flags))
-                       seq_printf(s, " requested");
+                       seq_puts(s, " requested");
 
                if (test_bit(PWMF_ENABLED, &pwm->flags))
-                       seq_printf(s, " enabled");
+                       seq_puts(s, " enabled");
 
-               seq_printf(s, "\n");
+               seq_puts(s, "\n");
        }
 }
 
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
new file mode 100644 (file)
index 0000000..bf4144a
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Driver for Atmel Pulse Width Modulation Controller
+ *
+ * Copyright (C) 2013 Atmel Corporation
+ *              Bo Shen <voice.shen@atmel.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+/* The following is global registers for PWM controller */
+#define PWM_ENA                        0x04
+#define PWM_DIS                        0x08
+#define PWM_SR                 0x0C
+/* Bit field in SR */
+#define PWM_SR_ALL_CH_ON       0x0F
+
+/* The following register is PWM channel related registers */
+#define PWM_CH_REG_OFFSET      0x200
+#define PWM_CH_REG_SIZE                0x20
+
+#define PWM_CMR                        0x0
+/* Bit field in CMR */
+#define PWM_CMR_CPOL           (1 << 9)
+#define PWM_CMR_UPD_CDTY       (1 << 10)
+
+/* The following registers for PWM v1 */
+#define PWMV1_CDTY             0x04
+#define PWMV1_CPRD             0x08
+#define PWMV1_CUPD             0x10
+
+/* The following registers for PWM v2 */
+#define PWMV2_CDTY             0x04
+#define PWMV2_CDTYUPD          0x08
+#define PWMV2_CPRD             0x0C
+#define PWMV2_CPRDUPD          0x10
+
+/*
+ * Max value for duty and period
+ *
+ * Although the duty and period register is 32 bit,
+ * however only the LSB 16 bits are significant.
+ */
+#define PWM_MAX_DTY            0xFFFF
+#define PWM_MAX_PRD            0xFFFF
+#define PRD_MAX_PRES           10
+
+struct atmel_pwm_chip {
+       struct pwm_chip chip;
+       struct clk *clk;
+       void __iomem *base;
+
+       void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
+                      unsigned long dty, unsigned long prd);
+};
+
+static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
+{
+       return container_of(chip, struct atmel_pwm_chip, chip);
+}
+
+static inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip,
+                                 unsigned long offset)
+{
+       return readl_relaxed(chip->base + offset);
+}
+
+static inline void atmel_pwm_writel(struct atmel_pwm_chip *chip,
+                                   unsigned long offset, unsigned long val)
+{
+       writel_relaxed(val, chip->base + offset);
+}
+
+static inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip,
+                                    unsigned int ch, unsigned long offset)
+{
+       unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
+
+       return readl_relaxed(chip->base + base + offset);
+}
+
+static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
+                                      unsigned int ch, unsigned long offset,
+                                      unsigned long val)
+{
+       unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
+
+       writel_relaxed(val, chip->base + base + offset);
+}
+
+static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                           int duty_ns, int period_ns)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       unsigned long clk_rate, prd, dty;
+       unsigned long long div;
+       unsigned int pres = 0;
+       int ret;
+
+       if (test_bit(PWMF_ENABLED, &pwm->flags) && (period_ns != pwm->period)) {
+               dev_err(chip->dev, "cannot change PWM period while enabled\n");
+               return -EBUSY;
+       }
+
+       clk_rate = clk_get_rate(atmel_pwm->clk);
+       div = clk_rate;
+
+       /* Calculate the period cycles */
+       while (div > PWM_MAX_PRD) {
+               div = clk_rate / (1 << pres);
+               div = div * period_ns;
+               /* 1/Hz = 100000000 ns */
+               do_div(div, 1000000000);
+
+               if (pres++ > PRD_MAX_PRES) {
+                       dev_err(chip->dev, "pres exceeds the maximum value\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* Calculate the duty cycles */
+       prd = div;
+       div *= duty_ns;
+       do_div(div, period_ns);
+       dty = div;
+
+       ret = clk_enable(atmel_pwm->clk);
+       if (ret) {
+               dev_err(chip->dev, "failed to enable PWM clock\n");
+               return ret;
+       }
+
+       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, pres);
+       atmel_pwm->config(chip, pwm, dty, prd);
+
+       clk_disable(atmel_pwm->clk);
+       return ret;
+}
+
+static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
+                               unsigned long dty, unsigned long prd)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       unsigned int val;
+
+       if (test_bit(PWMF_ENABLED, &pwm->flags)) {
+               /*
+                * If the PWM channel is enabled, using the update register,
+                * it needs to set bit 10 of CMR to 0
+                */
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
+
+               val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
+               val &= ~PWM_CMR_UPD_CDTY;
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
+       } else {
+               /*
+                * If the PWM channel is disabled, write value to duty and
+                * period registers directly.
+                */
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
+       }
+}
+
+static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
+                               unsigned long dty, unsigned long prd)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+
+       if (test_bit(PWMF_ENABLED, &pwm->flags)) {
+               /*
+                * If the PWM channel is enabled, using the duty update register
+                * to update the value.
+                */
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTYUPD, dty);
+       } else {
+               /*
+                * If the PWM channel is disabled, write value to duty and
+                * period registers directly.
+                */
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTY, dty);
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CPRD, prd);
+       }
+}
+
+static int atmel_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+                                 enum pwm_polarity polarity)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       u32 val;
+       int ret;
+
+       val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
+
+       if (polarity == PWM_POLARITY_NORMAL)
+               val &= ~PWM_CMR_CPOL;
+       else
+               val |= PWM_CMR_CPOL;
+
+       ret = clk_enable(atmel_pwm->clk);
+       if (ret) {
+               dev_err(chip->dev, "failed to enable PWM clock\n");
+               return ret;
+       }
+
+       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
+
+       clk_disable(atmel_pwm->clk);
+
+       return 0;
+}
+
+static int atmel_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       int ret;
+
+       ret = clk_enable(atmel_pwm->clk);
+       if (ret) {
+               dev_err(chip->dev, "failed to enable PWM clock\n");
+               return ret;
+       }
+
+       atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
+
+       return 0;
+}
+
+static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+
+       atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
+
+       clk_disable(atmel_pwm->clk);
+}
+
+static const struct pwm_ops atmel_pwm_ops = {
+       .config = atmel_pwm_config,
+       .set_polarity = atmel_pwm_set_polarity,
+       .enable = atmel_pwm_enable,
+       .disable = atmel_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
+struct atmel_pwm_data {
+       void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
+                      unsigned long dty, unsigned long prd);
+};
+
+static const struct atmel_pwm_data atmel_pwm_data_v1 = {
+       .config = atmel_pwm_config_v1,
+};
+
+static const struct atmel_pwm_data atmel_pwm_data_v2 = {
+       .config = atmel_pwm_config_v2,
+};
+
+static const struct platform_device_id atmel_pwm_devtypes[] = {
+       {
+               .name = "at91sam9rl-pwm",
+               .driver_data = (kernel_ulong_t)&atmel_pwm_data_v1,
+       }, {
+               .name = "sama5d3-pwm",
+               .driver_data = (kernel_ulong_t)&atmel_pwm_data_v2,
+       }, {
+               /* sentinel */
+       },
+};
+MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes);
+
+static const struct of_device_id atmel_pwm_dt_ids[] = {
+       {
+               .compatible = "atmel,at91sam9rl-pwm",
+               .data = &atmel_pwm_data_v1,
+       }, {
+               .compatible = "atmel,sama5d3-pwm",
+               .data = &atmel_pwm_data_v2,
+       }, {
+               /* sentinel */
+       },
+};
+MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
+
+static inline const struct atmel_pwm_data *
+atmel_pwm_get_driver_data(struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+
+               match = of_match_device(atmel_pwm_dt_ids, &pdev->dev);
+               if (!match)
+                       return NULL;
+
+               return match->data;
+       } else {
+               const struct platform_device_id *id;
+
+               id = platform_get_device_id(pdev);
+
+               return (struct atmel_pwm_data *)id->driver_data;
+       }
+}
+
+static int atmel_pwm_probe(struct platform_device *pdev)
+{
+       const struct atmel_pwm_data *data;
+       struct atmel_pwm_chip *atmel_pwm;
+       struct resource *res;
+       int ret;
+
+       data = atmel_pwm_get_driver_data(pdev);
+       if (!data)
+               return -ENODEV;
+
+       atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL);
+       if (!atmel_pwm)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(atmel_pwm->base))
+               return PTR_ERR(atmel_pwm->base);
+
+       atmel_pwm->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(atmel_pwm->clk))
+               return PTR_ERR(atmel_pwm->clk);
+
+       ret = clk_prepare(atmel_pwm->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare PWM clock\n");
+               return ret;
+       }
+
+       atmel_pwm->chip.dev = &pdev->dev;
+       atmel_pwm->chip.ops = &atmel_pwm_ops;
+
+       if (pdev->dev.of_node) {
+               atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
+               atmel_pwm->chip.of_pwm_n_cells = 3;
+       }
+
+       atmel_pwm->chip.base = -1;
+       atmel_pwm->chip.npwm = 4;
+       atmel_pwm->config = data->config;
+
+       ret = pwmchip_add(&atmel_pwm->chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret);
+               goto unprepare_clk;
+       }
+
+       platform_set_drvdata(pdev, atmel_pwm);
+
+       return ret;
+
+unprepare_clk:
+       clk_unprepare(atmel_pwm->clk);
+       return ret;
+}
+
+static int atmel_pwm_remove(struct platform_device *pdev)
+{
+       struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
+
+       clk_unprepare(atmel_pwm->clk);
+
+       return pwmchip_remove(&atmel_pwm->chip);
+}
+
+static struct platform_driver atmel_pwm_driver = {
+       .driver = {
+               .name = "atmel-pwm",
+               .of_match_table = of_match_ptr(atmel_pwm_dt_ids),
+       },
+       .id_table = atmel_pwm_devtypes,
+       .probe = atmel_pwm_probe,
+       .remove = atmel_pwm_remove,
+};
+module_platform_driver(atmel_pwm_driver);
+
+MODULE_ALIAS("platform:atmel-pwm");
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Atmel PWM driver");
+MODULE_LICENSE("GPL v2");
index 33aa4461e1ce8735d0ddc7a9a1688823a25a22b8..e593e9c45c51c1118f88ae12cc4a546498c77b40 100644 (file)
@@ -224,7 +224,7 @@ static struct platform_driver ep93xx_pwm_driver = {
 module_platform_driver(ep93xx_pwm_driver);
 
 MODULE_DESCRIPTION("Cirrus Logic EP93xx PWM driver");
-MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
-             "H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 MODULE_ALIAS("platform:ep93xx-pwm");
 MODULE_LICENSE("GPL");
index 0a2ede3c3932cf440e1b72d38d199bfac759335b..9c46209e1d02aae6845bfe8d4dad5a153c36b07d 100644 (file)
@@ -165,13 +165,12 @@ static const struct pwm_ops jz4740_pwm_ops = {
 static int jz4740_pwm_probe(struct platform_device *pdev)
 {
        struct jz4740_pwm_chip *jz4740;
-       int ret;
 
        jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL);
        if (!jz4740)
                return -ENOMEM;
 
-       jz4740->clk = clk_get(NULL, "ext");
+       jz4740->clk = devm_clk_get(&pdev->dev, "ext");
        if (IS_ERR(jz4740->clk))
                return PTR_ERR(jz4740->clk);
 
@@ -180,29 +179,16 @@ static int jz4740_pwm_probe(struct platform_device *pdev)
        jz4740->chip.npwm = NUM_PWM;
        jz4740->chip.base = -1;
 
-       ret = pwmchip_add(&jz4740->chip);
-       if (ret < 0) {
-               clk_put(jz4740->clk);
-               return ret;
-       }
-
        platform_set_drvdata(pdev, jz4740);
 
-       return 0;
+       return pwmchip_add(&jz4740->chip);
 }
 
 static int jz4740_pwm_remove(struct platform_device *pdev)
 {
        struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
-       int ret;
-
-       ret = pwmchip_remove(&jz4740->chip);
-       if (ret < 0)
-               return ret;
 
-       clk_put(jz4740->clk);
-
-       return 0;
+       return pwmchip_remove(&jz4740->chip);
 }
 
 static struct platform_driver jz4740_pwm_driver = {
index a4d2164aaf55836cc662784f1e9a6f071e6d8be5..8d995731cef8d13a96f8168161a038c7446e3d5a 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  *
  * 2008-02-13  initial version
- *             eric miao <eric.miao@marvell.com>
+ *             eric miao <eric.miao@marvell.com>
  */
 
 #include <linux/module.h>
@@ -19,6 +19,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
+#include <linux/of_device.h>
 
 #include <asm/div64.h>
 
@@ -124,6 +125,46 @@ static struct pwm_ops pxa_pwm_ops = {
        .owner = THIS_MODULE,
 };
 
+#ifdef CONFIG_OF
+/*
+ * Device tree users must create one device instance for each pwm channel.
+ * Hence we dispense with the HAS_SECONDARY_PWM and "tell" the original driver
+ * code that this is a single channel pxa25x-pwm.  Currently all devices are
+ * supported identically.
+ */
+static struct of_device_id pwm_of_match[] = {
+       { .compatible = "marvell,pxa250-pwm", .data = &pwm_id_table[0]},
+       { .compatible = "marvell,pxa270-pwm", .data = &pwm_id_table[0]},
+       { .compatible = "marvell,pxa168-pwm", .data = &pwm_id_table[0]},
+       { .compatible = "marvell,pxa910-pwm", .data = &pwm_id_table[0]},
+       { }
+};
+MODULE_DEVICE_TABLE(of, pwm_of_match);
+#else
+#define pwm_of_match NULL
+#endif
+
+static const struct platform_device_id *pxa_pwm_get_id_dt(struct device *dev)
+{
+       const struct of_device_id *id = of_match_device(pwm_of_match, dev);
+
+       return id ? id->data : NULL;
+}
+
+static struct pwm_device *
+pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
+{
+       struct pwm_device *pwm;
+
+       pwm = pwm_request_from_chip(pc, 0, NULL);
+       if (IS_ERR(pwm))
+               return pwm;
+
+       pwm_set_period(pwm, args->args[0]);
+
+       return pwm;
+}
+
 static int pwm_probe(struct platform_device *pdev)
 {
        const struct platform_device_id *id = platform_get_device_id(pdev);
@@ -131,6 +172,12 @@ static int pwm_probe(struct platform_device *pdev)
        struct resource *r;
        int ret = 0;
 
+       if (IS_ENABLED(CONFIG_OF) && id == NULL)
+               id = pxa_pwm_get_id_dt(&pdev->dev);
+
+       if (id == NULL)
+               return -EINVAL;
+
        pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
        if (pwm == NULL) {
                dev_err(&pdev->dev, "failed to allocate memory\n");
@@ -146,6 +193,11 @@ static int pwm_probe(struct platform_device *pdev)
        pwm->chip.base = -1;
        pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
 
+       if (IS_ENABLED(CONFIG_OF)) {
+               pwm->chip.of_xlate = pxa_pwm_of_xlate;
+               pwm->chip.of_pwm_n_cells = 1;
+       }
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(pwm->mmio_base))
@@ -176,6 +228,7 @@ static struct platform_driver pwm_driver = {
        .driver         = {
                .name   = "pxa25x-pwm",
                .owner  = THIS_MODULE,
+               .of_match_table = pwm_of_match,
        },
        .probe          = pwm_probe,
        .remove         = pwm_remove,
index 4e5c3d13d4f8d31a0faa65ccd7146c0a28436e3c..032092c7a6ae3d23705ca79d6d1e175b2a524768 100644 (file)
@@ -279,7 +279,6 @@ static int ecap_pwm_remove(struct platform_device *pdev)
        pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ);
        pm_runtime_put_sync(&pdev->dev);
 
-       pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return pwmchip_remove(&pc->chip);
 }
index a4d8f519d965660d1a33e0cdfc7bda02224fbd7d..aee4471424d14a98da494f877909ae5e9f804990 100644 (file)
@@ -360,8 +360,8 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        /* Enable TBCLK before enabling PWM device */
        ret = clk_enable(pc->tbclk);
        if (ret) {
-               pr_err("Failed to enable TBCLK for %s\n",
-                               dev_name(pc->chip.dev));
+               dev_err(chip->dev, "Failed to enable TBCLK for %s\n",
+                       dev_name(pc->chip.dev));
                return ret;
        }
 
index 8c20332d4825810a366e3af07b1d8831617d1951..4bd0c639e16da9d49598f637c5473ae37e419def 100644 (file)
@@ -169,15 +169,7 @@ static struct attribute *pwm_attrs[] = {
        &dev_attr_polarity.attr,
        NULL
 };
-
-static const struct attribute_group pwm_attr_group = {
-       .attrs          = pwm_attrs,
-};
-
-static const struct attribute_group *pwm_attr_groups[] = {
-       &pwm_attr_group,
-       NULL,
-};
+ATTRIBUTE_GROUPS(pwm);
 
 static void pwm_export_release(struct device *child)
 {
@@ -205,7 +197,7 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
        export->child.release = pwm_export_release;
        export->child.parent = parent;
        export->child.devt = MKDEV(0, 0);
-       export->child.groups = pwm_attr_groups;
+       export->child.groups = pwm_groups;
        dev_set_name(&export->child, "pwm%u", pwm->hwpwm);
 
        ret = device_register(&export->child);
index 464dd29d06c07dcbeb1e6ee96a439dbb037a25a9..58141f0651f280b4cc48b510f09455edf8b6cc0a 100644 (file)
@@ -257,6 +257,7 @@ static int __init xpram_setup_sizes(unsigned long pages)
        unsigned long mem_needed;
        unsigned long mem_auto;
        unsigned long long size;
+       char *sizes_end;
        int mem_auto_no;
        int i;
 
@@ -275,8 +276,8 @@ static int __init xpram_setup_sizes(unsigned long pages)
        mem_auto_no = 0;
        for (i = 0; i < xpram_devs; i++) {
                if (sizes[i]) {
-                       size = simple_strtoull(sizes[i], &sizes[i], 0);
-                       switch (sizes[i][0]) {
+                       size = simple_strtoull(sizes[i], &sizes_end, 0);
+                       switch (*sizes_end) {
                        case 'g':
                        case 'G':
                                size <<= 20;
index cb3c4e05a38503c043f35f1f9a70bc8f186e929f..49af8eeb90ea2b3cbd5786bdd075727b20a9a327 100644 (file)
@@ -700,3 +700,8 @@ out:
        free_page((unsigned long) sccb);
        return rc;
 }
+
+bool sclp_has_sprp(void)
+{
+       return !!(sclp_fac84 & 0x2);
+}
index 64c467998a90cbb47e5eed32cee3a0f6dc8a8ae3..0efb27f6f1999f4c85af4587c491b926fc30b251 100644 (file)
@@ -922,8 +922,8 @@ static int ur_set_online(struct ccw_device *cdev)
                goto fail_free_cdev;
        }
 
-       urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
-                                   NULL, "%s", node_id);
+       urd->device = device_create(vmur_class, &cdev->dev,
+                                   urd->char_device->dev, NULL, "%s", node_id);
        if (IS_ERR(urd->device)) {
                rc = PTR_ERR(urd->device);
                TRACE("ur_set_online: device_create rc=%d\n", rc);
index c1441ed282eb911ff67a6363ce5a78f6cbe45199..c7763e482eb235a12d4b48887070ec88154580ff 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
index fc1339cf91ac65d135ef5bf3c14e242462e1453b..7c71e7b4febf96a2cebc62446acee68550116d97 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/major.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/ioport.h>              /* request_region */
 #include <linux/slab.h>
index ddbe5a9e713dfba93218ad886e5df1f49b9fd19c..af15a2fdab5e92e9473b1dbf7184a2f024a2e236 100644 (file)
@@ -19,7 +19,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
index d9f268f237749df06e63f11cec4c19c69326f995..25c738e9ef19cea55a7a48ccbfb4b874789b056b 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/miscdevice.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
-#include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
index b0aae0536d588441aee8409e200ba417a6080b39..b7acafc8509956d583a506b54b7fdab30a723eff 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/mm.h>
 #include <linux/of.h>
index 978db344bda06ec333c2e0c434d1f0c69718ae48..b24aa010f68c5fd156c8abba916be24a61ed4c2f 100644 (file)
@@ -366,7 +366,7 @@ config TRACE_SINK
          "Trace data router for MIPI P1149.7 cJTAG standard".
 
 config PPC_EPAPR_HV_BYTECHAN
-       tristate "ePAPR hypervisor byte channel driver"
+       bool "ePAPR hypervisor byte channel driver"
        depends on PPC
        select EPAPR_PARAVIRT
        help
index db19a38c8c69b0d33dddac2c1fff95f3f79b80f3..ea74460f363862507cbf85af2b2873ae8208ae72 100644 (file)
@@ -77,6 +77,7 @@ struct hvc_iucv_private {
        struct list_head        tty_outqueue;   /* outgoing IUCV messages */
        struct list_head        tty_inqueue;    /* incoming IUCV messages */
        struct device           *dev;           /* device structure */
+       u8                      info_path[16];  /* IUCV path info (dev attr) */
 };
 
 struct iucv_tty_buffer {
@@ -126,7 +127,7 @@ static struct iucv_handler hvc_iucv_handler = {
  * This function returns the struct hvc_iucv_private instance that corresponds
  * to the HVC virtual terminal number specified as parameter @num.
  */
-struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
+static struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
 {
        if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices))
                return NULL;
@@ -772,18 +773,37 @@ static int hvc_iucv_filter_connreq(u8 ipvmid[8])
 static int hvc_iucv_path_pending(struct iucv_path *path,
                                  u8 ipvmid[8], u8 ipuser[16])
 {
-       struct hvc_iucv_private *priv;
+       struct hvc_iucv_private *priv, *tmp;
+       u8 wildcard[9] = "lnxhvc  ";
+       int i, rc, find_unused;
        u8 nuser_data[16];
        u8 vm_user_id[9];
-       int i, rc;
 
+       ASCEBC(wildcard, sizeof(wildcard));
+       find_unused = !memcmp(wildcard, ipuser, 8);
+
+       /* First, check if the pending path request is managed by this
+        * IUCV handler:
+        * - find a disconnected device if ipuser contains the wildcard
+        * - find the device that matches the terminal ID in ipuser
+        */
        priv = NULL;
-       for (i = 0; i < hvc_iucv_devices; i++)
-               if (hvc_iucv_table[i] &&
-                   (0 == memcmp(hvc_iucv_table[i]->srv_name, ipuser, 8))) {
-                       priv = hvc_iucv_table[i];
+       for (i = 0; i < hvc_iucv_devices; i++) {
+               tmp = hvc_iucv_table[i];
+               if (!tmp)
+                       continue;
+
+               if (find_unused) {
+                       spin_lock(&tmp->lock);
+                       if (tmp->iucv_state == IUCV_DISCONN)
+                               priv = tmp;
+                       spin_unlock(&tmp->lock);
+
+               } else if (!memcmp(tmp->srv_name, ipuser, 8))
+                               priv = tmp;
+               if (priv)
                        break;
-               }
+       }
        if (!priv)
                return -ENODEV;
 
@@ -826,6 +846,10 @@ static     int hvc_iucv_path_pending(struct iucv_path *path,
        priv->path = path;
        priv->iucv_state = IUCV_CONNECTED;
 
+       /* store path information */
+       memcpy(priv->info_path, ipvmid, 8);
+       memcpy(priv->info_path + 8, ipuser + 8, 8);
+
        /* flush buffered output data... */
        schedule_delayed_work(&priv->sndbuf_work, 5);
 
@@ -960,6 +984,49 @@ static int hvc_iucv_pm_restore_thaw(struct device *dev)
        return 0;
 }
 
+static ssize_t hvc_iucv_dev_termid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct hvc_iucv_private *priv = dev_get_drvdata(dev);
+       size_t len;
+
+       len = sizeof(priv->srv_name);
+       memcpy(buf, priv->srv_name, len);
+       EBCASC(buf, len);
+       buf[len++] = '\n';
+       return len;
+}
+
+static ssize_t hvc_iucv_dev_state_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct hvc_iucv_private *priv = dev_get_drvdata(dev);
+       return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state);
+}
+
+static ssize_t hvc_iucv_dev_peer_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct hvc_iucv_private *priv = dev_get_drvdata(dev);
+       char vmid[9], ipuser[9];
+
+       memset(vmid, 0, sizeof(vmid));
+       memset(ipuser, 0, sizeof(ipuser));
+
+       spin_lock_bh(&priv->lock);
+       if (priv->iucv_state == IUCV_CONNECTED) {
+               memcpy(vmid, priv->info_path, 8);
+               memcpy(ipuser, priv->info_path + 8, 8);
+       }
+       spin_unlock_bh(&priv->lock);
+       EBCASC(ipuser, 8);
+
+       return sprintf(buf, "%s:%s\n", vmid, ipuser);
+}
+
 
 /* HVC operations */
 static const struct hv_ops hvc_iucv_ops = {
@@ -985,6 +1052,25 @@ static struct device_driver hvc_iucv_driver = {
        .pm   = &hvc_iucv_pm_ops,
 };
 
+/* IUCV HVC device attributes */
+static DEVICE_ATTR(termid, 0640, hvc_iucv_dev_termid_show, NULL);
+static DEVICE_ATTR(state, 0640, hvc_iucv_dev_state_show, NULL);
+static DEVICE_ATTR(peer, 0640, hvc_iucv_dev_peer_show, NULL);
+static struct attribute *hvc_iucv_dev_attrs[] = {
+       &dev_attr_termid.attr,
+       &dev_attr_state.attr,
+       &dev_attr_peer.attr,
+       NULL,
+};
+static struct attribute_group hvc_iucv_dev_attr_group = {
+       .attrs = hvc_iucv_dev_attrs,
+};
+static const struct attribute_group *hvc_iucv_dev_attr_groups[] = {
+       &hvc_iucv_dev_attr_group,
+       NULL,
+};
+
+
 /**
  * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
  * @id:                        hvc_iucv_table index
@@ -1046,6 +1132,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console)
        priv->dev->bus = &iucv_bus;
        priv->dev->parent = iucv_root;
        priv->dev->driver = &hvc_iucv_driver;
+       priv->dev->groups = hvc_iucv_dev_attr_groups;
        priv->dev->release = (void (*)(struct device *)) kfree;
        rc = device_register(priv->dev);
        if (rc) {
index d98e4334897040cd7e6a482fee5a7a913338c4ec..67423805e6d9b0ed761c26958e7cf2df9a31e8f0 100644 (file)
@@ -455,11 +455,11 @@ static void load_code(struct icom_port *icom_port)
        for (index = 0; index < fw->size; index++)
                new_page[index] = fw->data[index];
 
-       release_firmware(fw);
-
        writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
        writel(temp_pci, &icom_port->dram->mac_load_addr);
 
+       release_firmware(fw);
+
        /*Setting the syncReg to 0x80 causes adapter to start downloading
           the personality code into adapter instruction RAM.
           Once code is loaded, it will begin executing and, based on
index 9cbd3acaf37fca13a55ea6b9a854e259790d1758..8fa1134e005165dc2ca33ef43b9d575368602590 100644 (file)
@@ -1508,10 +1508,14 @@ static int pch_uart_verify_port(struct uart_port *port,
                        __func__);
                return -EOPNOTSUPP;
 #endif
-               dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
-               if (!priv->use_dma)
+               if (!priv->use_dma) {
                        pch_request_dma(port);
-               priv->use_dma = 1;
+                       if (priv->chan_rx)
+                               priv->use_dma = 1;
+               }
+               dev_info(priv->port.dev, "PCH UART: %s\n",
+                               priv->use_dma ?
+                               "Use DMA Mode" : "No DMA");
        }
 
        return 0;
index c1af04d46682657794b4893f3eac571a13acc685..9cd706df3b3351cbfa10fa14c254b36724601cc1 100644 (file)
@@ -1209,7 +1209,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
        /* reset the fifos (and setup the uart) */
        s3c24xx_serial_resetport(port, cfg);
-       clk_disable_unprepare(ourport->clk);
        return 0;
 }
 
@@ -1287,6 +1286,13 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
        uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
        platform_set_drvdata(pdev, &ourport->port);
 
+       /*
+        * Deactivate the clock enabled in s3c24xx_serial_init_port here,
+        * so that a potential re-enablement through the pm-callback overlaps
+        * and keeps the clock enabled in this case.
+        */
+       clk_disable_unprepare(ourport->clk);
+
 #ifdef CONFIG_SAMSUNG_CLOCK
        ret = device_create_file(&pdev->dev, &dev_attr_clock_source);
        if (ret < 0)
index bdae7a04af75c48b80f16dfc7faa8ba842cc70c1..a84788ba662c98056bf047996c907ec816a10165 100644 (file)
@@ -81,7 +81,7 @@ static int tce_iommu_enable(struct tce_container *container)
         * enforcing the limit based on the max that the guest can map.
         */
        down_write(&current->mm->mmap_sem);
-       npages = (tbl->it_size << IOMMU_PAGE_SHIFT) >> PAGE_SHIFT;
+       npages = (tbl->it_size << IOMMU_PAGE_SHIFT_4K) >> PAGE_SHIFT;
        locked = current->mm->locked_vm + npages;
        lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
        if (locked > lock_limit && !capable(CAP_IPC_LOCK)) {
@@ -110,7 +110,7 @@ static void tce_iommu_disable(struct tce_container *container)
 
        down_write(&current->mm->mmap_sem);
        current->mm->locked_vm -= (container->tbl->it_size <<
-                       IOMMU_PAGE_SHIFT) >> PAGE_SHIFT;
+                       IOMMU_PAGE_SHIFT_4K) >> PAGE_SHIFT;
        up_write(&current->mm->mmap_sem);
 }
 
@@ -174,8 +174,8 @@ static long tce_iommu_ioctl(void *iommu_data,
                if (info.argsz < minsz)
                        return -EINVAL;
 
-               info.dma32_window_start = tbl->it_offset << IOMMU_PAGE_SHIFT;
-               info.dma32_window_size = tbl->it_size << IOMMU_PAGE_SHIFT;
+               info.dma32_window_start = tbl->it_offset << IOMMU_PAGE_SHIFT_4K;
+               info.dma32_window_size = tbl->it_size << IOMMU_PAGE_SHIFT_4K;
                info.flags = 0;
 
                if (copy_to_user((void __user *)arg, &info, minsz))
@@ -205,8 +205,8 @@ static long tce_iommu_ioctl(void *iommu_data,
                                VFIO_DMA_MAP_FLAG_WRITE))
                        return -EINVAL;
 
-               if ((param.size & ~IOMMU_PAGE_MASK) ||
-                               (param.vaddr & ~IOMMU_PAGE_MASK))
+               if ((param.size & ~IOMMU_PAGE_MASK_4K) ||
+                               (param.vaddr & ~IOMMU_PAGE_MASK_4K))
                        return -EINVAL;
 
                /* iova is checked by the IOMMU API */
@@ -220,17 +220,17 @@ static long tce_iommu_ioctl(void *iommu_data,
                if (ret)
                        return ret;
 
-               for (i = 0; i < (param.size >> IOMMU_PAGE_SHIFT); ++i) {
+               for (i = 0; i < (param.size >> IOMMU_PAGE_SHIFT_4K); ++i) {
                        ret = iommu_put_tce_user_mode(tbl,
-                                       (param.iova >> IOMMU_PAGE_SHIFT) + i,
+                                       (param.iova >> IOMMU_PAGE_SHIFT_4K) + i,
                                        tce);
                        if (ret)
                                break;
-                       tce += IOMMU_PAGE_SIZE;
+                       tce += IOMMU_PAGE_SIZE_4K;
                }
                if (ret)
                        iommu_clear_tces_and_put_pages(tbl,
-                                       param.iova >> IOMMU_PAGE_SHIFT, i);
+                                       param.iova >> IOMMU_PAGE_SHIFT_4K, i);
 
                iommu_flush_tce(tbl);
 
@@ -256,17 +256,17 @@ static long tce_iommu_ioctl(void *iommu_data,
                if (param.flags)
                        return -EINVAL;
 
-               if (param.size & ~IOMMU_PAGE_MASK)
+               if (param.size & ~IOMMU_PAGE_MASK_4K)
                        return -EINVAL;
 
                ret = iommu_tce_clear_param_check(tbl, param.iova, 0,
-                               param.size >> IOMMU_PAGE_SHIFT);
+                               param.size >> IOMMU_PAGE_SHIFT_4K);
                if (ret)
                        return ret;
 
                ret = iommu_clear_tces_and_put_pages(tbl,
-                               param.iova >> IOMMU_PAGE_SHIFT,
-                               param.size >> IOMMU_PAGE_SHIFT);
+                               param.iova >> IOMMU_PAGE_SHIFT_4K,
+                               param.size >> IOMMU_PAGE_SHIFT_4K);
                iommu_flush_tce(tbl);
 
                return ret;
index fb80d68f4d3366e5672498da5bd05f3140e7a753..b75201ff46f6d1bc133a5cae571b90082d11347d 100644 (file)
@@ -241,7 +241,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 
        pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
        if (!pb) {
-               dev_err(&pdev->dev, "no memory for state\n");
                ret = -ENOMEM;
                goto err_alloc;
        }
index 7af425f53beef91a6d21dc86b76e161ff7ed1696..8482f2d1160667ba1255ee5b48434287bc51da65 100644 (file)
@@ -156,7 +156,7 @@ int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid)
                return -EOPNOTSUPP;
        acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
        if (acl) {
-               retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+               retval = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
                if (retval)
                        return retval;
                set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
@@ -200,7 +200,7 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
        if (acl) {
                if (S_ISDIR(mode))
                        *dpacl = posix_acl_dup(acl);
-               retval = posix_acl_create(&acl, GFP_NOFS, &mode);
+               retval = __posix_acl_create(&acl, GFP_NOFS, &mode);
                if (retval < 0)
                        return retval;
                if (retval > 0)
index c229f828eb012ea32a13c306cf1953ae85e3ca2a..7385e54be4b9adbdd8a4c2d0ed3cafd3b516820a 100644 (file)
@@ -68,10 +68,6 @@ source "fs/quota/Kconfig"
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config GENERIC_ACL
-       bool
-       select FS_POSIX_ACL
-
 menu "Caches"
 
 source "fs/fscache/Kconfig"
@@ -119,7 +115,7 @@ config TMPFS_POSIX_ACL
        bool "Tmpfs POSIX Access Control Lists"
        depends on TMPFS
        select TMPFS_XATTR
-       select GENERIC_ACL
+       select FS_POSIX_ACL
        help
          POSIX Access Control Lists (ACLs) support additional access rights
          for users and groups beyond the standard owner/group/world scheme,
index 39a824f44e7c17c807988ca970a2eefbe2113ece..47ac07bb4acc6b44b318776c44e7a6cd7bf79113 100644 (file)
@@ -42,9 +42,8 @@ obj-$(CONFIG_BINFMT_SOM)      += binfmt_som.o
 obj-$(CONFIG_BINFMT_FLAT)      += binfmt_flat.o
 
 obj-$(CONFIG_FS_MBCACHE)       += mbcache.o
-obj-$(CONFIG_FS_POSIX_ACL)     += posix_acl.o xattr_acl.o
+obj-$(CONFIG_FS_POSIX_ACL)     += posix_acl.o
 obj-$(CONFIG_NFS_COMMON)       += nfs_common/
-obj-$(CONFIG_GENERIC_ACL)      += generic_acl.o
 obj-$(CONFIG_COREDUMP)         += coredump.o
 obj-$(CONFIG_SYSCTL)           += drop_caches.o
 
index 45161a832bbc9e4aa2d7f6b72a950273e0af7062..d098731b82ffa794853e66ff0bcb4e05aa59fcbc 100644 (file)
@@ -49,11 +49,6 @@ affs_put_super(struct super_block *sb)
        pr_debug("AFFS: put_super()\n");
 
        cancel_delayed_work_sync(&sbi->sb_work);
-       kfree(sbi->s_prefix);
-       affs_free_bitmap(sb);
-       affs_brelse(sbi->s_root_bh);
-       kfree(sbi);
-       sb->s_fs_info = NULL;
 }
 
 static int
@@ -316,7 +311,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        unsigned long            mount_flags;
        int                      tmp_flags;     /* fix remount prototype... */
        u8                       sig[4];
-       int                      ret = -EINVAL;
+       int                      ret;
 
        save_mount_options(sb, data);
 
@@ -412,17 +407,19 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        if (!silent)
                printk(KERN_ERR "AFFS: No valid root block on device %s\n",
                        sb->s_id);
-       goto out_error;
+       return -EINVAL;
 
        /* N.B. after this point bh must be released */
 got_root:
+       /* Keep super block in cache */
+       sbi->s_root_bh = root_bh;
        root_block = sbi->s_root_block;
 
        /* Find out which kind of FS we have */
        boot_bh = sb_bread(sb, 0);
        if (!boot_bh) {
                printk(KERN_ERR "AFFS: Cannot read boot block\n");
-               goto out_error;
+               return -EINVAL;
        }
        memcpy(sig, boot_bh->b_data, 4);
        brelse(boot_bh);
@@ -471,7 +468,7 @@ got_root:
                default:
                        printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
                                sb->s_id, chksum);
-                       goto out_error;
+                       return -EINVAL;
        }
 
        if (mount_flags & SF_VERBOSE) {
@@ -488,22 +485,17 @@ got_root:
        if (sbi->s_flags & SF_OFS)
                sbi->s_data_blksize -= 24;
 
-       /* Keep super block in cache */
-       sbi->s_root_bh = root_bh;
-       /* N.B. after this point s_root_bh must be released */
-
        tmp_flags = sb->s_flags;
-       if (affs_init_bitmap(sb, &tmp_flags))
-               goto out_error;
+       ret = affs_init_bitmap(sb, &tmp_flags);
+       if (ret)
+               return ret;
        sb->s_flags = tmp_flags;
 
        /* set up enough so that it can read an inode */
 
        root_inode = affs_iget(sb, root_block);
-       if (IS_ERR(root_inode)) {
-               ret = PTR_ERR(root_inode);
-               goto out_error;
-       }
+       if (IS_ERR(root_inode))
+               return PTR_ERR(root_inode);
 
        if (AFFS_SB(sb)->s_flags & SF_INTL)
                sb->s_d_op = &affs_intl_dentry_operations;
@@ -513,22 +505,11 @@ got_root:
        sb->s_root = d_make_root(root_inode);
        if (!sb->s_root) {
                printk(KERN_ERR "AFFS: Get root inode failed\n");
-               goto out_error;
+               return -ENOMEM;
        }
 
        pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
        return 0;
-
-       /*
-        * Begin the cascaded cleanup ...
-        */
-out_error:
-       kfree(sbi->s_bitmap);
-       affs_brelse(root_bh);
-       kfree(sbi->s_prefix);
-       kfree(sbi);
-       sb->s_fs_info = NULL;
-       return ret;
 }
 
 static int
@@ -615,11 +596,23 @@ static struct dentry *affs_mount(struct file_system_type *fs_type,
        return mount_bdev(fs_type, flags, dev_name, data, affs_fill_super);
 }
 
+static void affs_kill_sb(struct super_block *sb)
+{
+       struct affs_sb_info *sbi = AFFS_SB(sb);
+       kill_block_super(sb);
+       if (sbi) {
+               affs_free_bitmap(sb);
+               affs_brelse(sbi->s_root_bh);
+               kfree(sbi->s_prefix);
+               kfree(sbi);
+       }
+}
+
 static struct file_system_type affs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "affs",
        .mount          = affs_mount,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = affs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("affs");
index a306bb6d88d9937badc2a1df1462d3bb0f469829..6621f800812287f6f0fc27cdc7f71a2a32287af2 100644 (file)
@@ -195,7 +195,6 @@ struct afs_cell {
        struct list_head        link;           /* main cell list link */
        struct key              *anonymous_key; /* anonymous user key for this cell */
        struct list_head        proc_link;      /* /proc cell list link */
-       struct proc_dir_entry   *proc_dir;      /* /proc dir for this cell */
 #ifdef CONFIG_AFS_FSCACHE
        struct fscache_cookie   *cache;         /* caching cookie */
 #endif
index 526e4bbbde59e4936f91367101adac8c7373053e..bddc5120ed4089caa19bef3c2420725c63ef7f37 100644 (file)
@@ -41,11 +41,8 @@ static const struct file_operations afs_proc_cells_fops = {
        .write          = afs_proc_cells_write,
        .llseek         = seq_lseek,
        .release        = seq_release,
-       .owner          = THIS_MODULE,
 };
 
-static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
-static int afs_proc_rootcell_release(struct inode *inode, struct file *file);
 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
                                      size_t size, loff_t *_pos);
 static ssize_t afs_proc_rootcell_write(struct file *file,
@@ -53,17 +50,12 @@ static ssize_t afs_proc_rootcell_write(struct file *file,
                                       size_t size, loff_t *_pos);
 
 static const struct file_operations afs_proc_rootcell_fops = {
-       .open           = afs_proc_rootcell_open,
        .read           = afs_proc_rootcell_read,
        .write          = afs_proc_rootcell_write,
        .llseek         = no_llseek,
-       .release        = afs_proc_rootcell_release,
-       .owner          = THIS_MODULE,
 };
 
 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
-static int afs_proc_cell_volumes_release(struct inode *inode,
-                                        struct file *file);
 static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
 static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
                                        loff_t *pos);
@@ -81,14 +73,11 @@ static const struct file_operations afs_proc_cell_volumes_fops = {
        .open           = afs_proc_cell_volumes_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = afs_proc_cell_volumes_release,
-       .owner          = THIS_MODULE,
+       .release        = seq_release,
 };
 
 static int afs_proc_cell_vlservers_open(struct inode *inode,
                                        struct file *file);
-static int afs_proc_cell_vlservers_release(struct inode *inode,
-                                          struct file *file);
 static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
 static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
                                          loff_t *pos);
@@ -106,13 +95,10 @@ static const struct file_operations afs_proc_cell_vlservers_fops = {
        .open           = afs_proc_cell_vlservers_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = afs_proc_cell_vlservers_release,
-       .owner          = THIS_MODULE,
+       .release        = seq_release,
 };
 
 static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
-static int afs_proc_cell_servers_release(struct inode *inode,
-                                        struct file *file);
 static void *afs_proc_cell_servers_start(struct seq_file *p, loff_t *pos);
 static void *afs_proc_cell_servers_next(struct seq_file *p, void *v,
                                        loff_t *pos);
@@ -130,8 +116,7 @@ static const struct file_operations afs_proc_cell_servers_fops = {
        .open           = afs_proc_cell_servers_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = afs_proc_cell_servers_release,
-       .owner          = THIS_MODULE,
+       .release        = seq_release,
 };
 
 /*
@@ -139,29 +124,21 @@ static const struct file_operations afs_proc_cell_servers_fops = {
  */
 int afs_proc_init(void)
 {
-       struct proc_dir_entry *p;
-
        _enter("");
 
        proc_afs = proc_mkdir("fs/afs", NULL);
        if (!proc_afs)
                goto error_dir;
 
-       p = proc_create("cells", 0, proc_afs, &afs_proc_cells_fops);
-       if (!p)
-               goto error_cells;
-
-       p = proc_create("rootcell", 0, proc_afs, &afs_proc_rootcell_fops);
-       if (!p)
-               goto error_rootcell;
+       if (!proc_create("cells", 0, proc_afs, &afs_proc_cells_fops) ||
+           !proc_create("rootcell", 0, proc_afs, &afs_proc_rootcell_fops))
+               goto error_tree;
 
        _leave(" = 0");
        return 0;
 
-error_rootcell:
-       remove_proc_entry("cells", proc_afs);
-error_cells:
-       remove_proc_entry("fs/afs", NULL);
+error_tree:
+       remove_proc_subtree("fs/afs", NULL);
 error_dir:
        _leave(" = -ENOMEM");
        return -ENOMEM;
@@ -172,9 +149,7 @@ error_dir:
  */
 void afs_proc_cleanup(void)
 {
-       remove_proc_entry("rootcell", proc_afs);
-       remove_proc_entry("cells", proc_afs);
-       remove_proc_entry("fs/afs", NULL);
+       remove_proc_subtree("fs/afs", NULL);
 }
 
 /*
@@ -319,19 +294,6 @@ inval:
        goto done;
 }
 
-/*
- * Stubs for /proc/fs/afs/rootcell
- */
-static int afs_proc_rootcell_open(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
-static int afs_proc_rootcell_release(struct inode *inode, struct file *file)
-{
-       return 0;
-}
-
 static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
                                      size_t size, loff_t *_pos)
 {
@@ -387,38 +349,27 @@ nomem:
  */
 int afs_proc_cell_setup(struct afs_cell *cell)
 {
-       struct proc_dir_entry *p;
+       struct proc_dir_entry *dir;
 
        _enter("%p{%s}", cell, cell->name);
 
-       cell->proc_dir = proc_mkdir(cell->name, proc_afs);
-       if (!cell->proc_dir)
+       dir = proc_mkdir(cell->name, proc_afs);
+       if (!dir)
                goto error_dir;
 
-       p = proc_create_data("servers", 0, cell->proc_dir,
-                            &afs_proc_cell_servers_fops, cell);
-       if (!p)
-               goto error_servers;
-
-       p = proc_create_data("vlservers", 0, cell->proc_dir,
-                            &afs_proc_cell_vlservers_fops, cell);
-       if (!p)
-               goto error_vlservers;
-
-       p = proc_create_data("volumes", 0, cell->proc_dir,
-                            &afs_proc_cell_volumes_fops, cell);
-       if (!p)
-               goto error_volumes;
+       if (!proc_create_data("servers", 0, dir,
+                            &afs_proc_cell_servers_fops, cell) ||
+           !proc_create_data("vlservers", 0, dir,
+                            &afs_proc_cell_vlservers_fops, cell) ||
+           !proc_create_data("volumes", 0, dir,
+                            &afs_proc_cell_volumes_fops, cell))
+               goto error_tree;
 
        _leave(" = 0");
        return 0;
 
-error_volumes:
-       remove_proc_entry("vlservers", cell->proc_dir);
-error_vlservers:
-       remove_proc_entry("servers", cell->proc_dir);
-error_servers:
-       remove_proc_entry(cell->name, proc_afs);
+error_tree:
+       remove_proc_subtree(cell->name, proc_afs);
 error_dir:
        _leave(" = -ENOMEM");
        return -ENOMEM;
@@ -431,10 +382,7 @@ void afs_proc_cell_remove(struct afs_cell *cell)
 {
        _enter("");
 
-       remove_proc_entry("volumes", cell->proc_dir);
-       remove_proc_entry("vlservers", cell->proc_dir);
-       remove_proc_entry("servers", cell->proc_dir);
-       remove_proc_entry(cell->name, proc_afs);
+       remove_proc_subtree(cell->name, proc_afs);
 
        _leave("");
 }
@@ -462,14 +410,6 @@ static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- * close the file and release the ref to the cell
- */
-static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file)
-{
-       return seq_release(inode, file);
-}
-
 /*
  * set up the iterator to start reading from the cells list and return the
  * first item
@@ -568,15 +508,6 @@ static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- * close the file and release the ref to the cell
- */
-static int afs_proc_cell_vlservers_release(struct inode *inode,
-                                          struct file *file)
-{
-       return seq_release(inode, file);
-}
-
 /*
  * set up the iterator to start reading from the cells list and return the
  * first item
@@ -672,15 +603,6 @@ static int afs_proc_cell_servers_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-/*
- * close the file and release the ref to the cell
- */
-static int afs_proc_cell_servers_release(struct inode *inode,
-                                        struct file *file)
-{
-       return seq_release(inode, file);
-}
-
 /*
  * set up the iterator to start reading from the cells list and return the
  * first item
index daa15d6ba45077755d2bc859cfffb44f6a82bfd0..845d2d690ce2dc2becddef70041a3e6b69440d62 100644 (file)
@@ -324,8 +324,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
        befs_debug(sb, "---> befs_read_inode() " "inode = %lu", ino);
 
        inode = iget_locked(sb, ino);
-       if (IS_ERR(inode))
-               return inode;
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
                return inode;
 
index 0890c83643e944f69e43a22f4151e381e7503f04..ff9b3995d45394a607a7973458de3383ccd920ff 100644 (file)
@@ -35,13 +35,6 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
        char *value = NULL;
        struct posix_acl *acl;
 
-       if (!IS_POSIXACL(inode))
-               return NULL;
-
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
@@ -76,31 +69,10 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
-               void *value, size_t size, int type)
-{
-       struct posix_acl *acl;
-       int ret = 0;
-
-       if (!IS_POSIXACL(dentry->d_inode))
-               return -EOPNOTSUPP;
-
-       acl = btrfs_get_acl(dentry->d_inode, type);
-
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
-       posix_acl_release(acl);
-
-       return ret;
-}
-
 /*
  * Needs to be called with fs_mutex held
  */
-static int btrfs_set_acl(struct btrfs_trans_handle *trans,
+static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
                         struct inode *inode, struct posix_acl *acl, int type)
 {
        int ret, size = 0;
@@ -158,35 +130,9 @@ out:
        return ret;
 }
 
-static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       int ret;
-       struct posix_acl *acl = NULL;
-
-       if (!inode_owner_or_capable(dentry->d_inode))
-               return -EPERM;
-
-       if (!IS_POSIXACL(dentry->d_inode))
-               return -EOPNOTSUPP;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-
-               if (acl) {
-                       ret = posix_acl_valid(acl);
-                       if (ret)
-                               goto out;
-               }
-       }
-
-       ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type);
-out:
-       posix_acl_release(acl);
-
-       return ret;
+       return __btrfs_set_acl(NULL, inode, acl, type);
 }
 
 /*
@@ -197,83 +143,31 @@ out:
 int btrfs_init_acl(struct btrfs_trans_handle *trans,
                   struct inode *inode, struct inode *dir)
 {
-       struct posix_acl *acl = NULL;
+       struct posix_acl *default_acl, *acl;
        int ret = 0;
 
        /* this happens with subvols */
        if (!dir)
                return 0;
 
-       if (!S_ISLNK(inode->i_mode)) {
-               if (IS_POSIXACL(dir)) {
-                       acl = btrfs_get_acl(dir, ACL_TYPE_DEFAULT);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
+       ret = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (ret)
+               return ret;
 
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
+       if (default_acl) {
+               ret = __btrfs_set_acl(trans, inode, default_acl,
+                                     ACL_TYPE_DEFAULT);
+               posix_acl_release(default_acl);
        }
 
-       if (IS_POSIXACL(dir) && acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       ret = btrfs_set_acl(trans, inode, acl,
-                                           ACL_TYPE_DEFAULT);
-                       if (ret)
-                               goto failed;
-               }
-               ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
-               if (ret < 0)
-                       return ret;
-
-               if (ret > 0) {
-                       /* we need an acl */
-                       ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
-               } else if (ret < 0) {
-                       cache_no_acl(inode);
-               }
-       } else {
-               cache_no_acl(inode);
+       if (acl) {
+               if (!ret)
+                       ret = __btrfs_set_acl(trans, inode, acl,
+                                             ACL_TYPE_ACCESS);
+               posix_acl_release(acl);
        }
-failed:
-       posix_acl_release(acl);
-
-       return ret;
-}
 
-int btrfs_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int ret = 0;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       if (!IS_POSIXACL(inode))
-               return 0;
-
-       acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR_OR_NULL(acl))
-               return PTR_ERR(acl);
-
-       ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (ret)
-               return ret;
-       ret = btrfs_set_acl(NULL, inode, acl, ACL_TYPE_ACCESS);
-       posix_acl_release(acl);
+       if (!default_acl && !acl)
+               cache_no_acl(inode);
        return ret;
 }
-
-const struct xattr_handler btrfs_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .get    = btrfs_xattr_acl_get,
-       .set    = btrfs_xattr_acl_set,
-};
-
-const struct xattr_handler btrfs_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .get    = btrfs_xattr_acl_get,
-       .set    = btrfs_xattr_acl_set,
-};
index 54ab86127f7af49500f6a0bf2bf4b63cd6074c40..7506825211a29d44772cdcd93732875258281daf 100644 (file)
@@ -3899,20 +3899,17 @@ do {                                                                    \
 /* acl.c */
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
+int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int btrfs_init_acl(struct btrfs_trans_handle *trans,
                   struct inode *inode, struct inode *dir);
-int btrfs_acl_chmod(struct inode *inode);
 #else
 #define btrfs_get_acl NULL
+#define btrfs_set_acl NULL
 static inline int btrfs_init_acl(struct btrfs_trans_handle *trans,
                                 struct inode *inode, struct inode *dir)
 {
        return 0;
 }
-static inline int btrfs_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
 #endif
 
 /* relocation.c */
index 471a4f7f4044d4171f823e996ff89b68d237abb0..514b291b135405dd1fbd21f9a8e4edc1b161f5af 100644 (file)
@@ -4468,7 +4468,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
                err = btrfs_dirty_inode(inode);
 
                if (!err && attr->ia_valid & ATTR_MODE)
-                       err = btrfs_acl_chmod(inode);
+                       err = posix_acl_chmod(inode, inode->i_mode);
        }
 
        return err;
@@ -8653,12 +8653,14 @@ static const struct inode_operations btrfs_dir_inode_operations = {
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
 };
 static const struct inode_operations btrfs_dir_ro_inode_operations = {
        .lookup         = btrfs_lookup,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
 };
 
@@ -8728,6 +8730,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
 };
 static const struct inode_operations btrfs_special_inode_operations = {
@@ -8739,6 +8742,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
 };
 static const struct inode_operations btrfs_symlink_inode_operations = {
@@ -8752,7 +8756,6 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
        .getxattr       = btrfs_getxattr,
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
-       .get_acl        = btrfs_get_acl,
        .update_time    = btrfs_update_time,
 };
 
index 21da5762b0b1b33d193f3bd7f664995a43062bd6..ad27dcea319c74558d9f38e4647111bca362654a 100644 (file)
@@ -2686,14 +2686,11 @@ out_unlock:
 #define BTRFS_MAX_DEDUPE_LEN   (16 * 1024 * 1024)
 
 static long btrfs_ioctl_file_extent_same(struct file *file,
-                                        void __user *argp)
+                       struct btrfs_ioctl_same_args __user *argp)
 {
-       struct btrfs_ioctl_same_args tmp;
        struct btrfs_ioctl_same_args *same;
        struct btrfs_ioctl_same_extent_info *info;
-       struct inode *src = file->f_dentry->d_inode;
-       struct file *dst_file = NULL;
-       struct inode *dst;
+       struct inode *src = file_inode(file);
        u64 off;
        u64 len;
        int i;
@@ -2701,6 +2698,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
        unsigned long size;
        u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
        bool is_admin = capable(CAP_SYS_ADMIN);
+       u16 count;
 
        if (!(file->f_mode & FMODE_READ))
                return -EINVAL;
@@ -2709,17 +2707,14 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
        if (ret)
                return ret;
 
-       if (copy_from_user(&tmp,
-                          (struct btrfs_ioctl_same_args __user *)argp,
-                          sizeof(tmp))) {
+       if (get_user(count, &argp->dest_count)) {
                ret = -EFAULT;
                goto out;
        }
 
-       size = sizeof(tmp) +
-               tmp.dest_count * sizeof(struct btrfs_ioctl_same_extent_info);
+       size = offsetof(struct btrfs_ioctl_same_args __user, info[count]);
 
-       same = memdup_user((struct btrfs_ioctl_same_args __user *)argp, size);
+       same = memdup_user(argp, size);
 
        if (IS_ERR(same)) {
                ret = PTR_ERR(same);
@@ -2756,52 +2751,35 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
                goto out;
 
        /* pre-format output fields to sane values */
-       for (i = 0; i < same->dest_count; i++) {
+       for (i = 0; i < count; i++) {
                same->info[i].bytes_deduped = 0ULL;
                same->info[i].status = 0;
        }
 
-       ret = 0;
-       for (i = 0; i < same->dest_count; i++) {
-               info = &same->info[i];
-
-               dst_file = fget(info->fd);
-               if (!dst_file) {
+       for (i = 0, info = same->info; i < count; i++, info++) {
+               struct inode *dst;
+               struct fd dst_file = fdget(info->fd);
+               if (!dst_file.file) {
                        info->status = -EBADF;
-                       goto next;
+                       continue;
                }
+               dst = file_inode(dst_file.file);
 
-               if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
+               if (!(is_admin || (dst_file.file->f_mode & FMODE_WRITE))) {
                        info->status = -EINVAL;
-                       goto next;
-               }
-
-               info->status = -EXDEV;
-               if (file->f_path.mnt != dst_file->f_path.mnt)
-                       goto next;
-
-               dst = dst_file->f_dentry->d_inode;
-               if (src->i_sb != dst->i_sb)
-                       goto next;
-
-               if (S_ISDIR(dst->i_mode)) {
+               } else if (file->f_path.mnt != dst_file.file->f_path.mnt) {
+                       info->status = -EXDEV;
+               } else if (S_ISDIR(dst->i_mode)) {
                        info->status = -EISDIR;
-                       goto next;
-               }
-
-               if (!S_ISREG(dst->i_mode)) {
+               } else if (!S_ISREG(dst->i_mode)) {
                        info->status = -EACCES;
-                       goto next;
+               } else {
+                       info->status = btrfs_extent_same(src, off, len, dst,
+                                                       info->logical_offset);
+                       if (info->status == 0)
+                               info->bytes_deduped += len;
                }
-
-               info->status = btrfs_extent_same(src, off, len, dst,
-                                               info->logical_offset);
-               if (info->status == 0)
-                       info->bytes_deduped += len;
-
-next:
-               if (dst_file)
-                       fput(dst_file);
+               fdput(dst_file);
        }
 
        ret = copy_to_user(argp, same, size);
index 05740b9789e4f97dd92b65f0d000e87dac7558e6..3d1c301c9260299fbecc13eaeade5b6521c3ef26 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/rwsem.h>
 #include <linux/xattr.h>
 #include <linux/security.h>
+#include <linux/posix_acl_xattr.h>
 #include "ctree.h"
 #include "btrfs_inode.h"
 #include "transaction.h"
@@ -313,8 +314,8 @@ err:
  */
 const struct xattr_handler *btrfs_xattr_handlers[] = {
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
-       &btrfs_xattr_acl_access_handler,
-       &btrfs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL,
 };
index b3cc8039134bc4ed59420f51b48ab72c04f2eedc..5049608d13889e1e647cdb447851a6b30319990d 100644 (file)
@@ -21,8 +21,6 @@
 
 #include <linux/xattr.h>
 
-extern const struct xattr_handler btrfs_xattr_acl_access_handler;
-extern const struct xattr_handler btrfs_xattr_acl_default_handler;
 extern const struct xattr_handler *btrfs_xattr_handlers[];
 
 extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
index ac9a2ef5bb9b8f0e8638c0d594e1cd51b5719c91..264e9bf83ff3f2ffe2e040f7032771bdcc23903f 100644 (file)
@@ -25,3 +25,16 @@ config CEPH_FSCACHE
          caching support for Ceph clients using FS-Cache
 
 endif
+
+config CEPH_FS_POSIX_ACL
+       bool "Ceph POSIX Access Control Lists"
+       depends on CEPH_FS
+       select FS_POSIX_ACL
+       help
+         POSIX Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the POSIX ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N
index 32e30106a2f01e8bf62138981e1c4b678a509cfc..85a4230b9bffd5ca311d7b37bfc97e409ccc30ee 100644 (file)
@@ -10,3 +10,4 @@ ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
        debugfs.o
 
 ceph-$(CONFIG_CEPH_FSCACHE) += cache.o
+ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
new file mode 100644 (file)
index 0000000..66d377a
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * linux/fs/ceph/acl.c
+ *
+ * Copyright (C) 2013 Guangliang Zhao, <lucienchao@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * 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 021110-1307, USA.
+ */
+
+#include <linux/ceph/ceph_debug.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/posix_acl.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include "super.h"
+
+static inline void ceph_set_cached_acl(struct inode *inode,
+                                       int type, struct posix_acl *acl)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+
+       spin_lock(&ci->i_ceph_lock);
+       if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0))
+               set_cached_acl(inode, type, acl);
+       spin_unlock(&ci->i_ceph_lock);
+}
+
+static inline struct posix_acl *ceph_get_cached_acl(struct inode *inode,
+                                                       int type)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct posix_acl *acl = ACL_NOT_CACHED;
+
+       spin_lock(&ci->i_ceph_lock);
+       if (__ceph_caps_issued_mask(ci, CEPH_CAP_XATTR_SHARED, 0))
+               acl = get_cached_acl(inode, type);
+       spin_unlock(&ci->i_ceph_lock);
+
+       return acl;
+}
+
+void ceph_forget_all_cached_acls(struct inode *inode)
+{
+       forget_all_cached_acls(inode);
+}
+
+struct posix_acl *ceph_get_acl(struct inode *inode, int type)
+{
+       int size;
+       const char *name;
+       char *value = NULL;
+       struct posix_acl *acl;
+
+       if (!IS_POSIXACL(inode))
+               return NULL;
+
+       acl = ceph_get_cached_acl(inode, type);
+       if (acl != ACL_NOT_CACHED)
+               return acl;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name = POSIX_ACL_XATTR_ACCESS;
+               break;
+       case ACL_TYPE_DEFAULT:
+               name = POSIX_ACL_XATTR_DEFAULT;
+               break;
+       default:
+               BUG();
+       }
+
+       size = __ceph_getxattr(inode, name, "", 0);
+       if (size > 0) {
+               value = kzalloc(size, GFP_NOFS);
+               if (!value)
+                       return ERR_PTR(-ENOMEM);
+               size = __ceph_getxattr(inode, name, value, size);
+       }
+
+       if (size > 0)
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+       else if (size == -ERANGE || size == -ENODATA || size == 0)
+               acl = NULL;
+       else
+               acl = ERR_PTR(-EIO);
+
+       kfree(value);
+
+       if (!IS_ERR(acl))
+               ceph_set_cached_acl(inode, type, acl);
+
+       return acl;
+}
+
+int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+       int ret = 0, size = 0;
+       const char *name = NULL;
+       char *value = NULL;
+       struct iattr newattrs;
+       umode_t new_mode = inode->i_mode, old_mode = inode->i_mode;
+       struct dentry *dentry = d_find_alias(inode);
+
+       if (acl) {
+               ret = posix_acl_valid(acl);
+               if (ret < 0)
+                       goto out;
+       }
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name = POSIX_ACL_XATTR_ACCESS;
+               if (acl) {
+                       ret = posix_acl_equiv_mode(acl, &new_mode);
+                       if (ret < 0)
+                               goto out;
+                       if (ret == 0)
+                               acl = NULL;
+               }
+               break;
+       case ACL_TYPE_DEFAULT:
+               if (!S_ISDIR(inode->i_mode)) {
+                       ret = acl ? -EINVAL : 0;
+                       goto out;
+               }
+               name = POSIX_ACL_XATTR_DEFAULT;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (acl) {
+               size = posix_acl_xattr_size(acl->a_count);
+               value = kmalloc(size, GFP_NOFS);
+               if (!value) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
+               if (ret < 0)
+                       goto out_free;
+       }
+
+       if (new_mode != old_mode) {
+               newattrs.ia_mode = new_mode;
+               newattrs.ia_valid = ATTR_MODE;
+               ret = ceph_setattr(dentry, &newattrs);
+               if (ret)
+                       goto out_free;
+       }
+
+       if (value)
+               ret = __ceph_setxattr(dentry, name, value, size, 0);
+       else
+               ret = __ceph_removexattr(dentry, name);
+
+       if (ret) {
+               if (new_mode != old_mode) {
+                       newattrs.ia_mode = old_mode;
+                       newattrs.ia_valid = ATTR_MODE;
+                       ceph_setattr(dentry, &newattrs);
+               }
+               goto out_free;
+       }
+
+       ceph_set_cached_acl(inode, type, acl);
+
+out_free:
+       kfree(value);
+out:
+       return ret;
+}
+
+int ceph_init_acl(struct dentry *dentry, struct inode *inode, struct inode *dir)
+{
+       struct posix_acl *acl = NULL;
+       int ret = 0;
+
+       if (!S_ISLNK(inode->i_mode)) {
+               if (IS_POSIXACL(dir)) {
+                       acl = ceph_get_acl(dir, ACL_TYPE_DEFAULT);
+                       if (IS_ERR(acl)) {
+                               ret = PTR_ERR(acl);
+                               goto out;
+                       }
+               }
+
+               if (!acl)
+                       inode->i_mode &= ~current_umask();
+       }
+
+       if (IS_POSIXACL(dir) && acl) {
+               if (S_ISDIR(inode->i_mode)) {
+                       ret = ceph_set_acl(inode, acl, ACL_TYPE_DEFAULT);
+                       if (ret)
+                               goto out_release;
+               }
+               ret = __posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
+               if (ret < 0)
+                       goto out;
+               else if (ret > 0)
+                       ret = ceph_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               else
+                       cache_no_acl(inode);
+       } else {
+               cache_no_acl(inode);
+       }
+
+out_release:
+       posix_acl_release(acl);
+out:
+       return ret;
+}
index ec3ba43b9faae73fba6d6352da9515a812ec9f36..b53278c9fd9718509e96d91d3ea1027581714214 100644 (file)
@@ -209,6 +209,7 @@ static int readpage_nounlock(struct file *filp, struct page *page)
                err = 0;
        if (err < 0) {
                SetPageError(page);
+               ceph_fscache_readpage_cancel(inode, page);
                goto out;
        } else {
                if (err < PAGE_CACHE_SIZE) {
@@ -256,6 +257,8 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg)
        for (i = 0; i < num_pages; i++) {
                struct page *page = osd_data->pages[i];
 
+               if (rc < 0)
+                       goto unlock;
                if (bytes < (int)PAGE_CACHE_SIZE) {
                        /* zero (remainder of) page */
                        int s = bytes < 0 ? 0 : bytes;
@@ -266,6 +269,7 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg)
                flush_dcache_page(page);
                SetPageUptodate(page);
                ceph_readpage_to_fscache(inode, page);
+unlock:
                unlock_page(page);
                page_cache_release(page);
                bytes -= PAGE_CACHE_SIZE;
@@ -1207,6 +1211,41 @@ const struct address_space_operations ceph_aops = {
 /*
  * vm ops
  */
+static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct inode *inode = file_inode(vma->vm_file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *fi = vma->vm_file->private_data;
+       loff_t off = vmf->pgoff << PAGE_CACHE_SHIFT;
+       int want, got, ret;
+
+       dout("filemap_fault %p %llx.%llx %llu~%zd trying to get caps\n",
+            inode, ceph_vinop(inode), off, (size_t)PAGE_CACHE_SIZE);
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
+       else
+               want = CEPH_CAP_FILE_CACHE;
+       while (1) {
+               got = 0;
+               ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1);
+               if (ret == 0)
+                       break;
+               if (ret != -ERESTARTSYS) {
+                       WARN_ON(1);
+                       return VM_FAULT_SIGBUS;
+               }
+       }
+       dout("filemap_fault %p %llu~%zd got cap refs on %s\n",
+            inode, off, (size_t)PAGE_CACHE_SIZE, ceph_cap_string(got));
+
+       ret = filemap_fault(vma, vmf);
+
+       dout("filemap_fault %p %llu~%zd dropping cap refs on %s ret %d\n",
+            inode, off, (size_t)PAGE_CACHE_SIZE, ceph_cap_string(got), ret);
+       ceph_put_cap_refs(ci, got);
+
+       return ret;
+}
 
 /*
  * Reuse write_begin here for simplicity.
@@ -1214,23 +1253,41 @@ const struct address_space_operations ceph_aops = {
 static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct inode *inode = file_inode(vma->vm_file);
-       struct page *page = vmf->page;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_file_info *fi = vma->vm_file->private_data;
        struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+       struct page *page = vmf->page;
        loff_t off = page_offset(page);
-       loff_t size, len;
-       int ret;
-
-       /* Update time before taking page lock */
-       file_update_time(vma->vm_file);
+       loff_t size = i_size_read(inode);
+       size_t len;
+       int want, got, ret;
 
-       size = i_size_read(inode);
        if (off + PAGE_CACHE_SIZE <= size)
                len = PAGE_CACHE_SIZE;
        else
                len = size & ~PAGE_CACHE_MASK;
 
-       dout("page_mkwrite %p %llu~%llu page %p idx %lu\n", inode,
-            off, len, page, page->index);
+       dout("page_mkwrite %p %llx.%llx %llu~%zd getting caps i_size %llu\n",
+            inode, ceph_vinop(inode), off, len, size);
+       if (fi->fmode & CEPH_FILE_MODE_LAZY)
+               want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
+       else
+               want = CEPH_CAP_FILE_BUFFER;
+       while (1) {
+               got = 0;
+               ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, off + len);
+               if (ret == 0)
+                       break;
+               if (ret != -ERESTARTSYS) {
+                       WARN_ON(1);
+                       return VM_FAULT_SIGBUS;
+               }
+       }
+       dout("page_mkwrite %p %llu~%zd got cap refs on %s\n",
+            inode, off, len, ceph_cap_string(got));
+
+       /* Update time before taking page lock */
+       file_update_time(vma->vm_file);
 
        lock_page(page);
 
@@ -1252,14 +1309,26 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
                        ret = VM_FAULT_SIGBUS;
        }
 out:
-       dout("page_mkwrite %p %llu~%llu = %d\n", inode, off, len, ret);
-       if (ret != VM_FAULT_LOCKED)
+       if (ret != VM_FAULT_LOCKED) {
                unlock_page(page);
+       } else {
+               int dirty;
+               spin_lock(&ci->i_ceph_lock);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               spin_unlock(&ci->i_ceph_lock);
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
+       }
+
+       dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %d\n",
+            inode, off, len, ceph_cap_string(got), ret);
+       ceph_put_cap_refs(ci, got);
+
        return ret;
 }
 
 static struct vm_operations_struct ceph_vmops = {
-       .fault          = filemap_fault,
+       .fault          = ceph_filemap_fault,
        .page_mkwrite   = ceph_page_mkwrite,
        .remap_pages    = generic_file_remap_pages,
 };
index ba949408a336e663e018e5a2b9d0da040d9346f7..da95f61b7a09e850e6d28de88aceb4493d7157b8 100644 (file)
@@ -67,6 +67,14 @@ static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp)
        return fscache_maybe_release_page(ci->fscache, page, gfp);
 }
 
+static inline void ceph_fscache_readpage_cancel(struct inode *inode,
+                                               struct page *page)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       if (fscache_cookie_valid(ci->fscache) && PageFsCache(page))
+               __fscache_uncache_page(ci->fscache, page);
+}
+
 static inline void ceph_fscache_readpages_cancel(struct inode *inode,
                                                 struct list_head *pages)
 {
@@ -145,6 +153,11 @@ static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp)
        return 1;
 }
 
+static inline void ceph_fscache_readpage_cancel(struct inode *inode,
+                                               struct page *page)
+{
+}
+
 static inline void ceph_fscache_readpages_cancel(struct inode *inode,
                                                 struct list_head *pages)
 {
index 3c0a4bd7499645ca8bf90fd1a6ba16f6831c164c..17543383545c162f58425fbc8629a99f1c5a717e 100644 (file)
@@ -555,21 +555,34 @@ retry:
                cap->ci = ci;
                __insert_cap_node(ci, cap);
 
-               /* clear out old exporting info?  (i.e. on cap import) */
-               if (ci->i_cap_exporting_mds == mds) {
-                       ci->i_cap_exporting_issued = 0;
-                       ci->i_cap_exporting_mseq = 0;
-                       ci->i_cap_exporting_mds = -1;
-               }
-
                /* add to session cap list */
                cap->session = session;
                spin_lock(&session->s_cap_lock);
                list_add_tail(&cap->session_caps, &session->s_caps);
                session->s_nr_caps++;
                spin_unlock(&session->s_cap_lock);
-       } else if (new_cap)
-               ceph_put_cap(mdsc, new_cap);
+       } else {
+               if (new_cap)
+                       ceph_put_cap(mdsc, new_cap);
+
+               /*
+                * auth mds of the inode changed. we received the cap export
+                * message, but still haven't received the cap import message.
+                * handle_cap_export() updated the new auth MDS' cap.
+                *
+                * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing
+                * a message that was send before the cap import message. So
+                * don't remove caps.
+                */
+               if (ceph_seq_cmp(seq, cap->seq) <= 0) {
+                       WARN_ON(cap != ci->i_auth_cap);
+                       WARN_ON(cap->cap_id != cap_id);
+                       seq = cap->seq;
+                       mseq = cap->mseq;
+                       issued |= cap->issued;
+                       flags |= CEPH_CAP_FLAG_AUTH;
+               }
+       }
 
        if (!ci->i_snap_realm) {
                /*
@@ -611,15 +624,9 @@ retry:
                if (ci->i_auth_cap == NULL ||
                    ceph_seq_cmp(ci->i_auth_cap->mseq, mseq) < 0)
                        ci->i_auth_cap = cap;
-       } else if (ci->i_auth_cap == cap) {
-               ci->i_auth_cap = NULL;
-               spin_lock(&mdsc->cap_dirty_lock);
-               if (!list_empty(&ci->i_dirty_item)) {
-                       dout(" moving %p to cap_dirty_migrating\n", inode);
-                       list_move(&ci->i_dirty_item,
-                                 &mdsc->cap_dirty_migrating);
-               }
-               spin_unlock(&mdsc->cap_dirty_lock);
+               ci->i_cap_exporting_issued = 0;
+       } else {
+               WARN_ON(ci->i_auth_cap == cap);
        }
 
        dout("add_cap inode %p (%llx.%llx) cap %p %s now %s seq %d mds%d\n",
@@ -628,7 +635,7 @@ retry:
        cap->cap_id = cap_id;
        cap->issued = issued;
        cap->implemented |= issued;
-       if (mseq > cap->mseq)
+       if (ceph_seq_cmp(mseq, cap->mseq) > 0)
                cap->mds_wanted = wanted;
        else
                cap->mds_wanted |= wanted;
@@ -816,7 +823,7 @@ int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
 
        for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
                cap = rb_entry(p, struct ceph_cap, ci_node);
-               if (cap != ocap && __cap_is_valid(cap) &&
+               if (cap != ocap &&
                    (cap->implemented & ~cap->issued & mask))
                        return 1;
        }
@@ -888,7 +895,19 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci)
  */
 static int __ceph_is_any_caps(struct ceph_inode_info *ci)
 {
-       return !RB_EMPTY_ROOT(&ci->i_caps) || ci->i_cap_exporting_mds >= 0;
+       return !RB_EMPTY_ROOT(&ci->i_caps) || ci->i_cap_exporting_issued;
+}
+
+int ceph_is_any_caps(struct inode *inode)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       int ret;
+
+       spin_lock(&ci->i_ceph_lock);
+       ret = __ceph_is_any_caps(ci);
+       spin_unlock(&ci->i_ceph_lock);
+
+       return ret;
 }
 
 /*
@@ -1383,13 +1402,10 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
                                ci->i_snap_realm->cached_context);
                dout(" inode %p now dirty snapc %p auth cap %p\n",
                     &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap);
+               WARN_ON(!ci->i_auth_cap);
                BUG_ON(!list_empty(&ci->i_dirty_item));
                spin_lock(&mdsc->cap_dirty_lock);
-               if (ci->i_auth_cap)
-                       list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
-               else
-                       list_add(&ci->i_dirty_item,
-                                &mdsc->cap_dirty_migrating);
+               list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
                spin_unlock(&mdsc->cap_dirty_lock);
                if (ci->i_flushing_caps == 0) {
                        ihold(inode);
@@ -1735,13 +1751,12 @@ ack:
 /*
  * Try to flush dirty caps back to the auth mds.
  */
-static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session,
-                         unsigned *flush_tid)
+static int try_flush_caps(struct inode *inode, unsigned *flush_tid)
 {
        struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       int unlock_session = session ? 0 : 1;
        int flushing = 0;
+       struct ceph_mds_session *session = NULL;
 
 retry:
        spin_lock(&ci->i_ceph_lock);
@@ -1755,13 +1770,14 @@ retry:
                int want = __ceph_caps_wanted(ci);
                int delayed;
 
-               if (!session) {
+               if (!session || session != cap->session) {
                        spin_unlock(&ci->i_ceph_lock);
+                       if (session)
+                               mutex_unlock(&session->s_mutex);
                        session = cap->session;
                        mutex_lock(&session->s_mutex);
                        goto retry;
                }
-               BUG_ON(session != cap->session);
                if (cap->session->s_state < CEPH_MDS_SESSION_OPEN)
                        goto out;
 
@@ -1780,7 +1796,7 @@ retry:
 out:
        spin_unlock(&ci->i_ceph_lock);
 out_unlocked:
-       if (session && unlock_session)
+       if (session)
                mutex_unlock(&session->s_mutex);
        return flushing;
 }
@@ -1865,7 +1881,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                return ret;
        mutex_lock(&inode->i_mutex);
 
-       dirty = try_flush_caps(inode, NULL, &flush_tid);
+       dirty = try_flush_caps(inode, &flush_tid);
        dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
 
        /*
@@ -1900,7 +1916,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
 
        dout("write_inode %p wait=%d\n", inode, wait);
        if (wait) {
-               dirty = try_flush_caps(inode, NULL, &flush_tid);
+               dirty = try_flush_caps(inode, &flush_tid);
                if (dirty)
                        err = wait_event_interruptible(ci->i_cap_wq,
                                       caps_are_flushed(inode, flush_tid));
@@ -2350,11 +2366,11 @@ static void invalidate_aliases(struct inode *inode)
        d_prune_aliases(inode);
        /*
         * For non-directory inode, d_find_alias() only returns
-        * connected dentry. After calling d_invalidate(), the
-        * dentry become disconnected.
+        * hashed dentry. After calling d_invalidate(), the
+        * dentry becomes unhashed.
         *
         * For directory inode, d_find_alias() can return
-        * disconnected dentry. But directory inode should have
+        * unhashed dentry. But directory inode should have
         * one alias at most.
         */
        while ((dn = d_find_alias(inode))) {
@@ -2408,6 +2424,22 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
                inode->i_size);
 
+
+       /*
+        * auth mds of the inode changed. we received the cap export message,
+        * but still haven't received the cap import message. handle_cap_export
+        * updated the new auth MDS' cap.
+        *
+        * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message
+        * that was sent before the cap import message. So don't remove caps.
+        */
+       if (ceph_seq_cmp(seq, cap->seq) <= 0) {
+               WARN_ON(cap != ci->i_auth_cap);
+               WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id));
+               seq = cap->seq;
+               newcaps |= cap->issued;
+       }
+
        /*
         * If CACHE is being revoked, and we have no dirty buffers,
         * try to invalidate (once).  (If there are dirty buffers, we
@@ -2434,6 +2466,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
        issued |= implemented | __ceph_caps_dirty(ci);
 
        cap->cap_gen = session->s_cap_gen;
+       cap->seq = seq;
 
        __check_cap_issue(ci, cap, newcaps);
 
@@ -2464,6 +2497,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                                ceph_buffer_put(ci->i_xattrs.blob);
                        ci->i_xattrs.blob = ceph_buffer_get(xattr_buf);
                        ci->i_xattrs.version = version;
+                       ceph_forget_all_cached_acls(inode);
                }
        }
 
@@ -2483,6 +2517,10 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                            le32_to_cpu(grant->time_warp_seq), &ctime, &mtime,
                            &atime);
 
+
+       /* file layout may have changed */
+       ci->i_layout = grant->layout;
+
        /* max size increase? */
        if (ci->i_auth_cap == cap && max_size != ci->i_max_size) {
                dout("max_size %lld -> %llu\n", ci->i_max_size, max_size);
@@ -2511,11 +2549,6 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant,
                        check_caps = 1;
        }
 
-       cap->seq = seq;
-
-       /* file layout may have changed */
-       ci->i_layout = grant->layout;
-
        /* revocation, grant, or no-op? */
        if (cap->issued & ~newcaps) {
                int revoking = cap->issued & ~newcaps;
@@ -2741,65 +2774,114 @@ static void handle_cap_trunc(struct inode *inode,
  * caller holds s_mutex
  */
 static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
-                             struct ceph_mds_session *session,
-                             int *open_target_sessions)
+                             struct ceph_mds_cap_peer *ph,
+                             struct ceph_mds_session *session)
 {
        struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+       struct ceph_mds_session *tsession = NULL;
+       struct ceph_cap *cap, *tcap;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       int mds = session->s_mds;
+       u64 t_cap_id;
        unsigned mseq = le32_to_cpu(ex->migrate_seq);
-       struct ceph_cap *cap = NULL, *t;
-       struct rb_node *p;
-       int remember = 1;
+       unsigned t_seq, t_mseq;
+       int target, issued;
+       int mds = session->s_mds;
 
-       dout("handle_cap_export inode %p ci %p mds%d mseq %d\n",
-            inode, ci, mds, mseq);
+       if (ph) {
+               t_cap_id = le64_to_cpu(ph->cap_id);
+               t_seq = le32_to_cpu(ph->seq);
+               t_mseq = le32_to_cpu(ph->mseq);
+               target = le32_to_cpu(ph->mds);
+       } else {
+               t_cap_id = t_seq = t_mseq = 0;
+               target = -1;
+       }
 
+       dout("handle_cap_export inode %p ci %p mds%d mseq %d target %d\n",
+            inode, ci, mds, mseq, target);
+retry:
        spin_lock(&ci->i_ceph_lock);
+       cap = __get_cap_for_mds(ci, mds);
+       if (!cap)
+               goto out_unlock;
 
-       /* make sure we haven't seen a higher mseq */
-       for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) {
-               t = rb_entry(p, struct ceph_cap, ci_node);
-               if (ceph_seq_cmp(t->mseq, mseq) > 0) {
-                       dout(" higher mseq on cap from mds%d\n",
-                            t->session->s_mds);
-                       remember = 0;
-               }
-               if (t->session->s_mds == mds)
-                       cap = t;
+       if (target < 0) {
+               __ceph_remove_cap(cap, false);
+               goto out_unlock;
        }
 
-       if (cap) {
-               if (remember) {
-                       /* make note */
-                       ci->i_cap_exporting_mds = mds;
-                       ci->i_cap_exporting_mseq = mseq;
-                       ci->i_cap_exporting_issued = cap->issued;
-
-                       /*
-                        * make sure we have open sessions with all possible
-                        * export targets, so that we get the matching IMPORT
-                        */
-                       *open_target_sessions = 1;
+       /*
+        * now we know we haven't received the cap import message yet
+        * because the exported cap still exist.
+        */
 
-                       /*
-                        * we can't flush dirty caps that we've seen the
-                        * EXPORT but no IMPORT for
-                        */
-                       spin_lock(&mdsc->cap_dirty_lock);
-                       if (!list_empty(&ci->i_dirty_item)) {
-                               dout(" moving %p to cap_dirty_migrating\n",
-                                    inode);
-                               list_move(&ci->i_dirty_item,
-                                         &mdsc->cap_dirty_migrating);
+       issued = cap->issued;
+       WARN_ON(issued != cap->implemented);
+
+       tcap = __get_cap_for_mds(ci, target);
+       if (tcap) {
+               /* already have caps from the target */
+               if (tcap->cap_id != t_cap_id ||
+                   ceph_seq_cmp(tcap->seq, t_seq) < 0) {
+                       dout(" updating import cap %p mds%d\n", tcap, target);
+                       tcap->cap_id = t_cap_id;
+                       tcap->seq = t_seq - 1;
+                       tcap->issue_seq = t_seq - 1;
+                       tcap->mseq = t_mseq;
+                       tcap->issued |= issued;
+                       tcap->implemented |= issued;
+                       if (cap == ci->i_auth_cap)
+                               ci->i_auth_cap = tcap;
+                       if (ci->i_flushing_caps && ci->i_auth_cap == tcap) {
+                               spin_lock(&mdsc->cap_dirty_lock);
+                               list_move_tail(&ci->i_flushing_item,
+                                              &tcap->session->s_cap_flushing);
+                               spin_unlock(&mdsc->cap_dirty_lock);
                        }
-                       spin_unlock(&mdsc->cap_dirty_lock);
                }
                __ceph_remove_cap(cap, false);
+               goto out_unlock;
        }
-       /* else, we already released it */
 
+       if (tsession) {
+               int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
+               spin_unlock(&ci->i_ceph_lock);
+               /* add placeholder for the export tagert */
+               ceph_add_cap(inode, tsession, t_cap_id, -1, issued, 0,
+                            t_seq - 1, t_mseq, (u64)-1, flag, NULL);
+               goto retry;
+       }
+
+       spin_unlock(&ci->i_ceph_lock);
+       mutex_unlock(&session->s_mutex);
+
+       /* open target session */
+       tsession = ceph_mdsc_open_export_target_session(mdsc, target);
+       if (!IS_ERR(tsession)) {
+               if (mds > target) {
+                       mutex_lock(&session->s_mutex);
+                       mutex_lock_nested(&tsession->s_mutex,
+                                         SINGLE_DEPTH_NESTING);
+               } else {
+                       mutex_lock(&tsession->s_mutex);
+                       mutex_lock_nested(&session->s_mutex,
+                                         SINGLE_DEPTH_NESTING);
+               }
+               ceph_add_cap_releases(mdsc, tsession);
+       } else {
+               WARN_ON(1);
+               tsession = NULL;
+               target = -1;
+       }
+       goto retry;
+
+out_unlock:
        spin_unlock(&ci->i_ceph_lock);
+       mutex_unlock(&session->s_mutex);
+       if (tsession) {
+               mutex_unlock(&tsession->s_mutex);
+               ceph_put_mds_session(tsession);
+       }
 }
 
 /*
@@ -2810,10 +2892,12 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
  */
 static void handle_cap_import(struct ceph_mds_client *mdsc,
                              struct inode *inode, struct ceph_mds_caps *im,
+                             struct ceph_mds_cap_peer *ph,
                              struct ceph_mds_session *session,
                              void *snaptrace, int snaptrace_len)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_cap *cap;
        int mds = session->s_mds;
        unsigned issued = le32_to_cpu(im->caps);
        unsigned wanted = le32_to_cpu(im->wanted);
@@ -2821,28 +2905,44 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
        unsigned mseq = le32_to_cpu(im->migrate_seq);
        u64 realmino = le64_to_cpu(im->realm);
        u64 cap_id = le64_to_cpu(im->cap_id);
+       u64 p_cap_id;
+       int peer;
 
-       if (ci->i_cap_exporting_mds >= 0 &&
-           ceph_seq_cmp(ci->i_cap_exporting_mseq, mseq) < 0) {
-               dout("handle_cap_import inode %p ci %p mds%d mseq %d"
-                    " - cleared exporting from mds%d\n",
-                    inode, ci, mds, mseq,
-                    ci->i_cap_exporting_mds);
-               ci->i_cap_exporting_issued = 0;
-               ci->i_cap_exporting_mseq = 0;
-               ci->i_cap_exporting_mds = -1;
+       if (ph) {
+               p_cap_id = le64_to_cpu(ph->cap_id);
+               peer = le32_to_cpu(ph->mds);
+       } else {
+               p_cap_id = 0;
+               peer = -1;
+       }
 
-               spin_lock(&mdsc->cap_dirty_lock);
-               if (!list_empty(&ci->i_dirty_item)) {
-                       dout(" moving %p back to cap_dirty\n", inode);
-                       list_move(&ci->i_dirty_item, &mdsc->cap_dirty);
+       dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n",
+            inode, ci, mds, mseq, peer);
+
+       spin_lock(&ci->i_ceph_lock);
+       cap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
+       if (cap && cap->cap_id == p_cap_id) {
+               dout(" remove export cap %p mds%d flags %d\n",
+                    cap, peer, ph->flags);
+               if ((ph->flags & CEPH_CAP_FLAG_AUTH) &&
+                   (cap->seq != le32_to_cpu(ph->seq) ||
+                    cap->mseq != le32_to_cpu(ph->mseq))) {
+                       pr_err("handle_cap_import: mismatched seq/mseq: "
+                              "ino (%llx.%llx) mds%d seq %d mseq %d "
+                              "importer mds%d has peer seq %d mseq %d\n",
+                              ceph_vinop(inode), peer, cap->seq,
+                              cap->mseq, mds, le32_to_cpu(ph->seq),
+                              le32_to_cpu(ph->mseq));
                }
-               spin_unlock(&mdsc->cap_dirty_lock);
-       } else {
-               dout("handle_cap_import inode %p ci %p mds%d mseq %d\n",
-                    inode, ci, mds, mseq);
+               ci->i_cap_exporting_issued = cap->issued;
+               __ceph_remove_cap(cap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
        }
 
+       /* make sure we re-request max_size, if necessary */
+       ci->i_wanted_max_size = 0;
+       ci->i_requested_max_size = 0;
+       spin_unlock(&ci->i_ceph_lock);
+
        down_write(&mdsc->snap_rwsem);
        ceph_update_snap_trace(mdsc, snaptrace, snaptrace+snaptrace_len,
                               false);
@@ -2853,11 +2953,6 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
        kick_flushing_inode_caps(mdsc, session, inode);
        up_read(&mdsc->snap_rwsem);
 
-       /* make sure we re-request max_size, if necessary */
-       spin_lock(&ci->i_ceph_lock);
-       ci->i_wanted_max_size = 0;  /* reset */
-       ci->i_requested_max_size = 0;
-       spin_unlock(&ci->i_ceph_lock);
 }
 
 /*
@@ -2875,6 +2970,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        struct ceph_inode_info *ci;
        struct ceph_cap *cap;
        struct ceph_mds_caps *h;
+       struct ceph_mds_cap_peer *peer = NULL;
        int mds = session->s_mds;
        int op;
        u32 seq, mseq;
@@ -2885,12 +2981,13 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        void *snaptrace;
        size_t snaptrace_len;
        void *flock;
+       void *end;
        u32 flock_len;
-       int open_target_sessions = 0;
 
        dout("handle_caps from mds%d\n", mds);
 
        /* decode */
+       end = msg->front.iov_base + msg->front.iov_len;
        tid = le64_to_cpu(msg->hdr.tid);
        if (msg->front.iov_len < sizeof(*h))
                goto bad;
@@ -2908,17 +3005,28 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        snaptrace_len = le32_to_cpu(h->snap_trace_len);
 
        if (le16_to_cpu(msg->hdr.version) >= 2) {
-               void *p, *end;
-
-               p = snaptrace + snaptrace_len;
-               end = msg->front.iov_base + msg->front.iov_len;
+               void *p = snaptrace + snaptrace_len;
                ceph_decode_32_safe(&p, end, flock_len, bad);
+               if (p + flock_len > end)
+                       goto bad;
                flock = p;
        } else {
                flock = NULL;
                flock_len = 0;
        }
 
+       if (le16_to_cpu(msg->hdr.version) >= 3) {
+               if (op == CEPH_CAP_OP_IMPORT) {
+                       void *p = flock + flock_len;
+                       if (p + sizeof(*peer) > end)
+                               goto bad;
+                       peer = p;
+               } else if (op == CEPH_CAP_OP_EXPORT) {
+                       /* recorded in unused fields */
+                       peer = (void *)&h->size;
+               }
+       }
+
        mutex_lock(&session->s_mutex);
        session->s_seq++;
        dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq,
@@ -2951,11 +3059,11 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                goto done;
 
        case CEPH_CAP_OP_EXPORT:
-               handle_cap_export(inode, h, session, &open_target_sessions);
-               goto done;
+               handle_cap_export(inode, h, peer, session);
+               goto done_unlocked;
 
        case CEPH_CAP_OP_IMPORT:
-               handle_cap_import(mdsc, inode, h, session,
+               handle_cap_import(mdsc, inode, h, peer, session,
                                  snaptrace, snaptrace_len);
        }
 
@@ -3007,8 +3115,6 @@ done:
 done_unlocked:
        if (inode)
                iput(inode);
-       if (open_target_sessions)
-               ceph_mdsc_open_export_target_sessions(mdsc, session);
        return;
 
 bad:
index 2a0bcaeb189acd18b124aff8d54619667fd97bf2..6da4df84ba300824a8a6afdea9f2a20121600765 100644 (file)
@@ -693,6 +693,10 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
        if (!err && !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
+
+       if (!err)
+               err = ceph_init_acl(dentry, dentry->d_inode, dir);
+
        if (err)
                d_drop(dentry);
        return err;
@@ -1037,14 +1041,19 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                valid = 1;
        } else if (dentry_lease_is_valid(dentry) ||
                   dir_lease_is_valid(dir, dentry)) {
-               valid = 1;
+               if (dentry->d_inode)
+                       valid = ceph_is_any_caps(dentry->d_inode);
+               else
+                       valid = 1;
        }
 
        dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
-       if (valid)
+       if (valid) {
                ceph_dentry_lru_touch(dentry);
-       else
+       } else {
+               ceph_dir_clear_complete(dir);
                d_drop(dentry);
+       }
        iput(dir);
        return valid;
 }
@@ -1293,6 +1302,8 @@ const struct inode_operations ceph_dir_iops = {
        .getxattr = ceph_getxattr,
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
+       .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
        .mknod = ceph_mknod,
        .symlink = ceph_symlink,
        .mkdir = ceph_mkdir,
index 3de89829e2a162ab6bce2a58296b25aef9235c43..dfd2ce3419f812f71769406023d0ff33cea3a35b 100644 (file)
@@ -408,51 +408,92 @@ more:
  *
  * If the read spans object boundary, just do multiple reads.
  */
-static ssize_t ceph_sync_read(struct file *file, char __user *data,
-                             unsigned len, loff_t *poff, int *checkeof)
+static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
+                               int *checkeof)
 {
+       struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct page **pages;
-       u64 off = *poff;
+       u64 off = iocb->ki_pos;
        int num_pages, ret;
+       size_t len = i->count;
 
-       dout("sync_read on file %p %llu~%u %s\n", file, off, len,
+       dout("sync_read on file %p %llu~%u %s\n", file, off,
+            (unsigned)len,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
-
-       if (file->f_flags & O_DIRECT) {
-               num_pages = calc_pages_for((unsigned long)data, len);
-               pages = ceph_get_direct_page_vector(data, num_pages, true);
-       } else {
-               num_pages = calc_pages_for(off, len);
-               pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
-       }
-       if (IS_ERR(pages))
-               return PTR_ERR(pages);
-
        /*
         * flush any page cache pages in this range.  this
         * will make concurrent normal and sync io slow,
         * but it will at least behave sensibly when they are
         * in sequence.
         */
-       ret = filemap_write_and_wait(inode->i_mapping);
+       ret = filemap_write_and_wait_range(inode->i_mapping, off,
+                                               off + len);
        if (ret < 0)
-               goto done;
+               return ret;
 
-       ret = striped_read(inode, off, len, pages, num_pages, checkeof,
-                          file->f_flags & O_DIRECT,
-                          (unsigned long)data & ~PAGE_MASK);
+       if (file->f_flags & O_DIRECT) {
+               while (iov_iter_count(i)) {
+                       void __user *data = i->iov[0].iov_base + i->iov_offset;
+                       size_t len = i->iov[0].iov_len - i->iov_offset;
+
+                       num_pages = calc_pages_for((unsigned long)data, len);
+                       pages = ceph_get_direct_page_vector(data,
+                                                           num_pages, true);
+                       if (IS_ERR(pages))
+                               return PTR_ERR(pages);
+
+                       ret = striped_read(inode, off, len,
+                                          pages, num_pages, checkeof,
+                                          1, (unsigned long)data & ~PAGE_MASK);
+                       ceph_put_page_vector(pages, num_pages, true);
+
+                       if (ret <= 0)
+                               break;
+                       off += ret;
+                       iov_iter_advance(i, ret);
+                       if (ret < len)
+                               break;
+               }
+       } else {
+               num_pages = calc_pages_for(off, len);
+               pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
+               if (IS_ERR(pages))
+                       return PTR_ERR(pages);
+               ret = striped_read(inode, off, len, pages,
+                                       num_pages, checkeof, 0, 0);
+               if (ret > 0) {
+                       int l, k = 0;
+                       size_t left = len = ret;
+
+                       while (left) {
+                               void __user *data = i->iov[0].iov_base
+                                                       + i->iov_offset;
+                               l = min(i->iov[0].iov_len - i->iov_offset,
+                                       left);
+
+                               ret = ceph_copy_page_vector_to_user(&pages[k],
+                                                                   data, off,
+                                                                   l);
+                               if (ret > 0) {
+                                       iov_iter_advance(i, ret);
+                                       left -= ret;
+                                       off += ret;
+                                       k = calc_pages_for(iocb->ki_pos,
+                                                          len - left + 1) - 1;
+                                       BUG_ON(k >= num_pages && left);
+                               } else
+                                       break;
+                       }
+               }
+               ceph_release_page_vector(pages, num_pages);
+       }
 
-       if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
-               ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
-       if (ret >= 0)
-               *poff = off + ret;
+       if (off > iocb->ki_pos) {
+               ret = off - iocb->ki_pos;
+               iocb->ki_pos = off;
+       }
 
-done:
-       if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages, true);
-       else
-               ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
        return ret;
 }
@@ -489,83 +530,79 @@ static void ceph_sync_write_unsafe(struct ceph_osd_request *req, bool unsafe)
        }
 }
 
+
 /*
- * Synchronous write, straight from __user pointer or user pages (if
- * O_DIRECT).
+ * Synchronous write, straight from __user pointer or user pages.
  *
  * If write spans object boundary, just do multiple writes.  (For a
  * correct atomic write, we should e.g. take write locks on all
  * objects, rollback on failure, etc.)
  */
-static ssize_t ceph_sync_write(struct file *file, const char __user *data,
-                              size_t left, loff_t pos, loff_t *ppos)
+static ssize_t
+ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
+                      unsigned long nr_segs, size_t count)
 {
+       struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_snap_context *snapc;
        struct ceph_vino vino;
        struct ceph_osd_request *req;
-       int num_ops = 1;
        struct page **pages;
        int num_pages;
-       u64 len;
        int written = 0;
        int flags;
        int check_caps = 0;
-       int page_align, io_align;
-       unsigned long buf_align;
+       int page_align;
        int ret;
        struct timespec mtime = CURRENT_TIME;
-       bool own_pages = false;
+       loff_t pos = iocb->ki_pos;
+       struct iov_iter i;
 
        if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
                return -EROFS;
 
-       dout("sync_write on file %p %lld~%u %s\n", file, pos,
-            (unsigned)left, (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
+       dout("sync_direct_write on file %p %lld~%u\n", file, pos,
+            (unsigned)count);
 
-       ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
+       ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + count);
        if (ret < 0)
                return ret;
 
        ret = invalidate_inode_pages2_range(inode->i_mapping,
                                            pos >> PAGE_CACHE_SHIFT,
-                                           (pos + left) >> PAGE_CACHE_SHIFT);
+                                           (pos + count) >> PAGE_CACHE_SHIFT);
        if (ret < 0)
                dout("invalidate_inode_pages2_range returned %d\n", ret);
 
        flags = CEPH_OSD_FLAG_ORDERSNAP |
                CEPH_OSD_FLAG_ONDISK |
                CEPH_OSD_FLAG_WRITE;
-       if ((file->f_flags & (O_SYNC|O_DIRECT)) == 0)
-               flags |= CEPH_OSD_FLAG_ACK;
-       else
-               num_ops++;      /* Also include a 'startsync' command. */
 
-       /*
-        * we may need to do multiple writes here if we span an object
-        * boundary.  this isn't atomic, unfortunately.  :(
-        */
-more:
-       io_align = pos & ~PAGE_MASK;
-       buf_align = (unsigned long)data & ~PAGE_MASK;
-       len = left;
-
-       snapc = ci->i_snap_realm->cached_context;
-       vino = ceph_vino(inode);
-       req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
-                                   vino, pos, &len, num_ops,
-                                   CEPH_OSD_OP_WRITE, flags, snapc,
-                                   ci->i_truncate_seq, ci->i_truncate_size,
-                                   false);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       iov_iter_init(&i, iov, nr_segs, count, 0);
+
+       while (iov_iter_count(&i) > 0) {
+               void __user *data = i.iov->iov_base + i.iov_offset;
+               u64 len = i.iov->iov_len - i.iov_offset;
+
+               page_align = (unsigned long)data & ~PAGE_MASK;
+
+               snapc = ci->i_snap_realm->cached_context;
+               vino = ceph_vino(inode);
+               req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
+                                           vino, pos, &len,
+                                           2,/*include a 'startsync' command*/
+                                           CEPH_OSD_OP_WRITE, flags, snapc,
+                                           ci->i_truncate_seq,
+                                           ci->i_truncate_size,
+                                           false);
+               if (IS_ERR(req)) {
+                       ret = PTR_ERR(req);
+                       goto out;
+               }
 
-       /* write from beginning of first page, regardless of io alignment */
-       page_align = file->f_flags & O_DIRECT ? buf_align : io_align;
-       num_pages = calc_pages_for(page_align, len);
-       if (file->f_flags & O_DIRECT) {
+               num_pages = calc_pages_for(page_align, len);
                pages = ceph_get_direct_page_vector(data, num_pages, false);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
@@ -577,60 +614,175 @@ more:
                 * may block.
                 */
                truncate_inode_pages_range(inode->i_mapping, pos,
-                                          (pos+len) | (PAGE_CACHE_SIZE-1));
-       } else {
+                                  (pos+len) | (PAGE_CACHE_SIZE-1));
+               osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align,
+                                               false, false);
+
+               /* BUG_ON(vino.snap != CEPH_NOSNAP); */
+               ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
+
+               ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
+               if (!ret)
+                       ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
+
+               ceph_put_page_vector(pages, num_pages, false);
+
+out:
+               ceph_osdc_put_request(req);
+               if (ret == 0) {
+                       pos += len;
+                       written += len;
+                       iov_iter_advance(&i, (size_t)len);
+
+                       if (pos > i_size_read(inode)) {
+                               check_caps = ceph_inode_set_size(inode, pos);
+                               if (check_caps)
+                                       ceph_check_caps(ceph_inode(inode),
+                                                       CHECK_CAPS_AUTHONLY,
+                                                       NULL);
+                       }
+               } else
+                       break;
+       }
+
+       if (ret != -EOLDSNAPC && written > 0) {
+               iocb->ki_pos = pos;
+               ret = written;
+       }
+       return ret;
+}
+
+
+/*
+ * Synchronous write, straight from __user pointer or user pages.
+ *
+ * If write spans object boundary, just do multiple writes.  (For a
+ * correct atomic write, we should e.g. take write locks on all
+ * objects, rollback on failure, etc.)
+ */
+static ssize_t ceph_sync_write(struct kiocb *iocb, const struct iovec *iov,
+                              unsigned long nr_segs, size_t count)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+       struct ceph_snap_context *snapc;
+       struct ceph_vino vino;
+       struct ceph_osd_request *req;
+       struct page **pages;
+       u64 len;
+       int num_pages;
+       int written = 0;
+       int flags;
+       int check_caps = 0;
+       int ret;
+       struct timespec mtime = CURRENT_TIME;
+       loff_t pos = iocb->ki_pos;
+       struct iov_iter i;
+
+       if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+               return -EROFS;
+
+       dout("sync_write on file %p %lld~%u\n", file, pos, (unsigned)count);
+
+       ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + count);
+       if (ret < 0)
+               return ret;
+
+       ret = invalidate_inode_pages2_range(inode->i_mapping,
+                                           pos >> PAGE_CACHE_SHIFT,
+                                           (pos + count) >> PAGE_CACHE_SHIFT);
+       if (ret < 0)
+               dout("invalidate_inode_pages2_range returned %d\n", ret);
+
+       flags = CEPH_OSD_FLAG_ORDERSNAP |
+               CEPH_OSD_FLAG_ONDISK |
+               CEPH_OSD_FLAG_WRITE |
+               CEPH_OSD_FLAG_ACK;
+
+       iov_iter_init(&i, iov, nr_segs, count, 0);
+
+       while ((len = iov_iter_count(&i)) > 0) {
+               size_t left;
+               int n;
+
+               snapc = ci->i_snap_realm->cached_context;
+               vino = ceph_vino(inode);
+               req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
+                                           vino, pos, &len, 1,
+                                           CEPH_OSD_OP_WRITE, flags, snapc,
+                                           ci->i_truncate_seq,
+                                           ci->i_truncate_size,
+                                           false);
+               if (IS_ERR(req)) {
+                       ret = PTR_ERR(req);
+                       goto out;
+               }
+
+               /*
+                * write from beginning of first page,
+                * regardless of io alignment
+                */
+               num_pages = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
                pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
                        goto out;
                }
-               ret = ceph_copy_user_to_page_vector(pages, data, pos, len);
+
+               left = len;
+               for (n = 0; n < num_pages; n++) {
+                       size_t plen = min_t(size_t, left, PAGE_SIZE);
+                       ret = iov_iter_copy_from_user(pages[n], &i, 0, plen);
+                       if (ret != plen) {
+                               ret = -EFAULT;
+                               break;
+                       }
+                       left -= ret;
+                       iov_iter_advance(&i, ret);
+               }
+
                if (ret < 0) {
                        ceph_release_page_vector(pages, num_pages);
                        goto out;
                }
 
-               if ((file->f_flags & O_SYNC) == 0) {
-                       /* get a second commit callback */
-                       req->r_unsafe_callback = ceph_sync_write_unsafe;
-                       req->r_inode = inode;
-                       own_pages = true;
-               }
-       }
-       osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align,
-                                       false, own_pages);
+               /* get a second commit callback */
+               req->r_unsafe_callback = ceph_sync_write_unsafe;
+               req->r_inode = inode;
 
-       /* BUG_ON(vino.snap != CEPH_NOSNAP); */
-       ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
+               osd_req_op_extent_osd_data_pages(req, 0, pages, len, 0,
+                                               false, true);
 
-       ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
-       if (!ret)
-               ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
+               /* BUG_ON(vino.snap != CEPH_NOSNAP); */
+               ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
 
-       if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages, false);
-       else if (file->f_flags & O_SYNC)
-               ceph_release_page_vector(pages, num_pages);
+               ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
+               if (!ret)
+                       ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
 
 out:
-       ceph_osdc_put_request(req);
-       if (ret == 0) {
-               pos += len;
-               written += len;
-               left -= len;
-               data += len;
-               if (left)
-                       goto more;
+               ceph_osdc_put_request(req);
+               if (ret == 0) {
+                       pos += len;
+                       written += len;
+
+                       if (pos > i_size_read(inode)) {
+                               check_caps = ceph_inode_set_size(inode, pos);
+                               if (check_caps)
+                                       ceph_check_caps(ceph_inode(inode),
+                                                       CHECK_CAPS_AUTHONLY,
+                                                       NULL);
+                       }
+               } else
+                       break;
+       }
 
+       if (ret != -EOLDSNAPC && written > 0) {
                ret = written;
-               *ppos = pos;
-               if (pos > i_size_read(inode))
-                       check_caps = ceph_inode_set_size(inode, pos);
-               if (check_caps)
-                       ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY,
-                                       NULL);
-       } else if (ret != -EOLDSNAPC && written > 0) {
-               ret = written;
+               iocb->ki_pos = pos;
        }
        return ret;
 }
@@ -647,55 +799,84 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov,
 {
        struct file *filp = iocb->ki_filp;
        struct ceph_file_info *fi = filp->private_data;
-       loff_t *ppos = &iocb->ki_pos;
-       size_t len = iov->iov_len;
+       size_t len = iocb->ki_nbytes;
        struct inode *inode = file_inode(filp);
        struct ceph_inode_info *ci = ceph_inode(inode);
-       void __user *base = iov->iov_base;
        ssize_t ret;
        int want, got = 0;
        int checkeof = 0, read = 0;
 
-       dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
-            inode, ceph_vinop(inode), pos, (unsigned)len, inode);
 again:
+       dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
+            inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode);
+
        if (fi->fmode & CEPH_FILE_MODE_LAZY)
                want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
        else
                want = CEPH_CAP_FILE_CACHE;
        ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1);
        if (ret < 0)
-               goto out;
-       dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)len,
-            ceph_cap_string(got));
+               return ret;
 
        if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
            (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (fi->flags & CEPH_F_SYNC))
+           (fi->flags & CEPH_F_SYNC)) {
+               struct iov_iter i;
+
+               dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+                    inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+                    ceph_cap_string(got));
+
+               if (!read) {
+                       ret = generic_segment_checks(iov, &nr_segs,
+                                                       &len, VERIFY_WRITE);
+                       if (ret)
+                               goto out;
+               }
+
+               iov_iter_init(&i, iov, nr_segs, len, read);
+
                /* hmm, this isn't really async... */
-               ret = ceph_sync_read(filp, base, len, ppos, &checkeof);
-       else
-               ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+               ret = ceph_sync_read(iocb, &i, &checkeof);
+       } else {
+               /*
+                * We can't modify the content of iov,
+                * so we only read from beginning.
+                */
+               if (read) {
+                       iocb->ki_pos = pos;
+                       len = iocb->ki_nbytes;
+                       read = 0;
+               }
+               dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+                    inode, ceph_vinop(inode), pos, (unsigned)len,
+                    ceph_cap_string(got));
 
+               ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+       }
 out:
        dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
             inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
        ceph_put_cap_refs(ci, got);
 
        if (checkeof && ret >= 0) {
-               int statret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
+               int statret = ceph_do_getattr(inode,
+                                             CEPH_STAT_CAP_SIZE);
 
                /* hit EOF or hole? */
-               if (statret == 0 && *ppos < inode->i_size) {
-                       dout("aio_read sync_read hit hole, ppos %lld < size %lld, reading more\n", *ppos, inode->i_size);
+               if (statret == 0 && iocb->ki_pos < inode->i_size &&
+                       ret < len) {
+                       dout("sync_read hit hole, ppos %lld < size %lld"
+                            ", reading more\n", iocb->ki_pos,
+                            inode->i_size);
+
                        read += ret;
-                       base += ret;
                        len -= ret;
                        checkeof = 0;
                        goto again;
                }
        }
+
        if (ret >= 0)
                ret += read;
 
@@ -772,11 +953,13 @@ retry_snap:
             inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
 
        if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (fi->flags & CEPH_F_SYNC)) {
+           (file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
                mutex_unlock(&inode->i_mutex);
-               written = ceph_sync_write(file, iov->iov_base, count,
-                                         pos, &iocb->ki_pos);
+               if (file->f_flags & O_DIRECT)
+                       written = ceph_sync_direct_write(iocb, iov,
+                                                        nr_segs, count);
+               else
+                       written = ceph_sync_write(iocb, iov, nr_segs, count);
                if (written == -EOLDSNAPC) {
                        dout("aio_write %p %llx.%llx %llu~%u"
                                "got EOLDSNAPC, retrying\n",
@@ -1018,7 +1201,7 @@ static long ceph_fallocate(struct file *file, int mode,
                                loff_t offset, loff_t length)
 {
        struct ceph_file_info *fi = file->private_data;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file_inode(file);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_osd_client *osdc =
                &ceph_inode_to_client(inode)->client->osdc;
index 278fd28912880b5cc09989ed7dcb8e7fbbfcb3ef..32d519d8a2e210316fbf2af3b2c0a842d47a13b2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/namei.h>
 #include <linux/writeback.h>
 #include <linux/vmalloc.h>
+#include <linux/posix_acl.h>
 
 #include "super.h"
 #include "mds_client.h"
@@ -95,6 +96,8 @@ const struct inode_operations ceph_file_iops = {
        .getxattr = ceph_getxattr,
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
+       .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
 };
 
 
@@ -335,12 +338,10 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
        ci->i_hold_caps_min = 0;
        ci->i_hold_caps_max = 0;
        INIT_LIST_HEAD(&ci->i_cap_delay_list);
-       ci->i_cap_exporting_mds = 0;
-       ci->i_cap_exporting_mseq = 0;
-       ci->i_cap_exporting_issued = 0;
        INIT_LIST_HEAD(&ci->i_cap_snaps);
        ci->i_head_snapc = NULL;
        ci->i_snap_caps = 0;
+       ci->i_cap_exporting_issued = 0;
 
        for (i = 0; i < CEPH_FILE_MODE_NUM; i++)
                ci->i_nr_by_mode[i] = 0;
@@ -436,6 +437,16 @@ void ceph_destroy_inode(struct inode *inode)
        call_rcu(&inode->i_rcu, ceph_i_callback);
 }
 
+int ceph_drop_inode(struct inode *inode)
+{
+       /*
+        * Positve dentry and corresponding inode are always accompanied
+        * in MDS reply. So no need to keep inode in the cache after
+        * dropping all its aliases.
+        */
+       return 1;
+}
+
 /*
  * Helpers to fill in size, ctime, mtime, and atime.  We have to be
  * careful because either the client or MDS may have more up to date
@@ -670,6 +681,7 @@ static int fill_inode(struct inode *inode,
                        memcpy(ci->i_xattrs.blob->vec.iov_base,
                               iinfo->xattr_data, iinfo->xattr_len);
                ci->i_xattrs.version = le64_to_cpu(info->xattr_version);
+               ceph_forget_all_cached_acls(inode);
                xattr_blob = NULL;
        }
 
@@ -1454,7 +1466,8 @@ static void ceph_invalidate_work(struct work_struct *work)
        dout("invalidate_pages %p gen %d revoking %d\n", inode,
             ci->i_rdcache_gen, ci->i_rdcache_revoking);
        if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
-               /* nevermind! */
+               if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
+                       check = 1;
                spin_unlock(&ci->i_ceph_lock);
                mutex_unlock(&ci->i_truncate_mutex);
                goto out;
@@ -1475,13 +1488,14 @@ static void ceph_invalidate_work(struct work_struct *work)
                dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
                     inode, orig_gen, ci->i_rdcache_gen,
                     ci->i_rdcache_revoking);
+               if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
+                       check = 1;
        }
        spin_unlock(&ci->i_ceph_lock);
        mutex_unlock(&ci->i_truncate_mutex);
-
+out:
        if (check)
                ceph_check_caps(ci, 0, NULL);
-out:
        iput(inode);
 }
 
@@ -1602,6 +1616,8 @@ static const struct inode_operations ceph_symlink_iops = {
        .getxattr = ceph_getxattr,
        .listxattr = ceph_listxattr,
        .removexattr = ceph_removexattr,
+       .get_acl = ceph_get_acl,
+       .set_acl = ceph_set_acl,
 };
 
 /*
@@ -1675,6 +1691,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
                        dirtied |= CEPH_CAP_AUTH_EXCL;
                } else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 ||
                           attr->ia_mode != inode->i_mode) {
+                       inode->i_mode = attr->ia_mode;
                        req->r_args.setattr.mode = cpu_to_le32(attr->ia_mode);
                        mask |= CEPH_SETATTR_MODE;
                        release |= CEPH_CAP_AUTH_SHARED;
@@ -1790,6 +1807,12 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        if (inode_dirty_flags)
                __mark_inode_dirty(inode, inode_dirty_flags);
 
+       if (ia_valid & ATTR_MODE) {
+               err = posix_acl_chmod(inode, attr->ia_mode);
+               if (err)
+                       goto out_put;
+       }
+
        if (mask) {
                req->r_inode = inode;
                ihold(inode);
@@ -1809,6 +1832,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        return err;
 out:
        spin_unlock(&ci->i_ceph_lock);
+out_put:
        ceph_mdsc_put_request(req);
        return err;
 }
index 669622fd1ae3d52af418cc4c283a5f22513bca73..dc66c9e023e4f3aee170db98d2bb549819d99abc 100644 (file)
@@ -183,6 +183,8 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_osd_client *osdc =
                &ceph_sb_to_client(inode->i_sb)->client->osdc;
+       struct ceph_object_locator oloc;
+       struct ceph_object_id oid;
        u64 len = 1, olen;
        u64 tmp;
        struct ceph_pg pgid;
@@ -211,8 +213,10 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
        snprintf(dl.object_name, sizeof(dl.object_name), "%llx.%08llx",
                 ceph_ino(inode), dl.object_no);
 
-       r = ceph_calc_ceph_pg(&pgid, dl.object_name, osdc->osdmap,
-                               ceph_file_layout_pg_pool(ci->i_layout));
+       oloc.pool = ceph_file_layout_pg_pool(ci->i_layout);
+       ceph_oid_set_name(&oid, dl.object_name);
+
+       r = ceph_oloc_oid_to_pg(osdc->osdmap, &oloc, &oid, &pgid);
        if (r < 0) {
                up_read(&osdc->map_sem);
                return r;
index d90861f452107cc47b7242e8ea66dc1257f7c235..f4f050a69a48fff9a707c28d4a024691a5bdc814 100644 (file)
@@ -63,7 +63,7 @@ static const struct ceph_connection_operations mds_con_ops;
  */
 static int parse_reply_info_in(void **p, void *end,
                               struct ceph_mds_reply_info_in *info,
-                              int features)
+                              u64 features)
 {
        int err = -EIO;
 
@@ -98,7 +98,7 @@ bad:
  */
 static int parse_reply_info_trace(void **p, void *end,
                                  struct ceph_mds_reply_info_parsed *info,
-                                 int features)
+                                 u64 features)
 {
        int err;
 
@@ -145,7 +145,7 @@ out_bad:
  */
 static int parse_reply_info_dir(void **p, void *end,
                                struct ceph_mds_reply_info_parsed *info,
-                               int features)
+                               u64 features)
 {
        u32 num, i = 0;
        int err;
@@ -217,7 +217,7 @@ out_bad:
  */
 static int parse_reply_info_filelock(void **p, void *end,
                                     struct ceph_mds_reply_info_parsed *info,
-                                    int features)
+                                    u64 features)
 {
        if (*p + sizeof(*info->filelock_reply) > end)
                goto bad;
@@ -238,7 +238,7 @@ bad:
  */
 static int parse_reply_info_create(void **p, void *end,
                                  struct ceph_mds_reply_info_parsed *info,
-                                 int features)
+                                 u64 features)
 {
        if (features & CEPH_FEATURE_REPLY_CREATE_INODE) {
                if (*p == end) {
@@ -262,7 +262,7 @@ bad:
  */
 static int parse_reply_info_extra(void **p, void *end,
                                  struct ceph_mds_reply_info_parsed *info,
-                                 int features)
+                                 u64 features)
 {
        if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
                return parse_reply_info_filelock(p, end, info, features);
@@ -280,7 +280,7 @@ static int parse_reply_info_extra(void **p, void *end,
  */
 static int parse_reply_info(struct ceph_msg *msg,
                            struct ceph_mds_reply_info_parsed *info,
-                           int features)
+                           u64 features)
 {
        void *p, *end;
        u32 len;
@@ -713,14 +713,15 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
                        struct dentry *dn = get_nonsnap_parent(parent);
                        inode = dn->d_inode;
                        dout("__choose_mds using nonsnap parent %p\n", inode);
-               } else if (req->r_dentry->d_inode) {
+               } else {
                        /* dentry target */
                        inode = req->r_dentry->d_inode;
-               } else {
-                       /* dir + name */
-                       inode = dir;
-                       hash = ceph_dentry_hash(dir, req->r_dentry);
-                       is_hash = true;
+                       if (!inode || mode == USE_AUTH_MDS) {
+                               /* dir + name */
+                               inode = dir;
+                               hash = ceph_dentry_hash(dir, req->r_dentry);
+                               is_hash = true;
+                       }
                }
        }
 
@@ -846,35 +847,56 @@ static int __open_session(struct ceph_mds_client *mdsc,
  *
  * called under mdsc->mutex
  */
+static struct ceph_mds_session *
+__open_export_target_session(struct ceph_mds_client *mdsc, int target)
+{
+       struct ceph_mds_session *session;
+
+       session = __ceph_lookup_mds_session(mdsc, target);
+       if (!session) {
+               session = register_session(mdsc, target);
+               if (IS_ERR(session))
+                       return session;
+       }
+       if (session->s_state == CEPH_MDS_SESSION_NEW ||
+           session->s_state == CEPH_MDS_SESSION_CLOSING)
+               __open_session(mdsc, session);
+
+       return session;
+}
+
+struct ceph_mds_session *
+ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target)
+{
+       struct ceph_mds_session *session;
+
+       dout("open_export_target_session to mds%d\n", target);
+
+       mutex_lock(&mdsc->mutex);
+       session = __open_export_target_session(mdsc, target);
+       mutex_unlock(&mdsc->mutex);
+
+       return session;
+}
+
 static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
                                          struct ceph_mds_session *session)
 {
        struct ceph_mds_info *mi;
        struct ceph_mds_session *ts;
        int i, mds = session->s_mds;
-       int target;
 
        if (mds >= mdsc->mdsmap->m_max_mds)
                return;
+
        mi = &mdsc->mdsmap->m_info[mds];
        dout("open_export_target_sessions for mds%d (%d targets)\n",
             session->s_mds, mi->num_export_targets);
 
        for (i = 0; i < mi->num_export_targets; i++) {
-               target = mi->export_targets[i];
-               ts = __ceph_lookup_mds_session(mdsc, target);
-               if (!ts) {
-                       ts = register_session(mdsc, target);
-                       if (IS_ERR(ts))
-                               return;
-               }
-               if (session->s_state == CEPH_MDS_SESSION_NEW ||
-                   session->s_state == CEPH_MDS_SESSION_CLOSING)
-                       __open_session(mdsc, session);
-               else
-                       dout(" mds%d target mds%d %p is %s\n", session->s_mds,
-                            i, ts, session_state_name(ts->s_state));
-               ceph_put_mds_session(ts);
+               ts = __open_export_target_session(mdsc, mi->export_targets[i]);
+               if (!IS_ERR(ts))
+                       ceph_put_mds_session(ts);
        }
 }
 
@@ -1136,6 +1158,21 @@ static int send_renew_caps(struct ceph_mds_client *mdsc,
        return 0;
 }
 
+static int send_flushmsg_ack(struct ceph_mds_client *mdsc,
+                            struct ceph_mds_session *session, u64 seq)
+{
+       struct ceph_msg *msg;
+
+       dout("send_flushmsg_ack to mds%d (%s)s seq %lld\n",
+            session->s_mds, session_state_name(session->s_state), seq);
+       msg = create_session_msg(CEPH_SESSION_FLUSHMSG_ACK, seq);
+       if (!msg)
+               return -ENOMEM;
+       ceph_con_send(&session->s_con, msg);
+       return 0;
+}
+
+
 /*
  * Note new cap ttl, and any transition from stale -> not stale (fresh?).
  *
@@ -1214,7 +1251,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
 {
        struct ceph_mds_session *session = arg;
        struct ceph_inode_info *ci = ceph_inode(inode);
-       int used, oissued, mine;
+       int used, wanted, oissued, mine;
 
        if (session->s_trim_caps <= 0)
                return -1;
@@ -1222,14 +1259,19 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
        spin_lock(&ci->i_ceph_lock);
        mine = cap->issued | cap->implemented;
        used = __ceph_caps_used(ci);
+       wanted = __ceph_caps_file_wanted(ci);
        oissued = __ceph_caps_issued_other(ci, cap);
 
-       dout("trim_caps_cb %p cap %p mine %s oissued %s used %s\n",
+       dout("trim_caps_cb %p cap %p mine %s oissued %s used %s wanted %s\n",
             inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued),
-            ceph_cap_string(used));
-       if (ci->i_dirty_caps)
-               goto out;   /* dirty caps */
-       if ((used & ~oissued) & mine)
+            ceph_cap_string(used), ceph_cap_string(wanted));
+       if (cap == ci->i_auth_cap) {
+               if (ci->i_dirty_caps | ci->i_flushing_caps)
+                       goto out;
+               if ((used | wanted) & CEPH_CAP_ANY_WR)
+                       goto out;
+       }
+       if ((used | wanted) & ~oissued & mine)
                goto out;   /* we need these caps */
 
        session->s_trim_caps--;
@@ -2156,26 +2198,16 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
         */
        if (result == -ESTALE) {
                dout("got ESTALE on request %llu", req->r_tid);
-               if (!req->r_inode) {
-                       /* do nothing; not an authority problem */
-               } else if (req->r_direct_mode != USE_AUTH_MDS) {
+               if (req->r_direct_mode != USE_AUTH_MDS) {
                        dout("not using auth, setting for that now");
                        req->r_direct_mode = USE_AUTH_MDS;
                        __do_request(mdsc, req);
                        mutex_unlock(&mdsc->mutex);
                        goto out;
                } else  {
-                       struct ceph_inode_info *ci = ceph_inode(req->r_inode);
-                       struct ceph_cap *cap = NULL;
-
-                       if (req->r_session)
-                               cap = ceph_get_cap_for_mds(ci,
-                                                  req->r_session->s_mds);
-
-                       dout("already using auth");
-                       if ((!cap || cap != ci->i_auth_cap) ||
-                           (cap->mseq != req->r_sent_on_mseq)) {
-                               dout("but cap changed, so resending");
+                       int mds = __choose_mds(mdsc, req);
+                       if (mds >= 0 && mds != req->r_session->s_mds) {
+                               dout("but auth changed, so resending");
                                __do_request(mdsc, req);
                                mutex_unlock(&mdsc->mutex);
                                goto out;
@@ -2400,6 +2432,10 @@ static void handle_session(struct ceph_mds_session *session,
                trim_caps(mdsc, session, le32_to_cpu(h->max_caps));
                break;
 
+       case CEPH_SESSION_FLUSHMSG:
+               send_flushmsg_ack(mdsc, session, seq);
+               break;
+
        default:
                pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
                WARN_ON(1);
index 4c053d099ae4e60400dbcbdcce21844138ba8a47..68288917c7371fbebc314a0085e691580f57a711 100644 (file)
@@ -383,6 +383,8 @@ extern void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
 extern void ceph_mdsc_handle_map(struct ceph_mds_client *mdsc,
                                 struct ceph_msg *msg);
 
+extern struct ceph_mds_session *
+ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target);
 extern void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc,
                                          struct ceph_mds_session *session);
 
index 89fa4a940a0ffff7b9cea94bfebb1bb62f8721df..4440f447fd3f2329b28f8e88e44e10141e4b30c4 100644 (file)
@@ -41,6 +41,8 @@ const char *ceph_session_op_name(int op)
        case CEPH_SESSION_RENEWCAPS: return "renewcaps";
        case CEPH_SESSION_STALE: return "stale";
        case CEPH_SESSION_RECALL_STATE: return "recall_state";
+       case CEPH_SESSION_FLUSHMSG: return "flushmsg";
+       case CEPH_SESSION_FLUSHMSG_ACK: return "flushmsg_ack";
        }
        return "???";
 }
index 6a0951e4304441a241ca8fe550aba36cc097c271..2df963f1cf5a3b84615772e793cd45eeddec801f 100644 (file)
@@ -490,10 +490,10 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
                                        struct ceph_options *opt)
 {
        struct ceph_fs_client *fsc;
-       const unsigned supported_features =
+       const u64 supported_features =
                CEPH_FEATURE_FLOCK |
                CEPH_FEATURE_DIRLAYOUTHASH;
-       const unsigned required_features = 0;
+       const u64 required_features = 0;
        int page_count;
        size_t size;
        int err = -ENOMEM;
@@ -686,6 +686,7 @@ static const struct super_operations ceph_super_ops = {
        .alloc_inode    = ceph_alloc_inode,
        .destroy_inode  = ceph_destroy_inode,
        .write_inode    = ceph_write_inode,
+       .drop_inode     = ceph_drop_inode,
        .sync_fs        = ceph_sync_fs,
        .put_super      = ceph_put_super,
        .show_options   = ceph_show_options,
@@ -818,7 +819,11 @@ static int ceph_set_super(struct super_block *s, void *data)
 
        s->s_flags = fsc->mount_options->sb_flags;
        s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       s->s_flags |= MS_POSIXACL;
+#endif
 
+       s->s_xattr = ceph_xattr_handlers;
        s->s_fs_info = fsc;
        fsc->sb = s;
 
index ef4ac38bb614a911680668fe52f6e7fa272d94ce..aa260590f6154cce25517c24789e62f58ed1b7a3 100644 (file)
@@ -287,14 +287,12 @@ struct ceph_inode_info {
        unsigned long i_hold_caps_min; /* jiffies */
        unsigned long i_hold_caps_max; /* jiffies */
        struct list_head i_cap_delay_list;  /* for delayed cap release to mds */
-       int i_cap_exporting_mds;         /* to handle cap migration between */
-       unsigned i_cap_exporting_mseq;   /*  mds's. */
-       unsigned i_cap_exporting_issued;
        struct ceph_cap_reservation i_cap_migration_resv;
        struct list_head i_cap_snaps;   /* snapped state pending flush to mds */
        struct ceph_snap_context *i_head_snapc;  /* set if wr_buffer_head > 0 or
                                                    dirty|flushing caps */
        unsigned i_snap_caps;           /* cap bits for snapped files */
+       unsigned i_cap_exporting_issued;
 
        int i_nr_by_mode[CEPH_FILE_MODE_NUM];  /* open file counts */
 
@@ -335,7 +333,6 @@ struct ceph_inode_info {
        u32 i_fscache_gen; /* sequence, for delayed fscache validate */
        struct work_struct i_revalidate_work;
 #endif
-
        struct inode vfs_inode; /* at end */
 };
 
@@ -529,6 +526,8 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci)
 }
 extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask);
 
+extern int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
+                                     struct ceph_cap *ocap, int mask);
 extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
 extern int __ceph_caps_used(struct ceph_inode_info *ci);
 
@@ -691,6 +690,7 @@ extern const struct inode_operations ceph_file_iops;
 
 extern struct inode *ceph_alloc_inode(struct super_block *sb);
 extern void ceph_destroy_inode(struct inode *inode);
+extern int ceph_drop_inode(struct inode *inode);
 
 extern struct inode *ceph_get_inode(struct super_block *sb,
                                    struct ceph_vino vino);
@@ -718,12 +718,16 @@ extern void ceph_queue_writeback(struct inode *inode);
 extern int ceph_do_getattr(struct inode *inode, int mask);
 extern int ceph_permission(struct inode *inode, int mask);
 extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
+extern int ceph_setattr(struct dentry *dentry, struct iattr *attr);
 extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
                        struct kstat *stat);
 
 /* xattr.c */
 extern int ceph_setxattr(struct dentry *, const char *, const void *,
                         size_t, int);
+int __ceph_setxattr(struct dentry *, const char *, const void *, size_t, int);
+ssize_t __ceph_getxattr(struct inode *, const char *, void *, size_t);
+int __ceph_removexattr(struct dentry *, const char *);
 extern ssize_t ceph_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
 extern int ceph_removexattr(struct dentry *, const char *);
@@ -732,6 +736,38 @@ extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
 extern void __init ceph_xattr_init(void);
 extern void ceph_xattr_exit(void);
 
+/* acl.c */
+extern const struct xattr_handler *ceph_xattr_handlers[];
+
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+
+struct posix_acl *ceph_get_acl(struct inode *, int);
+int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type);
+int ceph_init_acl(struct dentry *, struct inode *, struct inode *);
+void ceph_forget_all_cached_acls(struct inode *inode);
+
+#else
+
+#define ceph_get_acl NULL
+#define ceph_set_acl NULL
+
+static inline int ceph_init_acl(struct dentry *dentry, struct inode *inode,
+                               struct inode *dir)
+{
+       return 0;
+}
+
+static inline int ceph_acl_chmod(struct dentry *dentry, struct inode *inode)
+{
+       return 0;
+}
+
+static inline void ceph_forget_all_cached_acls(struct inode *inode)
+{
+}
+
+#endif
+
 /* caps.c */
 extern const char *ceph_cap_string(int c);
 extern void ceph_handle_caps(struct ceph_mds_session *session,
@@ -744,6 +780,7 @@ extern int ceph_add_cap(struct inode *inode,
 extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
 extern void ceph_put_cap(struct ceph_mds_client *mdsc,
                         struct ceph_cap *cap);
+extern int ceph_is_any_caps(struct inode *inode);
 
 extern void __queue_cap_release(struct ceph_mds_session *session, u64 ino,
                                u64 cap_id, u32 migrate_seq, u32 issue_seq);
index be661d8f532adcea4b44d2b42aae52b788d4753e..898b6565ad3e2c114baca0282fafea6a5643071a 100644 (file)
@@ -6,16 +6,30 @@
 #include <linux/ceph/decode.h>
 
 #include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/slab.h>
 
 #define XATTR_CEPH_PREFIX "ceph."
 #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1)
 
+/*
+ * List of handlers for synthetic system.* attributes. Other
+ * attributes are handled directly.
+ */
+const struct xattr_handler *ceph_xattr_handlers[] = {
+#ifdef CONFIG_CEPH_FS_POSIX_ACL
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
+#endif
+       NULL,
+};
+
 static bool ceph_is_valid_xattr(const char *name)
 {
        return !strncmp(name, XATTR_CEPH_PREFIX, XATTR_CEPH_PREFIX_LEN) ||
               !strncmp(name, XATTR_SECURITY_PREFIX,
                        XATTR_SECURITY_PREFIX_LEN) ||
+              !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
               !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
               !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
@@ -663,10 +677,9 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
        }
 }
 
-ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
+ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
                      size_t size)
 {
-       struct inode *inode = dentry->d_inode;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int err;
        struct ceph_inode_xattr *xattr;
@@ -675,7 +688,6 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
        if (!ceph_is_valid_xattr(name))
                return -ENODATA;
 
-
        /* let's see if a virtual xattr was requested */
        vxattr = ceph_match_vxattr(inode, name);
        if (vxattr && !(vxattr->exists_cb && !vxattr->exists_cb(ci))) {
@@ -725,6 +737,15 @@ out:
        return err;
 }
 
+ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
+                     size_t size)
+{
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_getxattr(dentry, name, value, size);
+
+       return __ceph_getxattr(dentry->d_inode, name, value, size);
+}
+
 ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
 {
        struct inode *inode = dentry->d_inode;
@@ -863,8 +884,8 @@ out:
        return err;
 }
 
-int ceph_setxattr(struct dentry *dentry, const char *name,
-                 const void *value, size_t size, int flags)
+int __ceph_setxattr(struct dentry *dentry, const char *name,
+                       const void *value, size_t size, int flags)
 {
        struct inode *inode = dentry->d_inode;
        struct ceph_vxattr *vxattr;
@@ -879,9 +900,6 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
        struct ceph_inode_xattr *xattr = NULL;
        int required_blob_size;
 
-       if (ceph_snap(inode) != CEPH_NOSNAP)
-               return -EROFS;
-
        if (!ceph_is_valid_xattr(name))
                return -EOPNOTSUPP;
 
@@ -958,6 +976,18 @@ out:
        return err;
 }
 
+int ceph_setxattr(struct dentry *dentry, const char *name,
+                 const void *value, size_t size, int flags)
+{
+       if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+               return -EROFS;
+
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_setxattr(dentry, name, value, size, flags);
+
+       return __ceph_setxattr(dentry, name, value, size, flags);
+}
+
 static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
@@ -984,7 +1014,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
        return err;
 }
 
-int ceph_removexattr(struct dentry *dentry, const char *name)
+int __ceph_removexattr(struct dentry *dentry, const char *name)
 {
        struct inode *inode = dentry->d_inode;
        struct ceph_vxattr *vxattr;
@@ -994,9 +1024,6 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
        int required_blob_size;
        int dirty;
 
-       if (ceph_snap(inode) != CEPH_NOSNAP)
-               return -EROFS;
-
        if (!ceph_is_valid_xattr(name))
                return -EOPNOTSUPP;
 
@@ -1053,3 +1080,13 @@ out:
        return err;
 }
 
+int ceph_removexattr(struct dentry *dentry, const char *name)
+{
+       if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+               return -EROFS;
+
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_removexattr(dentry, name);
+
+       return __ceph_removexattr(dentry, name);
+}
index e501ac3a49ff7380a1bd2644ecc8abc3f648ce64..06610cf94d579a8da72a5d6af53b098ec43e482d 100644 (file)
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/blkdev.h>
-#include <linux/cramfs_fs.h>
 #include <linux/slab.h>
-#include <linux/cramfs_fs_sb.h>
 #include <linux/vfs.h>
 #include <linux/mutex.h>
-
+#include <uapi/linux/cramfs_fs.h>
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
+/*
+ * cramfs super-block data in memory
+ */
+struct cramfs_sb_info {
+       unsigned long magic;
+       unsigned long size;
+       unsigned long blocks;
+       unsigned long files;
+       unsigned long flags;
+};
+
+static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
 static const struct super_operations cramfs_ops;
 static const struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
@@ -219,10 +235,11 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
        return read_buffers[buffer] + offset;
 }
 
-static void cramfs_put_super(struct super_block *sb)
+static void cramfs_kill_sb(struct super_block *sb)
 {
-       kfree(sb->s_fs_info);
-       sb->s_fs_info = NULL;
+       struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
+       kill_block_super(sb);
+       kfree(sbi);
 }
 
 static int cramfs_remount(struct super_block *sb, int *flags, char *data)
@@ -261,7 +278,7 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
                if (super.magic == CRAMFS_MAGIC_WEND) {
                        if (!silent)
                                printk(KERN_ERR "cramfs: wrong endianness\n");
-                       goto out;
+                       return -EINVAL;
                }
 
                /* check at 512 byte offset */
@@ -273,20 +290,20 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
                                printk(KERN_ERR "cramfs: wrong endianness\n");
                        else if (!silent)
                                printk(KERN_ERR "cramfs: wrong magic\n");
-                       goto out;
+                       return -EINVAL;
                }
        }
 
        /* get feature flags first */
        if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
                printk(KERN_ERR "cramfs: unsupported filesystem features\n");
-               goto out;
+               return -EINVAL;
        }
 
        /* Check that the root inode is in a sane state */
        if (!S_ISDIR(super.root.mode)) {
                printk(KERN_ERR "cramfs: root is not a directory\n");
-               goto out;
+               return -EINVAL;
        }
        /* correct strange, hard-coded permissions of mkcramfs */
        super.root.mode |= (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
@@ -310,22 +327,18 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
                  (root_offset != 512 + sizeof(struct cramfs_super))))
        {
                printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset);
-               goto out;
+               return -EINVAL;
        }
 
        /* Set it all up.. */
        sb->s_op = &cramfs_ops;
        root = get_cramfs_inode(sb, &super.root, 0);
        if (IS_ERR(root))
-               goto out;
+               return PTR_ERR(root);
        sb->s_root = d_make_root(root);
        if (!sb->s_root)
-               goto out;
+               return -ENOMEM;
        return 0;
-out:
-       kfree(sbi);
-       sb->s_fs_info = NULL;
-       return -EINVAL;
 }
 
 static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -550,7 +563,6 @@ static const struct inode_operations cramfs_dir_inode_operations = {
 };
 
 static const struct super_operations cramfs_ops = {
-       .put_super      = cramfs_put_super,
        .remount_fs     = cramfs_remount,
        .statfs         = cramfs_statfs,
 };
@@ -565,7 +577,7 @@ static struct file_system_type cramfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "cramfs",
        .mount          = cramfs_mount,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = cramfs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("cramfs");
similarity index 70%
rename from include/linux/cramfs_fs.h
rename to fs/cramfs/internal.h
index 133789609f239e5f25edfade82be8fe7f6ddb381..349d71272157ab8678805b0eb49902b3a96b50ec 100644 (file)
@@ -1,10 +1,4 @@
-#ifndef __CRAMFS_H
-#define __CRAMFS_H
-
-#include <uapi/linux/cramfs_fs.h>
-
 /* Uncompression interfaces to the underlying zlib */
 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
 int cramfs_uncompress_init(void);
 void cramfs_uncompress_exit(void);
-#endif
index 023329800d2e42152fec5a531f91f4310cae1729..1760c1b84d9787cc27cc23e22387147ad65129e7 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/errno.h>
 #include <linux/vmalloc.h>
 #include <linux/zlib.h>
-#include <linux/cramfs_fs.h>
+#include "internal.h"
 
 static z_stream stream;
 static int initialized;
index cb4a10690868263cb58e28012ee8f9abc4880da5..265e0ce9769c70db65d5f9df11c4365f44c6dd29 100644 (file)
@@ -3116,26 +3116,28 @@ char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
-static char *__dentry_path(struct dentry *dentry, char *buf, int buflen)
+static char *__dentry_path(struct dentry *d, char *buf, int buflen)
 {
+       struct dentry *dentry;
        char *end, *retval;
        int len, seq = 0;
        int error = 0;
 
+       if (buflen < 2)
+               goto Elong;
+
        rcu_read_lock();
 restart:
+       dentry = d;
        end = buf + buflen;
        len = buflen;
        prepend(&end, &len, "\0", 1);
-       if (buflen < 1)
-               goto Elong;
        /* Get '/' right */
        retval = end-1;
        *retval = '/';
        read_seqbegin_or_lock(&rename_lock, &seq);
        while (!IS_ROOT(dentry)) {
                struct dentry *parent = dentry->d_parent;
-               int error;
 
                prefetch(parent);
                error = prepend_name(&end, &len, &dentry->d_name);
index ab5954b50267d29afa219bbaec128af2304f59e2..ac44a69fbea9a533dbcc27cdc27771f4f7795f1e 100644 (file)
@@ -204,7 +204,7 @@ out:
 }
 
 #ifdef CONFIG_COMPAT
-COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, w0, u32, w1, char __user *, buf, size_t, len)
+COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, w0, u32, w1, char __user *, buf, compat_size_t, len)
 {
 #ifdef __BIG_ENDIAN
        return sys_lookup_dcookie(((u64)w0 << 32) | w1, buf, len);
index c36c4482447159c219a4d4f56506087229ebb276..b167ca48b8eef4984dec79a609644012421e6fea 100644 (file)
@@ -659,19 +659,17 @@ out_lock:
        return rc;
 }
 
-static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
-                                  size_t *bufsiz)
+static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)
 {
        struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
        char *lower_buf;
+       char *buf;
        mm_segment_t old_fs;
        int rc;
 
        lower_buf = kmalloc(PATH_MAX, GFP_KERNEL);
-       if (!lower_buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!lower_buf)
+               return ERR_PTR(-ENOMEM);
        old_fs = get_fs();
        set_fs(get_ds());
        rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
@@ -680,21 +678,18 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
        set_fs(old_fs);
        if (rc < 0)
                goto out;
-       rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry->d_sb,
+       rc = ecryptfs_decode_and_decrypt_filename(&buf, bufsiz, dentry->d_sb,
                                                  lower_buf, rc);
 out:
        kfree(lower_buf);
-       return rc;
+       return rc ? ERR_PTR(rc) : buf;
 }
 
 static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       char *buf;
-       size_t len = PATH_MAX;
-       int rc;
-
-       rc = ecryptfs_readlink_lower(dentry, &buf, &len);
-       if (rc)
+       size_t len;
+       char *buf = ecryptfs_readlink_lower(dentry, &len);
+       if (IS_ERR(buf))
                goto out;
        fsstack_copy_attr_atime(dentry->d_inode,
                                ecryptfs_dentry_to_lower(dentry)->d_inode);
@@ -1003,10 +998,12 @@ static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
                char *target;
                size_t targetsiz;
 
-               rc = ecryptfs_readlink_lower(dentry, &target, &targetsiz);
-               if (!rc) {
+               target = ecryptfs_readlink_lower(dentry, &targetsiz);
+               if (!IS_ERR(target)) {
                        kfree(target);
                        stat->size = targetsiz;
+               } else {
+                       rc = PTR_ERR(target);
                }
        }
        return rc;
index c6f57a74a559da265bc8f062eab06488d8d7c00a..50215bbd646313fdad24ae3b521af017b834bcf9 100644 (file)
@@ -26,11 +26,18 @@ static struct dentry *efs_mount(struct file_system_type *fs_type,
        return mount_bdev(fs_type, flags, dev_name, data, efs_fill_super);
 }
 
+static void efs_kill_sb(struct super_block *s)
+{
+       struct efs_sb_info *sbi = SUPER_INFO(s);
+       kill_block_super(s);
+       kfree(sbi);
+}
+
 static struct file_system_type efs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "efs",
        .mount          = efs_mount,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = efs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("efs");
@@ -105,12 +112,6 @@ static void destroy_inodecache(void)
        kmem_cache_destroy(efs_inode_cachep);
 }
 
-static void efs_put_super(struct super_block *s)
-{
-       kfree(s->s_fs_info);
-       s->s_fs_info = NULL;
-}
-
 static int efs_remount(struct super_block *sb, int *flags, char *data)
 {
        *flags |= MS_RDONLY;
@@ -120,7 +121,6 @@ static int efs_remount(struct super_block *sb, int *flags, char *data)
 static const struct super_operations efs_superblock_operations = {
        .alloc_inode    = efs_alloc_inode,
        .destroy_inode  = efs_destroy_inode,
-       .put_super      = efs_put_super,
        .statfs         = efs_statfs,
        .remount_fs     = efs_remount,
 };
@@ -259,7 +259,6 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        struct efs_sb_info *sb;
        struct buffer_head *bh;
        struct inode *root;
-       int ret = -EINVAL;
 
        sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
        if (!sb)
@@ -270,7 +269,7 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
                printk(KERN_ERR "EFS: device does not support %d byte blocks\n",
                        EFS_BLOCKSIZE);
-               goto out_no_fs_ul;
+               return -EINVAL;
        }
   
        /* read the vh (volume header) block */
@@ -278,7 +277,7 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
 
        if (!bh) {
                printk(KERN_ERR "EFS: cannot read volume header\n");
-               goto out_no_fs_ul;
+               return -EINVAL;
        }
 
        /*
@@ -290,13 +289,13 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        brelse(bh);
 
        if (sb->fs_start == -1) {
-               goto out_no_fs_ul;
+               return -EINVAL;
        }
 
        bh = sb_bread(s, sb->fs_start + EFS_SUPER);
        if (!bh) {
                printk(KERN_ERR "EFS: cannot read superblock\n");
-               goto out_no_fs_ul;
+               return -EINVAL;
        }
                
        if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
@@ -304,7 +303,7 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
                printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
 #endif
                brelse(bh);
-               goto out_no_fs_ul;
+               return -EINVAL;
        }
        brelse(bh);
 
@@ -319,24 +318,16 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        root = efs_iget(s, EFS_ROOTINODE);
        if (IS_ERR(root)) {
                printk(KERN_ERR "EFS: get root inode failed\n");
-               ret = PTR_ERR(root);
-               goto out_no_fs;
+               return PTR_ERR(root);
        }
 
        s->s_root = d_make_root(root);
        if (!(s->s_root)) {
                printk(KERN_ERR "EFS: get root dentry failed\n");
-               ret = -ENOMEM;
-               goto out_no_fs;
+               return -ENOMEM;
        }
 
        return 0;
-
-out_no_fs_ul:
-out_no_fs:
-       s->s_fs_info = NULL;
-       kfree(sb);
-       return ret;
 }
 
 static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
index 35470d9b96e68951de6f1a63fe3657f09a8296c4..d6a88e7812f3e68a84888ce104cce4285ea50538 100644 (file)
@@ -349,15 +349,12 @@ EXPORT_SYMBOL_GPL(eventfd_fget);
  */
 struct eventfd_ctx *eventfd_ctx_fdget(int fd)
 {
-       struct file *file;
        struct eventfd_ctx *ctx;
-
-       file = eventfd_fget(fd);
-       if (IS_ERR(file))
-               return (struct eventfd_ctx *) file;
-       ctx = eventfd_ctx_get(file->private_data);
-       fput(file);
-
+       struct fd f = fdget(fd);
+       if (!f.file)
+               return ERR_PTR(-EBADF);
+       ctx = eventfd_ctx_fileget(f.file);
+       fdput(f);
        return ctx;
 }
 EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
index a52a5d23c30bcfac672df7197c51b966cc087787..ee4317faccb1951852b483d825a5ccec7efa8a24 100644 (file)
@@ -577,7 +577,7 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
 
                if (offset >= i_size) {
                        *uptodate = true;
-                       EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index);
+                       EXOFS_DBGMSG2("offset >= i_size index=0x%lx\n", index);
                        return ZERO_PAGE(0);
                }
 
@@ -596,10 +596,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
                        *uptodate = true;
                else
                        *uptodate = PageUptodate(page);
-               EXOFS_DBGMSG("index=0x%lx uptodate=%d\n", index, *uptodate);
+               EXOFS_DBGMSG2("index=0x%lx uptodate=%d\n", index, *uptodate);
                return page;
        } else {
-               EXOFS_DBGMSG("YES that_locked_page index=0x%lx\n",
+               EXOFS_DBGMSG2("YES that_locked_page index=0x%lx\n",
                             pcol->that_locked_page->index);
                *uptodate = true;
                return pcol->that_locked_page;
@@ -611,11 +611,11 @@ static void __r4w_put_page(void *priv, struct page *page)
        struct page_collect *pcol = priv;
 
        if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) {
-               EXOFS_DBGMSG("index=0x%lx\n", page->index);
+               EXOFS_DBGMSG2("index=0x%lx\n", page->index);
                page_cache_release(page);
                return;
        }
-       EXOFS_DBGMSG("that_locked_page index=0x%lx\n",
+       EXOFS_DBGMSG2("that_locked_page index=0x%lx\n",
                     ZERO_PAGE(0) == page ? -1 : page->index);
 }
 
@@ -961,6 +961,14 @@ static void exofs_invalidatepage(struct page *page, unsigned int offset,
        WARN_ON(1);
 }
 
+
+ /* TODO: Should be easy enough to do proprly */
+static ssize_t exofs_direct_IO(int rw, struct kiocb *iocb,
+               const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+{
+       return 0;
+}
+
 const struct address_space_operations exofs_aops = {
        .readpage       = exofs_readpage,
        .readpages      = exofs_readpages,
@@ -974,7 +982,7 @@ const struct address_space_operations exofs_aops = {
 
        /* Not implemented Yet */
        .bmap           = NULL, /* TODO: use osd's OSD_ACT_READ_MAP */
-       .direct_IO      = NULL, /* TODO: Should be trivial to do */
+       .direct_IO      = exofs_direct_IO,
 
        /* With these NULL has special meaning or default is not exported */
        .get_xip_mem    = NULL,
@@ -1010,7 +1018,7 @@ static int _do_truncate(struct inode *inode, loff_t newsize)
        if (likely(!ret))
                truncate_setsize(inode, newsize);
 
-       EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n",
+       EXOFS_DBGMSG2("(0x%lx) size=0x%llx ret=>%d\n",
                     inode->i_ino, newsize, ret);
        return ret;
 }
@@ -1094,14 +1102,13 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
                /* If object is lost on target we might as well enable it's
                 * delete.
                 */
-               if ((ret == -ENOENT) || (ret == -EINVAL))
-                       ret = 0;
+               ret = 0;
                goto out;
        }
 
        ret = extract_attr_from_ios(ios, &attrs[0]);
        if (ret) {
-               EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__);
+               EXOFS_ERR("%s: extract_attr 0 of inode failed\n", __func__);
                goto out;
        }
        WARN_ON(attrs[0].len != EXOFS_INO_ATTR_SIZE);
@@ -1109,7 +1116,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
 
        ret = extract_attr_from_ios(ios, &attrs[1]);
        if (ret) {
-               EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__);
+               EXOFS_ERR("%s: extract_attr 1 of inode failed\n", __func__);
                goto out;
        }
        if (attrs[1].len) {
@@ -1124,7 +1131,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
 
        ret = extract_attr_from_ios(ios, &attrs[2]);
        if (ret) {
-               EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__);
+               EXOFS_ERR("%s: extract_attr 2 of inode failed\n", __func__);
                goto out;
        }
        if (attrs[2].len) {
index b744228886043d522fa15a32ff98cc80d29db3c9..dae884694bd99cd82643a5427c4981ea05c9639b 100644 (file)
@@ -103,7 +103,7 @@ int ore_verify_layout(unsigned total_comps, struct ore_layout *layout)
 
        layout->max_io_length =
                (BIO_MAX_PAGES_KMALLOC * PAGE_SIZE - layout->stripe_unit) *
-                                                       layout->group_width;
+                                       (layout->group_width - layout->parity);
        if (layout->parity) {
                unsigned stripe_length =
                                (layout->group_width - layout->parity) *
@@ -286,7 +286,8 @@ int  ore_get_rw_state(struct ore_layout *layout, struct ore_components *oc,
        if (length) {
                ore_calc_stripe_info(layout, offset, length, &ios->si);
                ios->length = ios->si.length;
-               ios->nr_pages = (ios->length + PAGE_SIZE - 1) / PAGE_SIZE;
+               ios->nr_pages = ((ios->offset & (PAGE_SIZE - 1)) +
+                                ios->length + PAGE_SIZE - 1) / PAGE_SIZE;
                if (layout->parity)
                        _ore_post_alloc_raid_stuff(ios);
        }
@@ -430,8 +431,12 @@ int ore_check_io(struct ore_io_state *ios, ore_on_dev_error on_dev_error)
                if (likely(!ret))
                        continue;
 
-               if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
-                       /* start read offset passed endof file */
+               if ((OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) &&
+                   per_dev->bio) {
+                       /* start read offset passed endof file.
+                        * Note: if we do not have bio it means read-attributes
+                        * In this case we should return error to caller.
+                        */
                        _clear_bio(per_dev->bio);
                        ORE_DBGMSG("start read offset passed end of file "
                                "offset=0x%llx, length=0x%llx\n",
@@ -536,6 +541,7 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset,
        u64     H = LmodS - G * T;
 
        u32     N = div_u64(H, U);
+       u32     Nlast;
 
        /* "H - (N * U)" is just "H % U" so it's bound to u32 */
        u32     C = (u32)(H - (N * U)) / stripe_unit + G * group_width;
@@ -568,6 +574,10 @@ void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset,
        si->length = T - H;
        if (si->length > length)
                si->length = length;
+
+       Nlast = div_u64(H + si->length + U - 1, U);
+       si->maxdevUnits = Nlast - N;
+
        si->M = M;
 }
 EXPORT_SYMBOL(ore_calc_stripe_info);
@@ -583,13 +593,16 @@ int _ore_add_stripe_unit(struct ore_io_state *ios,  unsigned *cur_pg,
        int ret;
 
        if (per_dev->bio == NULL) {
-               unsigned pages_in_stripe = ios->layout->group_width *
-                                       (ios->layout->stripe_unit / PAGE_SIZE);
-               unsigned nr_pages = ios->nr_pages * ios->layout->group_width /
-                                       (ios->layout->group_width -
-                                        ios->layout->parity);
-               unsigned bio_size = (nr_pages + pages_in_stripe) /
-                                       ios->layout->group_width;
+               unsigned bio_size;
+
+               if (!ios->reading) {
+                       bio_size = ios->si.maxdevUnits;
+               } else {
+                       bio_size = (ios->si.maxdevUnits + 1) *
+                            (ios->layout->group_width - ios->layout->parity) /
+                            ios->layout->group_width;
+               }
+               bio_size *= (ios->layout->stripe_unit / PAGE_SIZE);
 
                per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
                if (unlikely(!per_dev->bio)) {
@@ -609,8 +622,12 @@ int _ore_add_stripe_unit(struct ore_io_state *ios,  unsigned *cur_pg,
                added_len = bio_add_pc_page(q, per_dev->bio, pages[pg],
                                            pglen, pgbase);
                if (unlikely(pglen != added_len)) {
-                       ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=%u\n",
-                                  per_dev->bio->bi_vcnt);
+                       /* If bi_vcnt == bi_max then this is a SW BUG */
+                       ORE_DBGMSG("Failed bio_add_pc_page bi_vcnt=0x%x "
+                                  "bi_max=0x%x BIO_MAX=0x%x cur_len=0x%x\n",
+                                  per_dev->bio->bi_vcnt,
+                                  per_dev->bio->bi_max_vecs,
+                                  BIO_MAX_PAGES_KMALLOC, cur_len);
                        ret = -ENOMEM;
                        goto out;
                }
@@ -1098,7 +1115,7 @@ int ore_truncate(struct ore_layout *layout, struct ore_components *oc,
                size_attr->attr = g_attr_logical_length;
                size_attr->attr.val_ptr = &size_attr->newsize;
 
-               ORE_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
+               ORE_DBGMSG2("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
                             _LLU(oc->comps->obj.id), _LLU(obj_size), i);
                ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
                                        &size_attr->attr);
index 110b6b371a4edc353fc1904bcc79299580087184..1b8001bbe94778ec09cfab5ecd8d08136d384a5a 100644 (file)
@@ -148,13 +148,6 @@ ext2_get_acl(struct inode *inode, int type)
        struct posix_acl *acl;
        int retval;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return NULL;
-
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -189,19 +182,14 @@ ext2_get_acl(struct inode *inode, int type)
 /*
  * inode->i_mutex: down
  */
-static int
-ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+int
+ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        int name_index;
        void *value = NULL;
        size_t size = 0;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return 0;
-
        switch(type) {
                case ACL_TYPE_ACCESS:
                        name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -250,169 +238,21 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 int
 ext2_init_acl(struct inode *inode, struct inode *dir)
 {
-       struct posix_acl *acl = NULL;
-       int error = 0;
-
-       if (!S_ISLNK(inode->i_mode)) {
-               if (test_opt(dir->i_sb, POSIX_ACL)) {
-                       acl = ext2_get_acl(dir, ACL_TYPE_DEFAULT);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
-       }
-       if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       error = ext2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
-                       if (error)
-                               goto cleanup;
-               }
-               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
-               if (error < 0)
-                       return error;
-               if (error > 0) {
-                       /* This is an extended ACL */
-                       error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
-               }
-       }
-cleanup:
-       posix_acl_release(acl);
-       return error;
-}
-
-/*
- * Does chmod for an inode that may have an Access Control List. The
- * inode->i_mode field must be updated to the desired value by the caller
- * before calling this function.
- * Returns 0 on success, or a negative error number.
- *
- * We change the ACL rather than storing some ACL entries in the file
- * mode permission bits (which would be more efficient), because that
- * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
- * for directories) are added. There are no more bits available in the
- * file mode.
- *
- * inode->i_mutex: down
- */
-int
-ext2_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-        int error;
+       struct posix_acl *default_acl, *acl;
+       int error;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return 0;
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-       error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
        if (error)
                return error;
-       error = ext2_set_acl(inode, ACL_TYPE_ACCESS, acl);
-       posix_acl_release(acl);
-       return error;
-}
 
-/*
- * Extended attribut handlers
- */
-static size_t
-ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size,
-                          const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_size)
-               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-       return size;
-}
-
-static size_t
-ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
-                           const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_size)
-               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-       return size;
-}
-
-static int
-ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
-                  size_t size, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       acl = ext2_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
-                  size_t size, int flags, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(dentry->d_inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               else if (acl) {
-                       error = posix_acl_valid(acl);
-                       if (error)
-                               goto release_and_out;
-               }
-       } else
-               acl = NULL;
-
-       error = ext2_set_acl(dentry->d_inode, type, acl);
-
-release_and_out:
-       posix_acl_release(acl);
+       if (default_acl) {
+               error = ext2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (!error)
+                       error = ext2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               posix_acl_release(acl);
+       }
        return error;
 }
-
-const struct xattr_handler ext2_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = ext2_xattr_list_acl_access,
-       .get    = ext2_xattr_get_acl,
-       .set    = ext2_xattr_set_acl,
-};
-
-const struct xattr_handler ext2_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = ext2_xattr_list_acl_default,
-       .get    = ext2_xattr_get_acl,
-       .set    = ext2_xattr_set_acl,
-};
index 503bfb0ed79b208365c50a0695243d55c43bca19..44937f9fcf327522bb65fe4d2463c1cb2f8bc3b8 100644 (file)
@@ -55,7 +55,7 @@ static inline int ext2_acl_count(size_t size)
 
 /* acl.c */
 extern struct posix_acl *ext2_get_acl(struct inode *inode, int type);
-extern int ext2_acl_chmod (struct inode *);
+extern int ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int ext2_init_acl (struct inode *, struct inode *);
 
 #else
@@ -63,12 +63,6 @@ extern int ext2_init_acl (struct inode *, struct inode *);
 #define ext2_get_acl   NULL
 #define ext2_set_acl   NULL
 
-static inline int
-ext2_acl_chmod (struct inode *inode)
-{
-       return 0;
-}
-
 static inline int ext2_init_acl (struct inode *inode, struct inode *dir)
 {
        return 0;
index a5b3a5db31206f8f3c84781362f7c45e919ddf0e..44c36e5907655982cc10e26b822cc1061312fbd1 100644 (file)
@@ -103,5 +103,6 @@ const struct inode_operations ext2_file_inode_operations = {
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
+       .set_acl        = ext2_set_acl,
        .fiemap         = ext2_fiemap,
 };
index 8a337640a46a06fec154fe9ae1fef1e054000c23..94ed36849b717bb83d3824527b9ae4f2f7d4b90a 100644 (file)
@@ -1566,7 +1566,7 @@ int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
        }
        setattr_copy(inode, iattr);
        if (iattr->ia_valid & ATTR_MODE)
-               error = ext2_acl_chmod(inode);
+               error = posix_acl_chmod(inode, inode->i_mode);
        mark_inode_dirty(inode);
 
        return error;
index 256dd5f4c1c4ade3f1ba160726ed0defabfccaf8..c268d0af1db93c5c9b3db0dd93dd6819d977b42e 100644 (file)
@@ -421,6 +421,7 @@ const struct inode_operations ext2_dir_inode_operations = {
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
+       .set_acl        = ext2_set_acl,
        .tmpfile        = ext2_tmpfile,
 };
 
@@ -433,4 +434,5 @@ const struct inode_operations ext2_special_inode_operations = {
 #endif
        .setattr        = ext2_setattr,
        .get_acl        = ext2_get_acl,
+       .set_acl        = ext2_set_acl,
 };
index 2d7557db3ae855b614b0c70d2803adafb0f64181..91426141c33a32a1bd37bb95fa2414da5bcbad92 100644 (file)
@@ -103,8 +103,8 @@ static struct mb_cache *ext2_xattr_cache;
 static const struct xattr_handler *ext2_xattr_handler_map[] = {
        [EXT2_XATTR_INDEX_USER]              = &ext2_xattr_user_handler,
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
-       [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext2_xattr_acl_access_handler,
-       [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext2_xattr_acl_default_handler,
+       [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler,
+       [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
 #endif
        [EXT2_XATTR_INDEX_TRUSTED]           = &ext2_xattr_trusted_handler,
 #ifdef CONFIG_EXT2_FS_SECURITY
@@ -116,8 +116,8 @@ const struct xattr_handler *ext2_xattr_handlers[] = {
        &ext2_xattr_user_handler,
        &ext2_xattr_trusted_handler,
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
-       &ext2_xattr_acl_access_handler,
-       &ext2_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
 #ifdef CONFIG_EXT2_FS_SECURITY
        &ext2_xattr_security_handler,
index 5e41cccff7622a212fec0a8f2a43fe7e38d8b2d9..60edf298644ea2ad9a45b960425392697cbdf373 100644 (file)
@@ -57,8 +57,6 @@ struct ext2_xattr_entry {
 
 extern const struct xattr_handler ext2_xattr_user_handler;
 extern const struct xattr_handler ext2_xattr_trusted_handler;
-extern const struct xattr_handler ext2_xattr_acl_access_handler;
-extern const struct xattr_handler ext2_xattr_acl_default_handler;
 extern const struct xattr_handler ext2_xattr_security_handler;
 
 extern ssize_t ext2_listxattr(struct dentry *, char *, size_t);
index dbb5ad59a7fc3c22380ce30b9034f8942bec967b..8bbaf5bcf9820c6d538298a0a5d6922a52f3d231 100644 (file)
@@ -145,13 +145,6 @@ ext3_get_acl(struct inode *inode, int type)
        struct posix_acl *acl;
        int retval;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return NULL;
-
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -190,7 +183,7 @@ ext3_get_acl(struct inode *inode, int type)
  * inode->i_mutex: down unless called from ext3_new_inode
  */
 static int
-ext3_set_acl(handle_t *handle, struct inode *inode, int type,
+__ext3_set_acl(handle_t *handle, struct inode *inode, int type,
             struct posix_acl *acl)
 {
        int name_index;
@@ -198,9 +191,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
        size_t size = 0;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch(type) {
                case ACL_TYPE_ACCESS:
                        name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -243,204 +233,49 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
        return error;
 }
 
-/*
- * Initialize the ACLs of a new inode. Called from ext3_new_inode.
- *
- * dir->i_mutex: down
- * inode->i_mutex: up (access to inode is still exclusive)
- */
 int
-ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       struct posix_acl *acl = NULL;
-       int error = 0;
-
-       if (!S_ISLNK(inode->i_mode)) {
-               if (test_opt(dir->i_sb, POSIX_ACL)) {
-                       acl = ext3_get_acl(dir, ACL_TYPE_DEFAULT);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
-       }
-       if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       error = ext3_set_acl(handle, inode,
-                                            ACL_TYPE_DEFAULT, acl);
-                       if (error)
-                               goto cleanup;
-               }
-               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
-               if (error < 0)
-                       return error;
-
-               if (error > 0) {
-                       /* This is an extended ACL */
-                       error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
-               }
-       }
-cleanup:
-       posix_acl_release(acl);
-       return error;
-}
-
-/*
- * Does chmod for an inode that may have an Access Control List. The
- * inode->i_mode field must be updated to the desired value by the caller
- * before calling this function.
- * Returns 0 on success, or a negative error number.
- *
- * We change the ACL rather than storing some ACL entries in the file
- * mode permission bits (which would be more efficient), because that
- * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
- * for directories) are added. There are no more bits available in the
- * file mode.
- *
- * inode->i_mutex: down
- */
-int
-ext3_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
        handle_t *handle;
-       int retries = 0;
-        int error;
+       int error, retries = 0;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return 0;
-       acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-       error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (error)
-               return error;
 retry:
-       handle = ext3_journal_start(inode,
-                       EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle)) {
-               error = PTR_ERR(handle);
-               ext3_std_error(inode->i_sb, error);
-               goto out;
-       }
-       error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+       handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       error = __ext3_set_acl(handle, inode, type, acl);
        ext3_journal_stop(handle);
-       if (error == -ENOSPC &&
-           ext3_should_retry_alloc(inode->i_sb, &retries))
+       if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
-out:
-       posix_acl_release(acl);
        return error;
 }
 
 /*
- * Extended attribute handlers
+ * Initialize the ACLs of a new inode. Called from ext3_new_inode.
+ *
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
  */
-static size_t
-ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
-                          const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-       return size;
-}
-
-static size_t
-ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
-                           const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-       return size;
-}
-
-static int
-ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
-                  size_t size, int type)
+int
+ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 {
-       struct posix_acl *acl;
+       struct posix_acl *default_acl, *acl;
        int error;
 
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       acl = ext3_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
-                  size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       handle_t *handle;
-       struct posix_acl *acl;
-       int error, retries = 0;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               else if (acl) {
-                       error = posix_acl_valid(acl);
-                       if (error)
-                               goto release_and_out;
-               }
-       } else
-               acl = NULL;
-
-retry:
-       handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
-       error = ext3_set_acl(handle, inode, type, acl);
-       ext3_journal_stop(handle);
-       if (error == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
-               goto retry;
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (error)
+               return error;
 
-release_and_out:
-       posix_acl_release(acl);
+       if (default_acl) {
+               error = __ext3_set_acl(handle, inode, ACL_TYPE_DEFAULT,
+                                      default_acl);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (!error)
+                       error = __ext3_set_acl(handle, inode, ACL_TYPE_ACCESS,
+                                              acl);
+               posix_acl_release(acl);
+       }
        return error;
 }
-
-const struct xattr_handler ext3_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = ext3_xattr_list_acl_access,
-       .get    = ext3_xattr_get_acl,
-       .set    = ext3_xattr_set_acl,
-};
-
-const struct xattr_handler ext3_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = ext3_xattr_list_acl_default,
-       .get    = ext3_xattr_get_acl,
-       .set    = ext3_xattr_set_acl,
-};
index dbc921e458c5599177fb86fc6e3fc95481cf06ab..ea1c69edab9e15dd1a9447f2be4a0e83650252c7 100644 (file)
@@ -55,18 +55,13 @@ static inline int ext3_acl_count(size_t size)
 
 /* acl.c */
 extern struct posix_acl *ext3_get_acl(struct inode *inode, int type);
-extern int ext3_acl_chmod (struct inode *);
+extern int ext3_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
 
 #else  /* CONFIG_EXT3_FS_POSIX_ACL */
 #include <linux/sched.h>
 #define ext3_get_acl NULL
-
-static inline int
-ext3_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
+#define ext3_set_acl NULL
 
 static inline int
 ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
index 25cb413277e906edb1f037ba625ece7aa92903bb..aad05311392a046f3df724102580c511185c0fa2 100644 (file)
@@ -75,6 +75,7 @@ const struct inode_operations ext3_file_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .get_acl        = ext3_get_acl,
+       .set_acl        = ext3_set_acl,
        .fiemap         = ext3_fiemap,
 };
 
index 2bd85486b87974b390892a2280676a49d8eb274e..384b6ebb655f1aefa21e53b6b28f6598c40db1b2 100644 (file)
@@ -3365,7 +3365,7 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
        mark_inode_dirty(inode);
 
        if (ia_valid & ATTR_MODE)
-               rc = ext3_acl_chmod(inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
 
 err_out:
        ext3_std_error(inode->i_sb, error);
index f8cde46de9cd77c3047182e94164bdfdac4a317d..f197736dccfa16cca207fecb81e6445a18e96973 100644 (file)
@@ -2569,6 +2569,7 @@ const struct inode_operations ext3_dir_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .get_acl        = ext3_get_acl,
+       .set_acl        = ext3_set_acl,
 };
 
 const struct inode_operations ext3_special_inode_operations = {
@@ -2580,4 +2581,5 @@ const struct inode_operations ext3_special_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .get_acl        = ext3_get_acl,
+       .set_acl        = ext3_set_acl,
 };
index b1fc96383e087157879e853b2affbf0cb87982ec..c6874be6d58b41f02bcaa3b93cf182845bd85bec 100644 (file)
@@ -102,8 +102,8 @@ static struct mb_cache *ext3_xattr_cache;
 static const struct xattr_handler *ext3_xattr_handler_map[] = {
        [EXT3_XATTR_INDEX_USER]              = &ext3_xattr_user_handler,
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-       [EXT3_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext3_xattr_acl_access_handler,
-       [EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext3_xattr_acl_default_handler,
+       [EXT3_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler,
+       [EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
 #endif
        [EXT3_XATTR_INDEX_TRUSTED]           = &ext3_xattr_trusted_handler,
 #ifdef CONFIG_EXT3_FS_SECURITY
@@ -115,8 +115,8 @@ const struct xattr_handler *ext3_xattr_handlers[] = {
        &ext3_xattr_user_handler,
        &ext3_xattr_trusted_handler,
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-       &ext3_xattr_acl_access_handler,
-       &ext3_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
 #ifdef CONFIG_EXT3_FS_SECURITY
        &ext3_xattr_security_handler,
index 2be4f69bfa64b301d437e5130868f433a01d5f50..32e93ebf80315bed89dd5e919202a4de2d2f4de3 100644 (file)
@@ -60,8 +60,6 @@ struct ext3_xattr_entry {
 
 extern const struct xattr_handler ext3_xattr_user_handler;
 extern const struct xattr_handler ext3_xattr_trusted_handler;
-extern const struct xattr_handler ext3_xattr_acl_access_handler;
-extern const struct xattr_handler ext3_xattr_acl_default_handler;
 extern const struct xattr_handler ext3_xattr_security_handler;
 
 extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
index 39a54a0e9fe4a9a6290f75b961cde9ccea06f669..d40c8dbbb0d66a3622915c68dc104841ab1f5753 100644 (file)
@@ -152,13 +152,6 @@ ext4_get_acl(struct inode *inode, int type)
        struct posix_acl *acl;
        int retval;
 
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return NULL;
-
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -196,7 +189,7 @@ ext4_get_acl(struct inode *inode, int type)
  * inode->i_mutex: down unless called from ext4_new_inode
  */
 static int
-ext4_set_acl(handle_t *handle, struct inode *inode, int type,
+__ext4_set_acl(handle_t *handle, struct inode *inode, int type,
             struct posix_acl *acl)
 {
        int name_index;
@@ -204,9 +197,6 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
        size_t size = 0;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -248,208 +238,51 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type,
        return error;
 }
 
-/*
- * Initialize the ACLs of a new inode. Called from ext4_new_inode.
- *
- * dir->i_mutex: down
- * inode->i_mutex: up (access to inode is still exclusive)
- */
 int
-ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
+ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       struct posix_acl *acl = NULL;
-       int error = 0;
-
-       if (!S_ISLNK(inode->i_mode)) {
-               if (test_opt(dir->i_sb, POSIX_ACL)) {
-                       acl = ext4_get_acl(dir, ACL_TYPE_DEFAULT);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
-       }
-       if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       error = ext4_set_acl(handle, inode,
-                                            ACL_TYPE_DEFAULT, acl);
-                       if (error)
-                               goto cleanup;
-               }
-               error = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
-               if (error < 0)
-                       return error;
-
-               if (error > 0) {
-                       /* This is an extended ACL */
-                       error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
-               }
-       }
-cleanup:
-       posix_acl_release(acl);
-       return error;
-}
-
-/*
- * Does chmod for an inode that may have an Access Control List. The
- * inode->i_mode field must be updated to the desired value by the caller
- * before calling this function.
- * Returns 0 on success, or a negative error number.
- *
- * We change the ACL rather than storing some ACL entries in the file
- * mode permission bits (which would be more efficient), because that
- * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
- * for directories) are added. There are no more bits available in the
- * file mode.
- *
- * inode->i_mutex: down
- */
-int
-ext4_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
        handle_t *handle;
-       int retries = 0;
-       int error;
-
+       int error, retries = 0;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return 0;
-       acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-       error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (error)
-               return error;
 retry:
        handle = ext4_journal_start(inode, EXT4_HT_XATTR,
                                    ext4_jbd2_credits_xattr(inode));
-       if (IS_ERR(handle)) {
-               error = PTR_ERR(handle);
-               ext4_std_error(inode->i_sb, error);
-               goto out;
-       }
-       error = ext4_set_acl(handle, inode, ACL_TYPE_ACCESS, acl);
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+
+       error = __ext4_set_acl(handle, inode, type, acl);
        ext4_journal_stop(handle);
-       if (error == -ENOSPC &&
-           ext4_should_retry_alloc(inode->i_sb, &retries))
+       if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
-out:
-       posix_acl_release(acl);
        return error;
 }
 
 /*
- * Extended attribute handlers
+ * Initialize the ACLs of a new inode. Called from ext4_new_inode.
+ *
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
  */
-static size_t
-ext4_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
-                          const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-       return size;
-}
-
-static size_t
-ext4_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
-                           const char *name, size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return 0;
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-       return size;
-}
-
-static int
-ext4_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
-                  size_t size, int type)
+int
+ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
 {
-       struct posix_acl *acl;
+       struct posix_acl *default_acl, *acl;
        int error;
 
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(dentry->d_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       acl = ext4_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
-                  size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       handle_t *handle;
-       struct posix_acl *acl;
-       int error, retries = 0;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(inode->i_sb, POSIX_ACL))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               else if (acl) {
-                       error = posix_acl_valid(acl);
-                       if (error)
-                               goto release_and_out;
-               }
-       } else
-               acl = NULL;
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (error)
+               return error;
 
-retry:
-       handle = ext4_journal_start(inode, EXT4_HT_XATTR,
-                                   ext4_jbd2_credits_xattr(inode));
-       if (IS_ERR(handle)) {
-               error = PTR_ERR(handle);
-               goto release_and_out;
+       if (default_acl) {
+               error = __ext4_set_acl(handle, inode, ACL_TYPE_DEFAULT,
+                                      default_acl);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (!error)
+                       error = __ext4_set_acl(handle, inode, ACL_TYPE_ACCESS,
+                                              acl);
+               posix_acl_release(acl);
        }
-       error = ext4_set_acl(handle, inode, type, acl);
-       ext4_journal_stop(handle);
-       if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
-               goto retry;
-
-release_and_out:
-       posix_acl_release(acl);
        return error;
 }
-
-const struct xattr_handler ext4_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = ext4_xattr_list_acl_access,
-       .get    = ext4_xattr_get_acl,
-       .set    = ext4_xattr_set_acl,
-};
-
-const struct xattr_handler ext4_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = ext4_xattr_list_acl_default,
-       .get    = ext4_xattr_get_acl,
-       .set    = ext4_xattr_set_acl,
-};
index 18cb39ed7c7bbb88dfb72f67150b40cf859e2a58..da2c79577d724ae14e7fbf3b5adb4cb3e2848e5d 100644 (file)
@@ -55,18 +55,13 @@ static inline int ext4_acl_count(size_t size)
 
 /* acl.c */
 struct posix_acl *ext4_get_acl(struct inode *inode, int type);
-extern int ext4_acl_chmod(struct inode *);
+int ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
 
 #else  /* CONFIG_EXT4_FS_POSIX_ACL */
 #include <linux/sched.h>
 #define ext4_get_acl NULL
-
-static inline int
-ext4_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
+#define ext4_set_acl NULL
 
 static inline int
 ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
index 3384dc4bed4034921beffb84783327024e4cf22e..10cff4736b116185f9d0a2cea73dca9423c6fb92 100644 (file)
@@ -3477,7 +3477,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        WARN_ON(map->m_lblk < ee_block);
        /*
         * It is safe to convert extent to initialized via explicit
-        * zeroout only if extent is fully insde i_size or new_size.
+        * zeroout only if extent is fully inside i_size or new_size.
         */
        split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
 
index 3da21945ff1fff3e16b8b70b332a0a6ee330c93e..43e64f6022eb4af22e7ac95eb6aaa34e7e6735a9 100644 (file)
@@ -617,6 +617,7 @@ const struct inode_operations ext4_file_inode_operations = {
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
+       .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
 };
 
index bae987549dc367736eaf0beeedb29e8e514e46e6..82edf5b9335277b8f508be2105b6944a9d57ce5c 100644 (file)
@@ -849,15 +849,16 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        handle_t *handle;
        struct page *page;
        struct ext4_iloc iloc;
+       int retries;
 
        ret = ext4_get_inode_loc(inode, &iloc);
        if (ret)
                return ret;
 
+retry_journal:
        handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
-               handle = NULL;
                goto out;
        }
 
@@ -867,7 +868,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        if (inline_size >= pos + len) {
                ret = ext4_prepare_inline_data(handle, inode, pos + len);
                if (ret && ret != -ENOSPC)
-                       goto out;
+                       goto out_journal;
        }
 
        if (ret == -ENOSPC) {
@@ -875,6 +876,10 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
                                                            inode,
                                                            flags,
                                                            fsdata);
+               ext4_journal_stop(handle);
+               if (ret == -ENOSPC &&
+                   ext4_should_retry_alloc(inode->i_sb, &retries))
+                       goto retry_journal;
                goto out;
        }
 
@@ -887,7 +892,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
        page = grab_cache_page_write_begin(mapping, 0, flags);
        if (!page) {
                ret = -ENOMEM;
-               goto out;
+               goto out_journal;
        }
 
        down_read(&EXT4_I(inode)->xattr_sem);
@@ -904,16 +909,15 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
 
        up_read(&EXT4_I(inode)->xattr_sem);
        *pagep = page;
-       handle = NULL;
        brelse(iloc.bh);
        return 1;
 out_release_page:
        up_read(&EXT4_I(inode)->xattr_sem);
        unlock_page(page);
        page_cache_release(page);
+out_journal:
+       ext4_journal_stop(handle);
 out:
-       if (handle)
-               ext4_journal_stop(handle);
        brelse(iloc.bh);
        return ret;
 }
@@ -1837,7 +1841,6 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
 {
        int error;
        struct ext4_xattr_entry *entry;
-       struct ext4_xattr_ibody_header *header;
        struct ext4_inode *raw_inode;
        struct ext4_iloc iloc;
 
@@ -1846,7 +1849,6 @@ int ext4_try_to_evict_inline_data(handle_t *handle,
                return error;
 
        raw_inode = ext4_raw_inode(&iloc);
-       header = IHDR(inode, raw_inode);
        entry = (struct ext4_xattr_entry *)((void *)raw_inode +
                                            EXT4_I(inode)->i_inline_off);
        if (EXT4_XATTR_LEN(entry->e_name_len) +
@@ -1924,9 +1926,11 @@ void ext4_inline_data_truncate(struct inode *inode, int *has_inline)
                }
 
                /* Clear the content within i_blocks. */
-               if (i_size < EXT4_MIN_INLINE_DATA_SIZE)
-                       memset(ext4_raw_inode(&is.iloc)->i_block + i_size, 0,
-                                       EXT4_MIN_INLINE_DATA_SIZE - i_size);
+               if (i_size < EXT4_MIN_INLINE_DATA_SIZE) {
+                       void *p = (void *) ext4_raw_inode(&is.iloc)->i_block;
+                       memset(p + i_size, 0,
+                              EXT4_MIN_INLINE_DATA_SIZE - i_size);
+               }
 
                EXT4_I(inode)->i_inline_size = i_size <
                                        EXT4_MIN_INLINE_DATA_SIZE ?
index 31fa964742bcba1b0f9dbd494e469feb56ee8428..6e39895a91b80aaae3914cc3a51756b3fa48a4c8 100644 (file)
@@ -144,8 +144,8 @@ static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
  */
 static int ext4_inode_is_fast_symlink(struct inode *inode)
 {
-       int ea_blocks = EXT4_I(inode)->i_file_acl ?
-               (inode->i_sb->s_blocksize >> 9) : 0;
+        int ea_blocks = EXT4_I(inode)->i_file_acl ?
+               EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0;
 
        return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
 }
@@ -1772,7 +1772,7 @@ static int __ext4_journalled_writepage(struct page *page,
                ret = err;
 
        if (!ext4_has_inline_data(inode))
-               ext4_walk_page_buffers(handle, page_bufs, 0, len,
+               ext4_walk_page_buffers(NULL, page_bufs, 0, len,
                                       NULL, bput_one);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 out:
@@ -3501,11 +3501,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
        if (!S_ISREG(inode->i_mode))
                return -EOPNOTSUPP;
 
-       if (EXT4_SB(sb)->s_cluster_ratio > 1) {
-               /* TODO: Add support for bigalloc file systems */
-               return -EOPNOTSUPP;
-       }
-
        trace_ext4_punch_hole(inode, offset, length);
 
        /*
@@ -4667,7 +4662,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                ext4_orphan_del(NULL, inode);
 
        if (!rc && (ia_valid & ATTR_MODE))
-               rc = ext4_acl_chmod(inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
 
 err_out:
        ext4_std_error(inode->i_sb, error);
index 60589b60e9b04936cb2d27c9615b2b8caee246fb..6bea80614d77c19c6ca7b1ac9160d64f1115b36e 100644 (file)
@@ -101,9 +101,8 @@ static long swap_inode_boot_loader(struct super_block *sb,
        handle_t *handle;
        int err;
        struct inode *inode_bl;
-       struct ext4_inode_info *ei;
        struct ext4_inode_info *ei_bl;
-       struct ext4_sb_info *sbi;
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
 
        if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) {
                err = -EINVAL;
@@ -115,9 +114,6 @@ static long swap_inode_boot_loader(struct super_block *sb,
                goto swap_boot_out;
        }
 
-       sbi = EXT4_SB(sb);
-       ei = EXT4_I(inode);
-
        inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
        if (IS_ERR(inode_bl)) {
                err = PTR_ERR(inode_bl);
index 5a0408d7b1147094c3e82b6d11750b33396b7732..d050e043e884c19120c8062a2ab2991ba71a9a86 100644 (file)
@@ -1425,9 +1425,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                        return ERR_PTR(-EIO);
                }
                if (unlikely(ino == dir->i_ino)) {
-                       EXT4_ERROR_INODE(dir, "'%.*s' linked to parent dir",
-                                        dentry->d_name.len,
-                                        dentry->d_name.name);
+                       EXT4_ERROR_INODE(dir, "'%pd' linked to parent dir",
+                                        dentry);
                        return ERR_PTR(-EIO);
                }
                inode = ext4_iget(dir->i_sb, ino);
@@ -3225,6 +3224,7 @@ const struct inode_operations ext4_dir_inode_operations = {
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
+       .set_acl        = ext4_set_acl,
        .fiemap         = ext4_fiemap,
 };
 
@@ -3235,4 +3235,5 @@ const struct inode_operations ext4_special_inode_operations = {
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
        .get_acl        = ext4_get_acl,
+       .set_acl        = ext4_set_acl,
 };
index 1423c4816a4783da4208b6d51fc33815b25597f4..e175e94116acefdc7685896e5c8744f7bd677dc4 100644 (file)
@@ -95,8 +95,8 @@ static struct mb_cache *ext4_xattr_cache;
 static const struct xattr_handler *ext4_xattr_handler_map[] = {
        [EXT4_XATTR_INDEX_USER]              = &ext4_xattr_user_handler,
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
-       [EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext4_xattr_acl_access_handler,
-       [EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext4_xattr_acl_default_handler,
+       [EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler,
+       [EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
 #endif
        [EXT4_XATTR_INDEX_TRUSTED]           = &ext4_xattr_trusted_handler,
 #ifdef CONFIG_EXT4_FS_SECURITY
@@ -108,8 +108,8 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
        &ext4_xattr_user_handler,
        &ext4_xattr_trusted_handler,
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
-       &ext4_xattr_acl_access_handler,
-       &ext4_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
 #ifdef CONFIG_EXT4_FS_SECURITY
        &ext4_xattr_security_handler,
index c767dbdd7fc495e5a4fd4a5c581455db73c5c1c3..819d6398833f9d98ea7a9e78552381f63f7b83fd 100644 (file)
@@ -96,8 +96,6 @@ struct ext4_xattr_ibody_find {
 
 extern const struct xattr_handler ext4_xattr_user_handler;
 extern const struct xattr_handler ext4_xattr_trusted_handler;
-extern const struct xattr_handler ext4_xattr_acl_access_handler;
-extern const struct xattr_handler ext4_xattr_acl_default_handler;
 extern const struct xattr_handler ext4_xattr_security_handler;
 
 extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
index d0fc287efeff4511fa7f4e84369cf77f0ae31538..fa8da4cb8c4b9a3aa647f2a4f51467fc86549fc5 100644 (file)
@@ -17,9 +17,6 @@
 #include "xattr.h"
 #include "acl.h"
 
-#define get_inode_mode(i)      ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
-                                       (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
-
 static inline size_t f2fs_acl_size(int count)
 {
        if (count <= 4) {
@@ -167,19 +164,11 @@ fail:
 
 struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
        void *value = NULL;
        struct posix_acl *acl;
        int retval;
 
-       if (!test_opt(sbi, POSIX_ACL))
-               return NULL;
-
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        if (type == ACL_TYPE_ACCESS)
                name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
 
@@ -205,21 +194,15 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int f2fs_set_acl(struct inode *inode, int type,
+static int __f2fs_set_acl(struct inode *inode, int type,
                        struct posix_acl *acl, struct page *ipage)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        struct f2fs_inode_info *fi = F2FS_I(inode);
        int name_index;
        void *value = NULL;
        size_t size = 0;
        int error;
 
-       if (!test_opt(sbi, POSIX_ACL))
-               return 0;
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
@@ -261,154 +244,31 @@ static int f2fs_set_acl(struct inode *inode, int type,
        return error;
 }
 
-int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage)
+int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
-       struct posix_acl *acl = NULL;
-       int error = 0;
-
-       if (!S_ISLNK(inode->i_mode)) {
-               if (test_opt(sbi, POSIX_ACL)) {
-                       acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
-               if (!acl)
-                       inode->i_mode &= ~current_umask();
-       }
-
-       if (!test_opt(sbi, POSIX_ACL) || !acl)
-               goto cleanup;
-
-       if (S_ISDIR(inode->i_mode)) {
-               error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage);
-               if (error)
-                       goto cleanup;
-       }
-       error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
-       if (error < 0)
-               return error;
-       if (error > 0)
-               error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage);
-cleanup:
-       posix_acl_release(acl);
-       return error;
+       return __f2fs_set_acl(inode, type, acl, NULL);
 }
 
-int f2fs_acl_chmod(struct inode *inode)
+int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-       struct posix_acl *acl;
-       int error;
-       umode_t mode = get_inode_mode(inode);
-
-       if (!test_opt(sbi, POSIX_ACL))
-               return 0;
-       if (S_ISLNK(mode))
-               return -EOPNOTSUPP;
-
-       acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
+       struct posix_acl *default_acl, *acl;
+       int error = 0;
 
-       error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
        if (error)
                return error;
 
-       error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, NULL);
-       posix_acl_release(acl);
-       return error;
-}
-
-static size_t f2fs_xattr_list_acl(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       const char *xname = POSIX_ACL_XATTR_DEFAULT;
-       size_t size;
-
-       if (!test_opt(sbi, POSIX_ACL))
-               return 0;
-
-       if (type == ACL_TYPE_ACCESS)
-               xname = POSIX_ACL_XATTR_ACCESS;
-
-       size = strlen(xname) + 1;
-       if (list && size <= list_size)
-               memcpy(list, xname, size);
-       return size;
-}
-
-static int f2fs_xattr_get_acl(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
-{
-       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       struct posix_acl *acl;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(sbi, POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       acl = f2fs_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (!acl)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
-{
-       struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl = NULL;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!test_opt(sbi, POSIX_ACL))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               if (acl) {
-                       error = posix_acl_valid(acl);
-                       if (error)
-                               goto release_and_out;
-               }
-       } else {
-               acl = NULL;
+       if (default_acl) {
+               error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
+                                      ipage);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (error)
+                       error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl,
+                                              ipage);
+               posix_acl_release(acl);
        }
 
-       error = f2fs_set_acl(inode, type, acl, NULL);
-
-release_and_out:
-       posix_acl_release(acl);
        return error;
 }
-
-const struct xattr_handler f2fs_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags = ACL_TYPE_DEFAULT,
-       .list = f2fs_xattr_list_acl,
-       .get = f2fs_xattr_get_acl,
-       .set = f2fs_xattr_set_acl,
-};
-
-const struct xattr_handler f2fs_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags = ACL_TYPE_ACCESS,
-       .list = f2fs_xattr_list_acl,
-       .get = f2fs_xattr_get_acl,
-       .set = f2fs_xattr_set_acl,
-};
index 49633131e038db76e14d21803538f1701a93d873..e0864651cdc1c09661e9d28c094c79c12603846f 100644 (file)
@@ -37,18 +37,13 @@ struct f2fs_acl_header {
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
 
 extern struct posix_acl *f2fs_get_acl(struct inode *, int);
-extern int f2fs_acl_chmod(struct inode *);
+extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int f2fs_init_acl(struct inode *, struct inode *, struct page *);
 #else
 #define f2fs_check_acl NULL
 #define f2fs_get_acl   NULL
 #define f2fs_set_acl   NULL
 
-static inline int f2fs_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
-
 static inline int f2fs_init_acl(struct inode *inode, struct inode *dir,
                                                        struct page *page)
 {
index af51a0bd2dee4c267e715d8d39c38b917b115743..fc3c558cb4f3d5a71b8ed03016e838cf5ec84cdf 100644 (file)
@@ -1023,6 +1023,10 @@ static inline int f2fs_readonly(struct super_block *sb)
        return sb->s_flags & MS_RDONLY;
 }
 
+#define get_inode_mode(i) \
+       ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+        (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
+
 /*
  * file.c
  */
index 85e91ca88d5791835d25dffe6fc0932f9640203b..0dfcef53a6ed830e442f8c174ea166b0d1b2eabd 100644 (file)
@@ -382,7 +382,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
        __setattr_copy(inode, attr);
 
        if (attr->ia_valid & ATTR_MODE) {
-               err = f2fs_acl_chmod(inode);
+               err = posix_acl_chmod(inode, get_inode_mode(inode));
                if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
                        inode->i_mode = fi->i_acl_mode;
                        clear_inode_flag(fi, FI_ACL_MODE);
@@ -397,6 +397,7 @@ const struct inode_operations f2fs_file_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
index 3d32f2969c5e047f54ffe9aec4b73dc132d9a8ca..397d459e97bf9f1ee2107c1079f02a282a47e5fa 100644 (file)
@@ -501,6 +501,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@ -527,6 +528,7 @@ const struct inode_operations f2fs_special_inode_operations = {
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
 #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
index b0fb8a27f3da6fe3b810eca732361953aeebc030..89d0422a91a88fea51ecf5935d31c2920545f8a6 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/rwsem.h>
 #include <linux/f2fs_fs.h>
 #include <linux/security.h>
+#include <linux/posix_acl_xattr.h>
 #include "f2fs.h"
 #include "xattr.h"
 
@@ -216,8 +217,8 @@ const struct xattr_handler f2fs_xattr_security_handler = {
 static const struct xattr_handler *f2fs_xattr_handler_map[] = {
        [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
-       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
-       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
 #endif
        [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
 #ifdef CONFIG_F2FS_FS_SECURITY
@@ -229,8 +230,8 @@ static const struct xattr_handler *f2fs_xattr_handler_map[] = {
 const struct xattr_handler *f2fs_xattr_handlers[] = {
        &f2fs_xattr_user_handler,
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
-       &f2fs_xattr_acl_access_handler,
-       &f2fs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        &f2fs_xattr_trusted_handler,
 #ifdef CONFIG_F2FS_FS_SECURITY
index 02a08fb88a151c9b38a4e5aabc78decb2f0b4101..b21d9ebdeff39efdf64485116bf53ce17263bb7e 100644 (file)
@@ -108,8 +108,6 @@ struct f2fs_xattr_entry {
 #ifdef CONFIG_F2FS_FS_XATTR
 extern const struct xattr_handler f2fs_xattr_user_handler;
 extern const struct xattr_handler f2fs_xattr_trusted_handler;
-extern const struct xattr_handler f2fs_xattr_acl_access_handler;
-extern const struct xattr_handler f2fs_xattr_acl_default_handler;
 extern const struct xattr_handler f2fs_xattr_advise_handler;
 extern const struct xattr_handler f2fs_xattr_security_handler;
 
index 4a78f981557a4b012919458993506f61fd5187a4..771578b33fb6c7fee9a7c28d01138e4670e07e59 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -348,21 +348,16 @@ out:
        return NULL;
 }
 
-static void close_files(struct files_struct * files)
+static struct fdtable *close_files(struct files_struct * files)
 {
-       int i, j;
-       struct fdtable *fdt;
-
-       j = 0;
-
        /*
         * It is safe to dereference the fd table without RCU or
         * ->file_lock because this is the last reference to the
-        * files structure.  But use RCU to shut RCU-lockdep up.
+        * files structure.
         */
-       rcu_read_lock();
-       fdt = files_fdtable(files);
-       rcu_read_unlock();
+       struct fdtable *fdt = rcu_dereference_raw(files->fdt);
+       int i, j = 0;
+
        for (;;) {
                unsigned long set;
                i = j * BITS_PER_LONG;
@@ -381,6 +376,8 @@ static void close_files(struct files_struct * files)
                        set >>= 1;
                }
        }
+
+       return fdt;
 }
 
 struct files_struct *get_files_struct(struct task_struct *task)
@@ -398,14 +395,9 @@ struct files_struct *get_files_struct(struct task_struct *task)
 
 void put_files_struct(struct files_struct *files)
 {
-       struct fdtable *fdt;
-
        if (atomic_dec_and_test(&files->count)) {
-               close_files(files);
-               /* not really needed, since nobody can see us */
-               rcu_read_lock();
-               fdt = files_fdtable(files);
-               rcu_read_unlock();
+               struct fdtable *fdt = close_files(files);
+
                /* free the arrays if they are not embedded */
                if (fdt != &files->fdtab)
                        __free_fdtable(fdt);
@@ -645,16 +637,16 @@ void do_close_on_exec(struct files_struct *files)
        spin_unlock(&files->file_lock);
 }
 
-struct file *fget(unsigned int fd)
+static struct file *__fget(unsigned int fd, fmode_t mask)
 {
-       struct file *file;
        struct files_struct *files = current->files;
+       struct file *file;
 
        rcu_read_lock();
        file = fcheck_files(files, fd);
        if (file) {
                /* File object ref couldn't be taken */
-               if (file->f_mode & FMODE_PATH ||
+               if ((file->f_mode & mask) ||
                    !atomic_long_inc_not_zero(&file->f_count))
                        file = NULL;
        }
@@ -663,25 +655,16 @@ struct file *fget(unsigned int fd)
        return file;
 }
 
+struct file *fget(unsigned int fd)
+{
+       return __fget(fd, FMODE_PATH);
+}
 EXPORT_SYMBOL(fget);
 
 struct file *fget_raw(unsigned int fd)
 {
-       struct file *file;
-       struct files_struct *files = current->files;
-
-       rcu_read_lock();
-       file = fcheck_files(files, fd);
-       if (file) {
-               /* File object ref couldn't be taken */
-               if (!atomic_long_inc_not_zero(&file->f_count))
-                       file = NULL;
-       }
-       rcu_read_unlock();
-
-       return file;
+       return __fget(fd, 0);
 }
-
 EXPORT_SYMBOL(fget_raw);
 
 /*
@@ -700,56 +683,33 @@ EXPORT_SYMBOL(fget_raw);
  * The fput_needed flag returned by fget_light should be passed to the
  * corresponding fput_light.
  */
-struct file *fget_light(unsigned int fd, int *fput_needed)
+struct file *__fget_light(unsigned int fd, fmode_t mask, int *fput_needed)
 {
-       struct file *file;
        struct files_struct *files = current->files;
+       struct file *file;
 
        *fput_needed = 0;
        if (atomic_read(&files->count) == 1) {
-               file = fcheck_files(files, fd);
-               if (file && (file->f_mode & FMODE_PATH))
+               file = __fcheck_files(files, fd);
+               if (file && (file->f_mode & mask))
                        file = NULL;
        } else {
-               rcu_read_lock();
-               file = fcheck_files(files, fd);
-               if (file) {
-                       if (!(file->f_mode & FMODE_PATH) &&
-                           atomic_long_inc_not_zero(&file->f_count))
-                               *fput_needed = 1;
-                       else
-                               /* Didn't get the reference, someone's freed */
-                               file = NULL;
-               }
-               rcu_read_unlock();
+               file = __fget(fd, mask);
+               if (file)
+                       *fput_needed = 1;
        }
 
        return file;
 }
+struct file *fget_light(unsigned int fd, int *fput_needed)
+{
+       return __fget_light(fd, FMODE_PATH, fput_needed);
+}
 EXPORT_SYMBOL(fget_light);
 
 struct file *fget_raw_light(unsigned int fd, int *fput_needed)
 {
-       struct file *file;
-       struct files_struct *files = current->files;
-
-       *fput_needed = 0;
-       if (atomic_read(&files->count) == 1) {
-               file = fcheck_files(files, fd);
-       } else {
-               rcu_read_lock();
-               file = fcheck_files(files, fd);
-               if (file) {
-                       if (atomic_long_inc_not_zero(&file->f_count))
-                               *fput_needed = 1;
-                       else
-                               /* Didn't get the reference, someone's freed */
-                               file = NULL;
-               }
-               rcu_read_unlock();
-       }
-
-       return file;
+       return __fget_light(fd, 0, fput_needed);
 }
 
 void set_close_on_exec(unsigned int fd, int flag)
index 74f6ca50050447832b4fbe41d8ee2f2a8bf4fa1f..77bcc303c3aeb9214ba4b13098da14fb8bcbe20b 100644 (file)
@@ -2727,6 +2727,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        inode = file->f_mapping->host;
        i_size = i_size_read(inode);
 
+       if ((rw == READ) && (offset > i_size))
+               return 0;
+
        /* optimization for short read */
        if (async_dio && rw != WRITE && offset + count > i_size) {
                if (offset >= i_size)
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
deleted file mode 100644 (file)
index b3f3676..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
- *
- * This file is released under the GPL.
- *
- * Generic ACL support for in-memory filesystems.
- */
-
-#include <linux/sched.h>
-#include <linux/gfp.h>
-#include <linux/fs.h>
-#include <linux/generic_acl.h>
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
-
-
-static size_t
-generic_acl_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
-{
-       struct posix_acl *acl;
-       const char *xname;
-       size_t size;
-
-       acl = get_cached_acl(dentry->d_inode, type);
-       if (!acl)
-               return 0;
-       posix_acl_release(acl);
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               xname = POSIX_ACL_XATTR_ACCESS;
-               break;
-       case ACL_TYPE_DEFAULT:
-               xname = POSIX_ACL_XATTR_DEFAULT;
-               break;
-       default:
-               return 0;
-       }
-       size = strlen(xname) + 1;
-       if (list && size <= list_size)
-               memcpy(list, xname, size);
-       return size;
-}
-
-static int
-generic_acl_get(struct dentry *dentry, const char *name, void *buffer,
-                    size_t size, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-
-       acl = get_cached_acl(dentry->d_inode, type);
-       if (!acl)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-generic_acl_set(struct dentry *dentry, const char *name, const void *value,
-                    size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl = NULL;
-       int error;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-       }
-       if (acl) {
-               error = posix_acl_valid(acl);
-               if (error)
-                       goto failed;
-               switch (type) {
-               case ACL_TYPE_ACCESS:
-                       error = posix_acl_equiv_mode(acl, &inode->i_mode);
-                       if (error < 0)
-                               goto failed;
-                       inode->i_ctime = CURRENT_TIME;
-                       if (error == 0) {
-                               posix_acl_release(acl);
-                               acl = NULL;
-                       }
-                       break;
-               case ACL_TYPE_DEFAULT:
-                       if (!S_ISDIR(inode->i_mode)) {
-                               error = -EINVAL;
-                               goto failed;
-                       }
-                       break;
-               }
-       }
-       set_cached_acl(inode, type, acl);
-       error = 0;
-failed:
-       posix_acl_release(acl);
-       return error;
-}
-
-/**
- * generic_acl_init  -  Take care of acl inheritance at @inode create time
- *
- * Files created inside a directory with a default ACL inherit the
- * directory's default ACL.
- */
-int
-generic_acl_init(struct inode *inode, struct inode *dir)
-{
-       struct posix_acl *acl = NULL;
-       int error;
-
-       if (!S_ISLNK(inode->i_mode))
-               acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
-       if (acl) {
-               if (S_ISDIR(inode->i_mode))
-                       set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
-               error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
-               if (error < 0)
-                       return error;
-               if (error > 0)
-                       set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
-       } else {
-               inode->i_mode &= ~current_umask();
-       }
-       error = 0;
-
-       posix_acl_release(acl);
-       return error;
-}
-
-/**
- * generic_acl_chmod  -  change the access acl of @inode upon chmod()
- *
- * A chmod also changes the permissions of the owner, group/mask, and
- * other ACL entries.
- */
-int
-generic_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int error = 0;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
-       if (acl) {
-               error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-               if (error)
-                       return error;
-               set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
-               posix_acl_release(acl);
-       }
-       return error;
-}
-
-const struct xattr_handler generic_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = generic_acl_list,
-       .get    = generic_acl_get,
-       .set    = generic_acl_set,
-};
-
-const struct xattr_handler generic_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = generic_acl_list,
-       .get    = generic_acl_get,
-       .set    = generic_acl_set,
-};
index f69ac0af5496cd456bf6df4d0c932747b6767779..ba9456685f47d761d51afae92a55328e2d54d78a 100644 (file)
@@ -49,10 +49,6 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
        if (!ip->i_eattr)
                return NULL;
 
-       acl = get_cached_acl(&ip->i_inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        name = gfs2_acl_name(type);
        if (name == NULL)
                return ERR_PTR(-EINVAL);
@@ -80,7 +76,7 @@ static int gfs2_set_mode(struct inode *inode, umode_t mode)
        return error;
 }
 
-static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
+int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        int error;
        int len;
@@ -88,219 +84,49 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
        const char *name = gfs2_acl_name(type);
 
        BUG_ON(name == NULL);
-       len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
-       if (len == 0)
-               return 0;
-       data = kmalloc(len, GFP_NOFS);
-       if (data == NULL)
-               return -ENOMEM;
-       error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
-       if (error < 0)
-               goto out;
-       error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
-       if (!error)
-               set_cached_acl(inode, type, acl);
-out:
-       kfree(data);
-       return error;
-}
-
-int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-       struct posix_acl *acl;
-       umode_t mode = inode->i_mode;
-       int error = 0;
-
-       if (!sdp->sd_args.ar_posix_acl)
-               return 0;
-       if (S_ISLNK(inode->i_mode))
-               return 0;
-
-       acl = gfs2_get_acl(&dip->i_inode, ACL_TYPE_DEFAULT);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (!acl) {
-               mode &= ~current_umask();
-               return gfs2_set_mode(inode, mode);
-       }
-
-       if (S_ISDIR(inode->i_mode)) {
-               error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
-               if (error)
-                       goto out;
-       }
-
-       error = posix_acl_create(&acl, GFP_NOFS, &mode);
-       if (error < 0)
-               return error;
 
-       if (error == 0)
-               goto munge;
-
-       error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
-       if (error)
-               goto out;
-munge:
-       error = gfs2_set_mode(inode, mode);
-out:
-       posix_acl_release(acl);
-       return error;
-}
-
-int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
-{
-       struct inode *inode = &ip->i_inode;
-       struct posix_acl *acl;
-       char *data;
-       unsigned int len;
-       int error;
-
-       acl = gfs2_get_acl(&ip->i_inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (!acl)
-               return gfs2_setattr_simple(inode, attr);
-
-       error = posix_acl_chmod(&acl, GFP_NOFS, attr->ia_mode);
-       if (error)
-               return error;
-
-       len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
-       data = kmalloc(len, GFP_NOFS);
-       error = -ENOMEM;
-       if (data == NULL)
-               goto out;
-       posix_acl_to_xattr(&init_user_ns, acl, data, len);
-       error = gfs2_xattr_acl_chmod(ip, attr, data);
-       kfree(data);
-       set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
-
-out:
-       posix_acl_release(acl);
-       return error;
-}
-
-static int gfs2_acl_type(const char *name)
-{
-       if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
-               return ACL_TYPE_ACCESS;
-       if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
-               return ACL_TYPE_DEFAULT;
-       return -EINVAL;
-}
-
-static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
-                                void *buffer, size_t size, int xtype)
-{
-       struct inode *inode = dentry->d_inode;
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
-       struct posix_acl *acl;
-       int type;
-       int error;
-
-       if (!sdp->sd_args.ar_posix_acl)
-               return -EOPNOTSUPP;
-
-       type = gfs2_acl_type(name);
-       if (type < 0)
-               return type;
-
-       acl = gfs2_get_acl(inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
-                                const void *value, size_t size, int flags,
-                                int xtype)
-{
-       struct inode *inode = dentry->d_inode;
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
-       struct posix_acl *acl = NULL;
-       int error = 0, type;
-
-       if (!sdp->sd_args.ar_posix_acl)
-               return -EOPNOTSUPP;
-
-       type = gfs2_acl_type(name);
-       if (type < 0)
-               return type;
-       if (flags & XATTR_CREATE)
-               return -EINVAL;
-       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-               return value ? -EACCES : 0;
-       if (!uid_eq(current_fsuid(), inode->i_uid) && !capable(CAP_FOWNER))
-               return -EPERM;
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       if (!value)
-               goto set_acl;
-
-       acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       if (!acl) {
-               /*
-                * acl_set_file(3) may request that we set default ACLs with
-                * zero length -- defend (gracefully) against that here.
-                */
-               goto out;
-       }
-       if (IS_ERR(acl)) {
-               error = PTR_ERR(acl);
-               goto out;
-       }
-
-       error = posix_acl_valid(acl);
-       if (error)
-               goto out_release;
-
-       error = -EINVAL;
        if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
-               goto out_release;
+               return -EINVAL;
 
        if (type == ACL_TYPE_ACCESS) {
                umode_t mode = inode->i_mode;
+
                error = posix_acl_equiv_mode(acl, &mode);
+               if (error < 0)
+                       return error;
 
-               if (error <= 0) {
-                       posix_acl_release(acl);
+               if (error == 0)
                        acl = NULL;
 
-                       if (error < 0)
-                               return error;
-               }
-
                error = gfs2_set_mode(inode, mode);
                if (error)
-                       goto out_release;
+                       return error;
        }
 
-set_acl:
-       error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
-       if (!error) {
-               if (acl)
-                       set_cached_acl(inode, type, acl);
-               else
-                       forget_cached_acl(inode, type);
+       if (acl) {
+               len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
+               if (len == 0)
+                       return 0;
+               data = kmalloc(len, GFP_NOFS);
+               if (data == NULL)
+                       return -ENOMEM;
+               error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
+               if (error < 0)
+                       goto out;
+       } else {
+               data = NULL;
+               len = 0;
        }
-out_release:
-       posix_acl_release(acl);
+
+       error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
+       if (error)
+               goto out;
+
+       if (acl)
+               set_cached_acl(inode, type, acl);
+       else
+               forget_cached_acl(inode, type);
 out:
+       kfree(data);
        return error;
 }
-
-const struct xattr_handler gfs2_xattr_system_handler = {
-       .prefix = XATTR_SYSTEM_PREFIX,
-       .flags  = GFS2_EATYPE_SYS,
-       .get    = gfs2_xattr_system_get,
-       .set    = gfs2_xattr_system_set,
-};
-
index 0da38dc7efec24959a1ad656ff2cda8b561db1e0..301260c999ba994bbcab3af270962cd93058dcd9 100644 (file)
@@ -17,8 +17,6 @@
 #define GFS2_ACL_MAX_ENTRIES           25
 
 extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
-extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode);
-extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
-extern const struct xattr_handler gfs2_xattr_system_handler;
+extern int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 
 #endif /* __ACL_DOT_H__ */
index 890588c7fb33f79208c3f4203eaf88dadeba8772..5c524180c98e85a50e8e4c63ce233f71ff82ea39 100644 (file)
@@ -571,6 +571,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
                             unsigned int size, int excl, int *opened)
 {
        const struct qstr *name = &dentry->d_name;
+       struct posix_acl *default_acl, *acl;
        struct gfs2_holder ghs[2];
        struct inode *inode = NULL;
        struct gfs2_inode *dip = GFS2_I(dir), *ip;
@@ -633,10 +634,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        if (!inode)
                goto fail_gunlock;
 
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
+               goto fail_free_vfs_inode;
+
        ip = GFS2_I(inode);
        error = gfs2_rs_alloc(ip);
        if (error)
-               goto fail_free_inode;
+               goto fail_free_acls;
 
        inode->i_mode = mode;
        set_nlink(inode, S_ISDIR(mode) ? 2 : 1);
@@ -704,7 +709,16 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        gfs2_set_iop(inode);
        insert_inode_hash(inode);
 
-       error = gfs2_acl_create(dip, inode);
+       if (default_acl) {
+               error = gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (!error)
+                       error = gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               posix_acl_release(acl);
+       }
+
        if (error)
                goto fail_gunlock3;
 
@@ -738,6 +752,12 @@ fail_free_inode:
        if (ip->i_gl)
                gfs2_glock_put(ip->i_gl);
        gfs2_rs_delete(ip, NULL);
+fail_free_acls:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
+fail_free_vfs_inode:
        free_inode_nonrcu(inode);
        inode = NULL;
 fail_gunlock:
@@ -1716,10 +1736,11 @@ static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
                error = gfs2_setattr_size(inode, attr->ia_size);
        else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
                error = setattr_chown(inode, attr);
-       else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
-               error = gfs2_acl_chmod(ip, attr);
-       else
+       else {
                error = gfs2_setattr_simple(inode, attr);
+               if (!error && attr->ia_valid & ATTR_MODE)
+                       error = posix_acl_chmod(inode, inode->i_mode);
+       }
 
 out:
        if (!error)
@@ -1879,6 +1900,7 @@ const struct inode_operations gfs2_file_iops = {
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
+       .set_acl = gfs2_set_acl,
 };
 
 const struct inode_operations gfs2_dir_iops = {
@@ -1900,6 +1922,7 @@ const struct inode_operations gfs2_dir_iops = {
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
+       .set_acl = gfs2_set_acl,
        .atomic_open = gfs2_atomic_open,
 };
 
@@ -1915,6 +1938,5 @@ const struct inode_operations gfs2_symlink_iops = {
        .listxattr = gfs2_listxattr,
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
-       .get_acl = gfs2_get_acl,
 };
 
index 8c6a6f6bdba978f9c3b37703a79d4c409516557b..0b81f783f78724293b174cd997d7f7b7321468b9 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/buffer_head.h>
 #include <linux/xattr.h>
 #include <linux/gfs2_ondisk.h>
+#include <linux/posix_acl_xattr.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -1500,7 +1501,8 @@ static const struct xattr_handler gfs2_xattr_security_handler = {
 const struct xattr_handler *gfs2_xattr_handlers[] = {
        &gfs2_xattr_user_handler,
        &gfs2_xattr_security_handler,
-       &gfs2_xattr_system_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
        NULL,
 };
 
index 07c0d4947527f33f46b433686e4a996dbb4aa984..95c8ed9ec17f7006940cf9c0fccdfe3c07a7868f 100644 (file)
 
 /* posix_acl.c */
 struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type);
-extern int hfsplus_posix_acl_chmod(struct inode *);
+int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
+               int type);
 extern int hfsplus_init_posix_acl(struct inode *, struct inode *);
 
 #else  /* CONFIG_HFSPLUS_FS_POSIX_ACL */
 #define hfsplus_get_posix_acl NULL
-
-static inline int hfsplus_posix_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
+#define hfsplus_set_posix_acl NULL
 
 static inline int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
 {
index 4a4fea0026735c8fb365d031c57165888e9bb079..9ee62985e739eba797e01318278712be6ee0dfac 100644 (file)
@@ -532,6 +532,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
        .removexattr            = hfsplus_removexattr,
 #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl                = hfsplus_get_posix_acl,
+       .set_acl                = hfsplus_set_posix_acl,
 #endif
 };
 
index 3ebda928229cb375486da2a05f15e860b5380fbc..4551cbd6bd43aaaebbde666c22c726c76112ab6e 100644 (file)
@@ -261,7 +261,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
        mark_inode_dirty(inode);
 
        if (attr->ia_valid & ATTR_MODE) {
-               error = hfsplus_posix_acl_chmod(inode);
+               error = posix_acl_chmod(inode, inode->i_mode);
                if (unlikely(error))
                        return error;
        }
@@ -334,6 +334,7 @@ static const struct inode_operations hfsplus_file_inode_operations = {
        .removexattr    = hfsplus_removexattr,
 #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl        = hfsplus_get_posix_acl,
+       .set_acl        = hfsplus_set_posix_acl,
 #endif
 };
 
index b609cc14c72e03c21063abbda72372c4ef94b1c7..df0c9af68d05ef0df5a127d53562677bc8a2d882 100644 (file)
@@ -17,9 +17,7 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
        char *value = NULL;
        ssize_t size;
 
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
+       hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
 
        switch (type) {
        case ACL_TYPE_ACCESS:
@@ -56,17 +54,15 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int hfsplus_set_posix_acl(struct inode *inode,
-                                       int type,
-                                       struct posix_acl *acl)
+int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
+               int type)
 {
        int err;
        char *xattr_name;
        size_t size = 0;
        char *value = NULL;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
+       hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
 
        switch (type) {
        case ACL_TYPE_ACCESS:
@@ -115,7 +111,7 @@ end_set_acl:
 int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
 {
        int err = 0;
-       struct posix_acl *acl = NULL;
+       struct posix_acl *default_acl, *acl;
 
        hfs_dbg(ACL_MOD,
                "[%s]: ino %lu, dir->ino %lu\n",
@@ -124,151 +120,21 @@ int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
        if (S_ISLNK(inode->i_mode))
                return 0;
 
-       acl = hfsplus_get_posix_acl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-
-       if (acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       err = hfsplus_set_posix_acl(inode,
-                                                       ACL_TYPE_DEFAULT,
-                                                       acl);
-                       if (unlikely(err))
-                               goto init_acl_cleanup;
-               }
-
-               err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
-               if (unlikely(err < 0))
-                       return err;
-
-               if (err > 0)
-                       err = hfsplus_set_posix_acl(inode,
-                                                       ACL_TYPE_ACCESS,
-                                                       acl);
-       } else
-               inode->i_mode &= ~current_umask();
-
-init_acl_cleanup:
-       posix_acl_release(acl);
-       return err;
-}
-
-int hfsplus_posix_acl_chmod(struct inode *inode)
-{
-       int err;
-       struct posix_acl *acl;
-
-       hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       acl = hfsplus_get_posix_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-
-       err = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (unlikely(err))
+       err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (err)
                return err;
 
-       err = hfsplus_set_posix_acl(inode, ACL_TYPE_ACCESS, acl);
-       posix_acl_release(acl);
-       return err;
-}
-
-static int hfsplus_xattr_get_posix_acl(struct dentry *dentry,
-                                       const char *name,
-                                       void *buffer,
-                                       size_t size,
-                                       int type)
-{
-       int err = 0;
-       struct posix_acl *acl;
-
-       hfs_dbg(ACL_MOD,
-               "[%s]: ino %lu, buffer %p, size %zu, type %#x\n",
-               __func__, dentry->d_inode->i_ino, buffer, size, type);
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-
-       acl = hfsplus_get_posix_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-
-       err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return err;
-}
-
-static int hfsplus_xattr_set_posix_acl(struct dentry *dentry,
-                                       const char *name,
-                                       const void *value,
-                                       size_t size,
-                                       int flags,
-                                       int type)
-{
-       int err = 0;
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl = NULL;
-
-       hfs_dbg(ACL_MOD,
-               "[%s]: ino %lu, value %p, size %zu, flags %#x, type %#x\n",
-               __func__, inode->i_ino, value, size, flags, type);
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               else if (acl) {
-                       err = posix_acl_valid(acl);
-                       if (err)
-                               goto end_xattr_set_acl;
-               }
+       if (default_acl) {
+               err = hfsplus_set_posix_acl(inode, default_acl,
+                                           ACL_TYPE_DEFAULT);
+               posix_acl_release(default_acl);
        }
 
-       err = hfsplus_set_posix_acl(inode, type, acl);
-
-end_xattr_set_acl:
-       posix_acl_release(acl);
+       if (acl) {
+               if (!err)
+                       err = hfsplus_set_posix_acl(inode, acl,
+                                                   ACL_TYPE_ACCESS);
+               posix_acl_release(acl);
+       }
        return err;
 }
-
-static size_t hfsplus_xattr_list_posix_acl(struct dentry *dentry,
-                                               char *list,
-                                               size_t list_size,
-                                               const char *name,
-                                               size_t name_len,
-                                               int type)
-{
-       /*
-        * This method is not used.
-        * It is used hfsplus_listxattr() instead of generic_listxattr().
-        */
-       return -EOPNOTSUPP;
-}
-
-const struct xattr_handler hfsplus_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = hfsplus_xattr_list_posix_acl,
-       .get    = hfsplus_xattr_get_posix_acl,
-       .set    = hfsplus_xattr_set_posix_acl,
-};
-
-const struct xattr_handler hfsplus_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = hfsplus_xattr_list_posix_acl,
-       .get    = hfsplus_xattr_get_posix_acl,
-       .set    = hfsplus_xattr_set_posix_acl,
-};
index 3c6136f98c737a8d0dc58f2a0cf41712e381ae92..0b4a5c9b93c44ad415f9378c3ec1e3914761c6ef 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "hfsplus_fs.h"
+#include <linux/posix_acl_xattr.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -15,8 +16,8 @@ const struct xattr_handler *hfsplus_xattr_handlers[] = {
        &hfsplus_xattr_user_handler,
        &hfsplus_xattr_trusted_handler,
 #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-       &hfsplus_xattr_acl_access_handler,
-       &hfsplus_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        &hfsplus_xattr_security_handler,
        NULL
@@ -51,82 +52,6 @@ static inline int is_known_namespace(const char *name)
        return true;
 }
 
-static int can_set_system_xattr(struct inode *inode, const char *name,
-                               const void *value, size_t size)
-{
-#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-       struct posix_acl *acl;
-       int err;
-
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       /*
-        * POSIX_ACL_XATTR_ACCESS is tied to i_mode
-        */
-       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               if (acl) {
-                       err = posix_acl_equiv_mode(acl, &inode->i_mode);
-                       posix_acl_release(acl);
-                       if (err < 0)
-                               return err;
-                       mark_inode_dirty(inode);
-               }
-               /*
-                * We're changing the ACL.  Get rid of the cached one
-                */
-               forget_cached_acl(inode, ACL_TYPE_ACCESS);
-
-               return 0;
-       } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               posix_acl_release(acl);
-
-               /*
-                * We're changing the default ACL.  Get rid of the cached one
-                */
-               forget_cached_acl(inode, ACL_TYPE_DEFAULT);
-
-               return 0;
-       }
-#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */
-       return -EOPNOTSUPP;
-}
-
-static int can_set_xattr(struct inode *inode, const char *name,
-                               const void *value, size_t value_len)
-{
-       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-               return can_set_system_xattr(inode, name, value, value_len);
-
-       if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
-               /*
-                * This makes sure that we aren't trying to set an
-                * attribute in a different namespace by prefixing it
-                * with "osx."
-                */
-               if (is_known_namespace(name + XATTR_MAC_OSX_PREFIX_LEN))
-                       return -EOPNOTSUPP;
-
-               return 0;
-       }
-
-       /*
-        * Don't allow setting an attribute in an unknown namespace.
-        */
-       if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
-           strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
-           strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
-               return -EOPNOTSUPP;
-
-       return 0;
-}
-
 static void hfsplus_init_header_node(struct inode *attr_file,
                                        u32 clump_size,
                                        char *buf, u16 node_size)
@@ -349,10 +274,6 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
                                HFSPLUS_IS_RSRC(inode))
                return -EOPNOTSUPP;
 
-       err = can_set_xattr(inode, name, value, size);
-       if (err)
-               return err;
-
        if (strncmp(name, XATTR_MAC_OSX_PREFIX,
                                XATTR_MAC_OSX_PREFIX_LEN) == 0)
                name += XATTR_MAC_OSX_PREFIX_LEN;
@@ -840,10 +761,6 @@ int hfsplus_removexattr(struct dentry *dentry, const char *name)
        if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
                return -EOPNOTSUPP;
 
-       err = can_set_xattr(inode, name, NULL, 0);
-       if (err)
-               return err;
-
        if (strncmp(name, XATTR_MAC_OSX_PREFIX,
                                XATTR_MAC_OSX_PREFIX_LEN) == 0)
                name += XATTR_MAC_OSX_PREFIX_LEN;
@@ -940,6 +857,9 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
        if (len > HFSPLUS_ATTR_MAX_STRLEN)
                return -EOPNOTSUPP;
 
+       if (is_known_namespace(name))
+               return -EOPNOTSUPP;
+
        strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
        strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
 
index 841b5698c0fc4b5375c8d5e153fea62bdc931da9..9e214490c313f6b61204db43e7317f2aac086e5c 100644 (file)
@@ -14,8 +14,6 @@
 extern const struct xattr_handler hfsplus_xattr_osx_handler;
 extern const struct xattr_handler hfsplus_xattr_user_handler;
 extern const struct xattr_handler hfsplus_xattr_trusted_handler;
-extern const struct xattr_handler hfsplus_xattr_acl_access_handler;
-extern const struct xattr_handler hfsplus_xattr_acl_default_handler;
 extern const struct xattr_handler hfsplus_xattr_security_handler;
 
 extern const struct xattr_handler *hfsplus_xattr_handlers[];
index 223283c301116f3d8d88cb70cf30aa030a54c456..009ec0b5993da879846ba7a733864116684026ca 100644 (file)
@@ -178,10 +178,6 @@ struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
        char *value = NULL;
        int rc, xprefix;
 
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                xprefix = JFFS2_XPREFIX_ACL_ACCESS;
@@ -232,13 +228,10 @@ static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *a
        return rc;
 }
 
-static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        int rc, xprefix;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                xprefix = JFFS2_XPREFIX_ACL_ACCESS;
@@ -277,30 +270,21 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 
 int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, umode_t *i_mode)
 {
-       struct posix_acl *acl;
+       struct posix_acl *default_acl, *acl;
        int rc;
 
        cache_no_acl(inode);
 
-       if (S_ISLNK(*i_mode))
-               return 0;       /* Symlink always has no-ACL */
-
-       acl = jffs2_get_acl(dir_i, ACL_TYPE_DEFAULT);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-
-       if (!acl) {
-               *i_mode &= ~current_umask();
-       } else {
-               if (S_ISDIR(*i_mode))
-                       set_cached_acl(inode, ACL_TYPE_DEFAULT, acl);
-
-               rc = posix_acl_create(&acl, GFP_KERNEL, i_mode);
-               if (rc < 0)
-                       return rc;
-               if (rc > 0)
-                       set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+       rc = posix_acl_create(dir_i, i_mode, &default_acl, &acl);
+       if (rc)
+               return rc;
 
+       if (default_acl) {
+               set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
                posix_acl_release(acl);
        }
        return 0;
@@ -324,106 +308,3 @@ int jffs2_init_acl_post(struct inode *inode)
 
        return 0;
 }
-
-int jffs2_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int rc;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-       acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-       rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (rc)
-               return rc;
-       rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, acl);
-       posix_acl_release(acl);
-       return rc;
-}
-
-static size_t jffs2_acl_access_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
-
-       if (list && retlen <= list_size)
-               strcpy(list, POSIX_ACL_XATTR_ACCESS);
-       return retlen;
-}
-
-static size_t jffs2_acl_default_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
-
-       if (list && retlen <= list_size)
-               strcpy(list, POSIX_ACL_XATTR_DEFAULT);
-       return retlen;
-}
-
-static int jffs2_acl_getxattr(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
-{
-       struct posix_acl *acl;
-       int rc;
-
-       if (name[0] != '\0')
-               return -EINVAL;
-
-       acl = jffs2_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (!acl)
-               return -ENODATA;
-       rc = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return rc;
-}
-
-static int jffs2_acl_setxattr(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
-{
-       struct posix_acl *acl;
-       int rc;
-
-       if (name[0] != '\0')
-               return -EINVAL;
-       if (!inode_owner_or_capable(dentry->d_inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               if (acl) {
-                       rc = posix_acl_valid(acl);
-                       if (rc)
-                               goto out;
-               }
-       } else {
-               acl = NULL;
-       }
-       rc = jffs2_set_acl(dentry->d_inode, type, acl);
- out:
-       posix_acl_release(acl);
-       return rc;
-}
-
-const struct xattr_handler jffs2_acl_access_xattr_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = jffs2_acl_access_listxattr,
-       .get    = jffs2_acl_getxattr,
-       .set    = jffs2_acl_setxattr,
-};
-
-const struct xattr_handler jffs2_acl_default_xattr_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = jffs2_acl_default_listxattr,
-       .get    = jffs2_acl_getxattr,
-       .set    = jffs2_acl_setxattr,
-};
index 9b477246f2a6ec1c0e0f0b9a34c870f44e6ba734..2e2b5745c3b75d42caea23256ccc4bfc6dacb039 100644 (file)
@@ -27,17 +27,14 @@ struct jffs2_acl_header {
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 
 struct posix_acl *jffs2_get_acl(struct inode *inode, int type);
-extern int jffs2_acl_chmod(struct inode *);
+int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int jffs2_init_acl_pre(struct inode *, struct inode *, umode_t *);
 extern int jffs2_init_acl_post(struct inode *);
 
-extern const struct xattr_handler jffs2_acl_access_xattr_handler;
-extern const struct xattr_handler jffs2_acl_default_xattr_handler;
-
 #else
 
 #define jffs2_get_acl                          (NULL)
-#define jffs2_acl_chmod(inode)                 (0)
+#define jffs2_set_acl                          (NULL)
 #define jffs2_init_acl_pre(dir_i,inode,mode)   (0)
 #define jffs2_init_acl_post(inode)             (0)
 
index e3aac222472e1f06e9d998f46323b4d8be0e1071..938556025d643349b5166e54b5cfc55ea4767dbe 100644 (file)
@@ -59,6 +59,7 @@ const struct inode_operations jffs2_dir_inode_operations =
        .mknod =        jffs2_mknod,
        .rename =       jffs2_rename,
        .get_acl =      jffs2_get_acl,
+       .set_acl =      jffs2_set_acl,
        .setattr =      jffs2_setattr,
        .setxattr =     jffs2_setxattr,
        .getxattr =     jffs2_getxattr,
index 1506673c087e11ae820245baadc8ae74cb9f01b2..256cd19a3b78c006a1439f893b1b51a0341c938a 100644 (file)
@@ -66,6 +66,7 @@ const struct file_operations jffs2_file_operations =
 const struct inode_operations jffs2_file_inode_operations =
 {
        .get_acl =      jffs2_get_acl,
+       .set_acl =      jffs2_set_acl,
        .setattr =      jffs2_setattr,
        .setxattr =     jffs2_setxattr,
        .getxattr =     jffs2_getxattr,
index 09b3ed45572475feb68b117fcf5b420a1a5e4d8f..a69e426435ddc3d2d207701df7a5b06264c1c481 100644 (file)
@@ -190,15 +190,16 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
 
 int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
 {
+       struct inode *inode = dentry->d_inode;
        int rc;
 
-       rc = inode_change_ok(dentry->d_inode, iattr);
+       rc = inode_change_ok(inode, iattr);
        if (rc)
                return rc;
 
-       rc = jffs2_do_setattr(dentry->d_inode, iattr);
+       rc = jffs2_do_setattr(inode, iattr);
        if (!rc && (iattr->ia_valid & ATTR_MODE))
-               rc = jffs2_acl_chmod(dentry->d_inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
 
        return rc;
 }
index 4f47aa24b5562001cf8983d6c7634c373d50206b..b8fd651307a42e2fce3d15dfcc1976e2526932ab 100644 (file)
@@ -288,6 +288,8 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
        struct jffs2_xattr_datum *xd;
        xd = kmem_cache_zalloc(xattr_datum_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", xd);
+       if (!xd)
+               return NULL;
 
        xd->class = RAWNODE_CLASS_XATTR_DATUM;
        xd->node = (void *)xd;
@@ -306,6 +308,8 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
        struct jffs2_xattr_ref *ref;
        ref = kmem_cache_zalloc(xattr_ref_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", ref);
+       if (!ref)
+               return NULL;
 
        ref->class = RAWNODE_CLASS_XATTR_REF;
        ref->node = (void *)ref;
index 6e563332bb242e2d4214026fa4ff608bcd69cf94..c7c77b0dfccde2fe5dedb619500fb8f4f4a1f866 100644 (file)
@@ -22,7 +22,6 @@ const struct inode_operations jffs2_symlink_inode_operations =
 {
        .readlink =     generic_readlink,
        .follow_link =  jffs2_follow_link,
-       .get_acl =      jffs2_get_acl,
        .setattr =      jffs2_setattr,
        .setxattr =     jffs2_setxattr,
        .getxattr =     jffs2_getxattr,
index 3034e970eb9a130cea79d7d413aa2463070408ff..ad0f2e2a1700835d596e656b540ec0ac06cafd90 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
 #include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 /* -------- xdatum related functions ----------------
@@ -921,8 +922,8 @@ const struct xattr_handler *jffs2_xattr_handlers[] = {
        &jffs2_security_xattr_handler,
 #endif
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
-       &jffs2_acl_access_xattr_handler,
-       &jffs2_acl_default_xattr_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        &jffs2_trusted_xattr_handler,
        NULL
@@ -942,10 +943,10 @@ static const struct xattr_handler *xprefix_to_handler(int xprefix) {
 #endif
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
        case JFFS2_XPREFIX_ACL_ACCESS:
-               ret = &jffs2_acl_access_xattr_handler;
+               ret = &posix_acl_access_xattr_handler;
                break;
        case JFFS2_XPREFIX_ACL_DEFAULT:
-               ret = &jffs2_acl_default_xattr_handler;
+               ret = &posix_acl_default_xattr_handler;
                break;
 #endif
        case JFFS2_XPREFIX_TRUSTED:
index d254d6d3599565fbca59621cf840d105d9cd4971..e973b85d6afd9f136bcae002cbe70432000e5a15 100644 (file)
@@ -72,7 +72,7 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
+static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
                       struct posix_acl *acl)
 {
        char *ea_name;
@@ -80,21 +80,22 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
        int size = 0;
        char *value = NULL;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       ea_name = POSIX_ACL_XATTR_ACCESS;
-                       break;
-               case ACL_TYPE_DEFAULT:
-                       ea_name = POSIX_ACL_XATTR_DEFAULT;
-                       if (!S_ISDIR(inode->i_mode))
-                               return acl ? -EACCES : 0;
-                       break;
-               default:
-                       return -EINVAL;
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               ea_name = POSIX_ACL_XATTR_ACCESS;
+               rc = posix_acl_equiv_mode(acl, &inode->i_mode);
+               if (rc < 0)
+                       return rc;
+               if (rc == 0)
+                       acl = NULL;
+               break;
+       case ACL_TYPE_DEFAULT:
+               ea_name = POSIX_ACL_XATTR_DEFAULT;
+               break;
+       default:
+               return -EINVAL;
        }
+
        if (acl) {
                size = posix_acl_xattr_size(acl->a_count);
                value = kmalloc(size, GFP_KERNEL);
@@ -114,65 +115,43 @@ out:
        return rc;
 }
 
+int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+       int rc;
+       tid_t tid;
+
+       tid = txBegin(inode->i_sb, 0);
+       mutex_lock(&JFS_IP(inode)->commit_mutex);
+       rc = __jfs_set_acl(tid, inode, type, acl);
+       if (!rc)
+               rc = txCommit(tid, 1, &inode, 0);
+       txEnd(tid);
+       mutex_unlock(&JFS_IP(inode)->commit_mutex);
+       return rc;
+}
+
 int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 {
-       struct posix_acl *acl = NULL;
+       struct posix_acl *default_acl, *acl;
        int rc = 0;
 
-       if (S_ISLNK(inode->i_mode))
-               return 0;
+       rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (rc)
+               return rc;
 
-       acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
+       if (default_acl) {
+               rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
+               posix_acl_release(default_acl);
+       }
 
        if (acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
-                       if (rc)
-                               goto cleanup;
-               }
-               rc = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
-               if (rc < 0)
-                       goto cleanup; /* posix_acl_release(NULL) is no-op */
-               if (rc > 0)
-                       rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
-cleanup:
+               if (!rc)
+                       rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
                posix_acl_release(acl);
-       } else
-               inode->i_mode &= ~current_umask();
+       }
 
        JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
                               inode->i_mode;
 
        return rc;
 }
-
-int jfs_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int rc;
-       tid_t tid;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       acl = jfs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-
-       rc = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (rc)
-               return rc;
-
-       tid = txBegin(inode->i_sb, 0);
-       mutex_lock(&JFS_IP(inode)->commit_mutex);
-       rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
-       if (!rc)
-               rc = txCommit(tid, 1, &inode, 0);
-       txEnd(tid);
-       mutex_unlock(&JFS_IP(inode)->commit_mutex);
-
-       posix_acl_release(acl);
-       return rc;
-}
index dd7442c5835864b0e04bdff5befbd0f020232bfb..794da944d5cd29c63d8db31040340e83d7079d87 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/posix_acl.h>
 #include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
@@ -131,7 +132,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
        mark_inode_dirty(inode);
 
        if (iattr->ia_valid & ATTR_MODE)
-               rc = jfs_acl_chmod(inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
        return rc;
 }
 
@@ -143,6 +144,7 @@ const struct inode_operations jfs_file_inode_operations = {
        .setattr        = jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
        .get_acl        = jfs_get_acl,
+       .set_acl        = jfs_set_acl,
 #endif
 };
 
index ad84fe50ca9e897362caa12101d63a590b56073f..489f993b7b137060a9df603bffbab24ba75d4d66 100644 (file)
@@ -21,8 +21,8 @@
 #ifdef CONFIG_JFS_POSIX_ACL
 
 struct posix_acl *jfs_get_acl(struct inode *inode, int type);
+int jfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int jfs_init_acl(tid_t, struct inode *, struct inode *);
-int jfs_acl_chmod(struct inode *inode);
 
 #else
 
@@ -32,10 +32,5 @@ static inline int jfs_init_acl(tid_t tid, struct inode *inode,
        return 0;
 }
 
-static inline int jfs_acl_chmod(struct inode *inode)
-{
-       return 0;
-}
-
 #endif
 #endif         /* _H_JFS_ACL */
index e9e100fd7c09a90a7ba603e7f1282ae9ba15e164..e8d717dabca3eb5a2e3bcff902c34b8376b8450d 100644 (file)
@@ -61,6 +61,8 @@ extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
 extern int jfs_removexattr(struct dentry *, const char *);
 
+extern const struct xattr_handler *jfs_xattr_handlers[];
+
 #ifdef CONFIG_JFS_SECURITY
 extern int jfs_init_security(tid_t, struct inode *, struct inode *,
                             const struct qstr *);
index aa8a3370631bd8da9475394ef9f571ed90c620ff..d59c7defb1efea8bb46bea33ddffe2c384db390b 100644 (file)
@@ -1524,6 +1524,7 @@ const struct inode_operations jfs_dir_inode_operations = {
        .setattr        = jfs_setattr,
 #ifdef CONFIG_JFS_POSIX_ACL
        .get_acl        = jfs_get_acl,
+       .set_acl        = jfs_set_acl,
 #endif
 };
 
index 6669aa2042c30154e0ad318ff5d6d657a2b60f61..e2b7483444fd0dc7163cf1d4ab651917b824965e 100644 (file)
@@ -44,6 +44,7 @@
 #include "jfs_imap.h"
 #include "jfs_acl.h"
 #include "jfs_debug.h"
+#include "jfs_xattr.h"
 
 MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
 MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
@@ -522,6 +523,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
         */
        sb->s_op = &jfs_super_operations;
        sb->s_export_op = &jfs_export_operations;
+       sb->s_xattr = jfs_xattr_handlers;
 #ifdef CONFIG_QUOTA
        sb->dq_op = &dquot_operations;
        sb->s_qcop = &dquot_quotactl_ops;
index d3472f4cd5301e1c3ac48817755a0c62f8f6975c..5324e4e2b9924babb2675451ed074f4a279d2ad4 100644 (file)
@@ -665,82 +665,13 @@ static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
        return 0;
 }
 
-/*
- * can_set_system_xattr
- *
- * This code is specific to the system.* namespace.  It contains policy
- * which doesn't belong in the main xattr codepath.
- */
-static int can_set_system_xattr(struct inode *inode, const char *name,
-                               const void *value, size_t value_len)
-{
-#ifdef CONFIG_JFS_POSIX_ACL
-       struct posix_acl *acl;
-       int rc;
-
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       /*
-        * POSIX_ACL_XATTR_ACCESS is tied to i_mode
-        */
-       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
-               if (IS_ERR(acl)) {
-                       rc = PTR_ERR(acl);
-                       printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
-                              rc);
-                       return rc;
-               }
-               if (acl) {
-                       rc = posix_acl_equiv_mode(acl, &inode->i_mode);
-                       posix_acl_release(acl);
-                       if (rc < 0) {
-                               printk(KERN_ERR
-                                      "posix_acl_equiv_mode returned %d\n",
-                                      rc);
-                               return rc;
-                       }
-                       mark_inode_dirty(inode);
-               }
-               /*
-                * We're changing the ACL.  Get rid of the cached one
-                */
-               forget_cached_acl(inode, ACL_TYPE_ACCESS);
-
-               return 0;
-       } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, value_len);
-               if (IS_ERR(acl)) {
-                       rc = PTR_ERR(acl);
-                       printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
-                              rc);
-                       return rc;
-               }
-               posix_acl_release(acl);
-
-               /*
-                * We're changing the default ACL.  Get rid of the cached one
-                */
-               forget_cached_acl(inode, ACL_TYPE_DEFAULT);
-
-               return 0;
-       }
-#endif                 /* CONFIG_JFS_POSIX_ACL */
-       return -EOPNOTSUPP;
-}
-
 /*
  * Most of the permission checking is done by xattr_permission in the vfs.
- * The local file system is responsible for handling the system.* namespace.
  * We also need to verify that this is a namespace that we recognize.
  */
 static int can_set_xattr(struct inode *inode, const char *name,
                         const void *value, size_t value_len)
 {
-       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
-               return can_set_system_xattr(inode, name, value, value_len);
-
        if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
                /*
                 * This makes sure that we aren't trying to set an
@@ -748,7 +679,7 @@ static int can_set_xattr(struct inode *inode, const char *name,
                 * with "os2."
                 */
                if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN))
-                               return -EOPNOTSUPP;
+                       return -EOPNOTSUPP;
                return 0;
        }
 
@@ -913,6 +844,14 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if ((rc = can_set_xattr(inode, name, value, value_len)))
                return rc;
 
+       /*
+        * If this is a request for a synthetic attribute in the system.*
+        * namespace use the generic infrastructure to resolve a handler
+        * for it via sb->s_xattr.
+        */
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_setxattr(dentry, name, value, value_len, flags);
+
        if (value == NULL) {    /* empty EA, do not remove */
                value = "";
                value_len = 0;
@@ -986,6 +925,14 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
 {
        int err;
 
+       /*
+        * If this is a request for a synthetic attribute in the system.*
+        * namespace use the generic infrastructure to resolve a handler
+        * for it via sb->s_xattr.
+        */
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_getxattr(dentry, name, data, buf_size);
+
        if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
                /*
                 * skip past "os2." prefix
@@ -1077,6 +1024,14 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
        if ((rc = can_set_xattr(inode, name, NULL, 0)))
                return rc;
 
+       /*
+        * If this is a request for a synthetic attribute in the system.*
+        * namespace use the generic infrastructure to resolve a handler
+        * for it via sb->s_xattr.
+        */
+       if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               return generic_removexattr(dentry, name);
+
        tid = txBegin(inode->i_sb, 0);
        mutex_lock(&ji->commit_mutex);
        rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
@@ -1088,6 +1043,19 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
        return rc;
 }
 
+/*
+ * List of handlers for synthetic system.* attributes.  All real ondisk
+ * attributes are handled directly.
+ */
+const struct xattr_handler *jfs_xattr_handlers[] = {
+#ifdef JFS_POSIX_ACL
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
+#endif
+       NULL,
+};
+
+
 #ifdef CONFIG_JFS_SECURITY
 static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
                          void *fs_info)
index d64c594be6c47baf29a70ffe63671f307cba4b7e..a17458ca6f29e4dbf1f1a1b8bb9e97949b279d29 100644 (file)
@@ -74,7 +74,7 @@ static inline int mnt_has_parent(struct mount *mnt)
 static inline int is_mounted(struct vfsmount *mnt)
 {
        /* neither detached nor internal? */
-       return !IS_ERR_OR_NULL(real_mount(mnt));
+       return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);
 }
 
 extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
index 3531deebad3084104e6a9fca7116ba68890ad5af..bcb838e2e52f24593da609abba67dc5ab5336947 100644 (file)
@@ -235,27 +235,9 @@ static int check_acl(struct inode *inode, int mask)
                return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK);
        }
 
-       acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
-
-       /*
-        * A filesystem can force a ACL callback by just never filling the
-        * ACL cache. But normally you'd fill the cache either at inode
-        * instantiation time, or on the first ->get_acl call.
-        *
-        * If the filesystem doesn't have a get_acl() function at all, we'll
-        * just create the negative cache entry.
-        */
-       if (acl == ACL_NOT_CACHED) {
-               if (inode->i_op->get_acl) {
-                       acl = inode->i_op->get_acl(inode, ACL_TYPE_ACCESS);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               } else {
-                       set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
-                       return -EAGAIN;
-               }
-       }
-
+       acl = get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
        if (acl) {
                int error = posix_acl_permission(inode, acl, mask);
                posix_acl_release(acl);
index 812154aff9818ccb6bcb79e88587478d9fe54fd6..b266f734bd5394a092edcf288fcd29d54e55df13 100644 (file)
@@ -1404,7 +1404,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
        /* Expect a negative dentry */
        BUG_ON(dentry->d_inode);
 
-       dfprintk(VFS, "NFS: atomic_open(%s/%ld), %pd\n",
+       dfprintk(VFS, "NFS: atomic_open(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        err = nfs_check_flags(open_flags);
@@ -1594,7 +1594,7 @@ int nfs_create(struct inode *dir, struct dentry *dentry,
        int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
        int error;
 
-       dfprintk(VFS, "NFS: create(%s/%ld), %pd\n",
+       dfprintk(VFS, "NFS: create(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        attr.ia_mode = mode;
@@ -1621,7 +1621,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
        struct iattr attr;
        int status;
 
-       dfprintk(VFS, "NFS: mknod(%s/%ld), %pd\n",
+       dfprintk(VFS, "NFS: mknod(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        if (!new_valid_dev(rdev))
@@ -1650,7 +1650,7 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct iattr attr;
        int error;
 
-       dfprintk(VFS, "NFS: mkdir(%s/%ld), %pd\n",
+       dfprintk(VFS, "NFS: mkdir(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        attr.ia_valid = ATTR_MODE;
@@ -1678,7 +1678,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
        int error;
 
-       dfprintk(VFS, "NFS: rmdir(%s/%ld), %pd\n",
+       dfprintk(VFS, "NFS: rmdir(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        trace_nfs_rmdir_enter(dir, dentry);
@@ -1747,7 +1747,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
        int error;
        int need_rehash = 0;
 
-       dfprintk(VFS, "NFS: unlink(%s/%ld, %pd)\n", dir->i_sb->s_id,
+       dfprintk(VFS, "NFS: unlink(%s/%lu, %pd)\n", dir->i_sb->s_id,
                dir->i_ino, dentry);
 
        trace_nfs_unlink_enter(dir, dentry);
@@ -1798,7 +1798,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        unsigned int pathlen = strlen(symname);
        int error;
 
-       dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s)\n", dir->i_sb->s_id,
+       dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s)\n", dir->i_sb->s_id,
                dir->i_ino, dentry, symname);
 
        if (pathlen > PAGE_SIZE)
@@ -1821,7 +1821,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
        trace_nfs_symlink_exit(dir, dentry, error);
        if (error != 0) {
-               dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s) error %d\n",
+               dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s) error %d\n",
                        dir->i_sb->s_id, dir->i_ino,
                        dentry, symname, error);
                d_drop(dentry);
@@ -2304,7 +2304,7 @@ out:
        if (!res && (mask & MAY_EXEC) && !execute_ok(inode))
                res = -EACCES;
 
-       dfprintk(VFS, "NFS: permission(%s/%ld), mask=0x%x, res=%d\n",
+       dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n",
                inode->i_sb->s_id, inode->i_ino, mask, res);
        return res;
 out_notsup:
index d71d66c9e0a1e6235cacdcdc41be6c045c65c554..b8797ae6831ff3e1be4c4b3f85c2c38e34252498 100644 (file)
@@ -222,14 +222,31 @@ out:
  * Synchronous I/O uses a stack-allocated iocb.  Thus we can't trust
  * the iocb is still valid here if this is a synchronous request.
  */
-static void nfs_direct_complete(struct nfs_direct_req *dreq)
+static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
 {
+       struct inode *inode = dreq->inode;
+
+       if (dreq->iocb && write) {
+               loff_t pos = dreq->iocb->ki_pos + dreq->count;
+
+               spin_lock(&inode->i_lock);
+               if (i_size_read(inode) < pos)
+                       i_size_write(inode, pos);
+               spin_unlock(&inode->i_lock);
+       }
+
+       if (write)
+               nfs_zap_mapping(inode, inode->i_mapping);
+
+       inode_dio_done(inode);
+
        if (dreq->iocb) {
                long res = (long) dreq->error;
                if (!res)
                        res = (long) dreq->count;
                aio_complete(dreq->iocb, res, 0);
        }
+
        complete_all(&dreq->completion);
 
        nfs_direct_req_release(dreq);
@@ -237,9 +254,9 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
 
 static void nfs_direct_readpage_release(struct nfs_page *req)
 {
-       dprintk("NFS: direct read done (%s/%lld %d@%lld)\n",
+       dprintk("NFS: direct read done (%s/%llu %d@%lld)\n",
                req->wb_context->dentry->d_inode->i_sb->s_id,
-               (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+               (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode),
                req->wb_bytes,
                (long long)req_offset(req));
        nfs_release_request(req);
@@ -272,7 +289,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
        }
 out_put:
        if (put_dreq(dreq))
-               nfs_direct_complete(dreq);
+               nfs_direct_complete(dreq, false);
        hdr->release(hdr);
 }
 
@@ -402,6 +419,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
                                              loff_t pos, bool uio)
 {
        struct nfs_pageio_descriptor desc;
+       struct inode *inode = dreq->inode;
        ssize_t result = -EINVAL;
        size_t requested_bytes = 0;
        unsigned long seg;
@@ -410,6 +428,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
                             &nfs_direct_read_completion_ops);
        get_dreq(dreq);
        desc.pg_dreq = dreq;
+       atomic_inc(&inode->i_dio_count);
 
        for (seg = 0; seg < nr_segs; seg++) {
                const struct iovec *vec = &iov[seg];
@@ -429,26 +448,69 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
         * generic layer handle the completion.
         */
        if (requested_bytes == 0) {
+               inode_dio_done(inode);
                nfs_direct_req_release(dreq);
                return result < 0 ? result : -EIO;
        }
 
        if (put_dreq(dreq))
-               nfs_direct_complete(dreq);
+               nfs_direct_complete(dreq, false);
        return 0;
 }
 
-static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
-                              unsigned long nr_segs, loff_t pos, bool uio)
+/**
+ * nfs_file_direct_read - file direct read operation for NFS files
+ * @iocb: target I/O control block
+ * @iov: vector of user buffers into which to read data
+ * @nr_segs: size of iov vector
+ * @pos: byte offset in file where reading starts
+ *
+ * We use this function for direct reads instead of calling
+ * generic_file_aio_read() in order to avoid gfar's check to see if
+ * the request starts before the end of the file.  For that check
+ * to work, we must generate a GETATTR before each direct read, and
+ * even then there is a window between the GETATTR and the subsequent
+ * READ where the file size could change.  Our preference is simply
+ * to do all reads the application wants, and the server will take
+ * care of managing the end of file boundary.
+ *
+ * This function also eliminates unnecessarily updating the file's
+ * atime locally, as the NFS server sets the file's atime, and this
+ * client must read the updated atime from the server back into its
+ * cache.
+ */
+ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
+                               unsigned long nr_segs, loff_t pos, bool uio)
 {
-       ssize_t result = -ENOMEM;
-       struct inode *inode = iocb->ki_filp->f_mapping->host;
+       struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
        struct nfs_direct_req *dreq;
        struct nfs_lock_context *l_ctx;
+       ssize_t result = -EINVAL;
+       size_t count;
 
+       count = iov_length(iov, nr_segs);
+       nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count);
+
+       dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n",
+               file, count, (long long) pos);
+
+       result = 0;
+       if (!count)
+               goto out;
+
+       mutex_lock(&inode->i_mutex);
+       result = nfs_sync_mapping(mapping);
+       if (result)
+               goto out_unlock;
+
+       task_io_account_read(count);
+
+       result = -ENOMEM;
        dreq = nfs_direct_req_alloc();
        if (dreq == NULL)
-               goto out;
+               goto out_unlock;
 
        dreq->inode = inode;
        dreq->bytes_left = iov_length(iov, nr_segs);
@@ -464,20 +526,26 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
 
        NFS_I(inode)->read_io += iov_length(iov, nr_segs);
        result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio);
-       if (!result)
+
+       mutex_unlock(&inode->i_mutex);
+
+       if (!result) {
                result = nfs_direct_wait(dreq);
+               if (result > 0)
+                       iocb->ki_pos = pos + result;
+       }
+
+       nfs_direct_req_release(dreq);
+       return result;
+
 out_release:
        nfs_direct_req_release(dreq);
+out_unlock:
+       mutex_unlock(&inode->i_mutex);
 out:
        return result;
 }
 
-static void nfs_inode_dio_write_done(struct inode *inode)
-{
-       nfs_zap_mapping(inode, inode->i_mapping);
-       inode_dio_done(inode);
-}
-
 #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4)
 static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 {
@@ -593,8 +661,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work)
                        nfs_direct_write_reschedule(dreq);
                        break;
                default:
-                       nfs_inode_dio_write_done(dreq->inode);
-                       nfs_direct_complete(dreq);
+                       nfs_direct_complete(dreq, true);
        }
 }
 
@@ -610,8 +677,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work)
 
 static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode)
 {
-       nfs_inode_dio_write_done(inode);
-       nfs_direct_complete(dreq);
+       nfs_direct_complete(dreq, true);
 }
 #endif
 
@@ -842,93 +908,6 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
        return 0;
 }
 
-static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos,
-                               size_t count, bool uio)
-{
-       ssize_t result = -ENOMEM;
-       struct inode *inode = iocb->ki_filp->f_mapping->host;
-       struct nfs_direct_req *dreq;
-       struct nfs_lock_context *l_ctx;
-
-       dreq = nfs_direct_req_alloc();
-       if (!dreq)
-               goto out;
-
-       dreq->inode = inode;
-       dreq->bytes_left = count;
-       dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
-       l_ctx = nfs_get_lock_context(dreq->ctx);
-       if (IS_ERR(l_ctx)) {
-               result = PTR_ERR(l_ctx);
-               goto out_release;
-       }
-       dreq->l_ctx = l_ctx;
-       if (!is_sync_kiocb(iocb))
-               dreq->iocb = iocb;
-
-       result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio);
-       if (!result)
-               result = nfs_direct_wait(dreq);
-out_release:
-       nfs_direct_req_release(dreq);
-out:
-       return result;
-}
-
-/**
- * nfs_file_direct_read - file direct read operation for NFS files
- * @iocb: target I/O control block
- * @iov: vector of user buffers into which to read data
- * @nr_segs: size of iov vector
- * @pos: byte offset in file where reading starts
- *
- * We use this function for direct reads instead of calling
- * generic_file_aio_read() in order to avoid gfar's check to see if
- * the request starts before the end of the file.  For that check
- * to work, we must generate a GETATTR before each direct read, and
- * even then there is a window between the GETATTR and the subsequent
- * READ where the file size could change.  Our preference is simply
- * to do all reads the application wants, and the server will take
- * care of managing the end of file boundary.
- *
- * This function also eliminates unnecessarily updating the file's
- * atime locally, as the NFS server sets the file's atime, and this
- * client must read the updated atime from the server back into its
- * cache.
- */
-ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos, bool uio)
-{
-       ssize_t retval = -EINVAL;
-       struct file *file = iocb->ki_filp;
-       struct address_space *mapping = file->f_mapping;
-       size_t count;
-
-       count = iov_length(iov, nr_segs);
-       nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count);
-
-       dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n",
-               file, count, (long long) pos);
-
-       retval = 0;
-       if (!count)
-               goto out;
-
-       retval = nfs_sync_mapping(mapping);
-       if (retval)
-               goto out;
-
-       task_io_account_read(count);
-
-       retval = nfs_direct_read(iocb, iov, nr_segs, pos, uio);
-       if (retval > 0)
-               iocb->ki_pos = pos + retval;
-
-out:
-       return retval;
-}
-
 /**
  * nfs_file_direct_write - file direct write operation for NFS files
  * @iocb: target I/O control block
@@ -954,46 +933,96 @@ out:
 ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos, bool uio)
 {
-       ssize_t retval = -EINVAL;
+       ssize_t result = -EINVAL;
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
+       struct nfs_direct_req *dreq;
+       struct nfs_lock_context *l_ctx;
+       loff_t end;
        size_t count;
 
        count = iov_length(iov, nr_segs);
+       end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
+
        nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
 
        dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
                file, count, (long long) pos);
 
-       retval = generic_write_checks(file, &pos, &count, 0);
-       if (retval)
+       result = generic_write_checks(file, &pos, &count, 0);
+       if (result)
                goto out;
 
-       retval = -EINVAL;
+       result = -EINVAL;
        if ((ssize_t) count < 0)
                goto out;
-       retval = 0;
+       result = 0;
        if (!count)
                goto out;
 
-       retval = nfs_sync_mapping(mapping);
-       if (retval)
-               goto out;
+       mutex_lock(&inode->i_mutex);
+
+       result = nfs_sync_mapping(mapping);
+       if (result)
+               goto out_unlock;
+
+       if (mapping->nrpages) {
+               result = invalidate_inode_pages2_range(mapping,
+                                       pos >> PAGE_CACHE_SHIFT, end);
+               if (result)
+                       goto out_unlock;
+       }
 
        task_io_account_write(count);
 
-       retval = nfs_direct_write(iocb, iov, nr_segs, pos, count, uio);
-       if (retval > 0) {
-               struct inode *inode = mapping->host;
+       result = -ENOMEM;
+       dreq = nfs_direct_req_alloc();
+       if (!dreq)
+               goto out_unlock;
 
-               iocb->ki_pos = pos + retval;
-               spin_lock(&inode->i_lock);
-               if (i_size_read(inode) < iocb->ki_pos)
-                       i_size_write(inode, iocb->ki_pos);
-               spin_unlock(&inode->i_lock);
+       dreq->inode = inode;
+       dreq->bytes_left = count;
+       dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
+       l_ctx = nfs_get_lock_context(dreq->ctx);
+       if (IS_ERR(l_ctx)) {
+               result = PTR_ERR(l_ctx);
+               goto out_release;
+       }
+       dreq->l_ctx = l_ctx;
+       if (!is_sync_kiocb(iocb))
+               dreq->iocb = iocb;
+
+       result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio);
+
+       if (mapping->nrpages) {
+               invalidate_inode_pages2_range(mapping,
+                                             pos >> PAGE_CACHE_SHIFT, end);
        }
+
+       mutex_unlock(&inode->i_mutex);
+
+       if (!result) {
+               result = nfs_direct_wait(dreq);
+               if (result > 0) {
+                       struct inode *inode = mapping->host;
+
+                       iocb->ki_pos = pos + result;
+                       spin_lock(&inode->i_lock);
+                       if (i_size_read(inode) < iocb->ki_pos)
+                               i_size_write(inode, iocb->ki_pos);
+                       spin_unlock(&inode->i_lock);
+               }
+       }
+       nfs_direct_req_release(dreq);
+       return result;
+
+out_release:
+       nfs_direct_req_release(dreq);
+out_unlock:
+       mutex_unlock(&inode->i_mutex);
 out:
-       return retval;
+       return result;
 }
 
 /**
index e2fcacf07de349c6d937991744fbcbbd4c4c91fc..5bb790a69c7165fd8319104ebbdc2a09848ab8b3 100644 (file)
@@ -354,7 +354,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
        struct page *page;
        int once_thru = 0;
 
-       dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%ld), %u@%lld)\n",
+       dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n",
                file, mapping->host->i_ino, len, (long long) pos);
 
 start:
@@ -395,7 +395,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        int status;
 
-       dfprintk(PAGECACHE, "NFS: write_end(%pD2(%ld), %u@%lld)\n",
+       dfprintk(PAGECACHE, "NFS: write_end(%pD2(%lu), %u@%lld)\n",
                file, mapping->host->i_ino, len, (long long) pos);
 
        /*
@@ -585,7 +585,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        int ret = VM_FAULT_NOPAGE;
        struct address_space *mapping;
 
-       dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%ld), offset %lld)\n",
+       dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%lu), offset %lld)\n",
                filp, filp->f_mapping->host->i_ino,
                (long long)page_offset(page));
 
index 00ad1c2b217ded2338c0ac4154681f83963581ab..ea00b34ff0712d6374908a08832cef0acdef82eb 100644 (file)
@@ -458,9 +458,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                unlock_new_inode(inode);
        } else
                nfs_refresh_inode(inode, fattr);
-       dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n",
+       dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n",
                inode->i_sb->s_id,
-               (long long)NFS_FILEID(inode),
+               (unsigned long long)NFS_FILEID(inode),
                nfs_display_fhandle_hash(fh),
                atomic_read(&inode->i_count));
 
@@ -870,8 +870,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
        struct nfs_fattr *fattr = NULL;
        struct nfs_inode *nfsi = NFS_I(inode);
 
-       dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
-               inode->i_sb->s_id, (long long)NFS_FILEID(inode));
+       dfprintk(PAGECACHE, "NFS: revalidating (%s/%Lu)\n",
+               inode->i_sb->s_id, (unsigned long long)NFS_FILEID(inode));
 
        trace_nfs_revalidate_inode_enter(inode);
 
@@ -895,9 +895,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 
        status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label);
        if (status != 0) {
-               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
+               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
                         inode->i_sb->s_id,
-                        (long long)NFS_FILEID(inode), status);
+                        (unsigned long long)NFS_FILEID(inode), status);
                if (status == -ESTALE) {
                        nfs_zap_caches(inode);
                        if (!S_ISDIR(inode->i_mode))
@@ -908,9 +908,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 
        status = nfs_refresh_inode(inode, fattr);
        if (status) {
-               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",
+               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) refresh failed, error=%d\n",
                         inode->i_sb->s_id,
-                        (long long)NFS_FILEID(inode), status);
+                        (unsigned long long)NFS_FILEID(inode), status);
                goto err_out;
        }
 
@@ -919,9 +919,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 
        nfs_setsecurity(inode, fattr, label);
 
-       dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
+       dfprintk(PAGECACHE, "NFS: (%s/%Lu) revalidation complete\n",
                inode->i_sb->s_id,
-               (long long)NFS_FILEID(inode));
+               (unsigned long long)NFS_FILEID(inode));
 
 err_out:
        nfs4_label_free(label);
@@ -985,8 +985,9 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map
        nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
        nfs_fscache_wait_on_invalidate(inode);
 
-       dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
-                       inode->i_sb->s_id, (long long)NFS_FILEID(inode));
+       dfprintk(PAGECACHE, "NFS: (%s/%Lu) data cache invalidated\n",
+                       inode->i_sb->s_id,
+                       (unsigned long long)NFS_FILEID(inode));
        return 0;
 }
 
@@ -1282,12 +1283,28 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n
                ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
 }
 
+/*
+ * Don't trust the change_attribute, mtime, ctime or size if
+ * a pnfs LAYOUTCOMMIT is outstanding
+ */
+static void nfs_inode_attrs_handle_layoutcommit(struct inode *inode,
+               struct nfs_fattr *fattr)
+{
+       if (pnfs_layoutcommit_outstanding(inode))
+               fattr->valid &= ~(NFS_ATTR_FATTR_CHANGE |
+                               NFS_ATTR_FATTR_MTIME |
+                               NFS_ATTR_FATTR_CTIME |
+                               NFS_ATTR_FATTR_SIZE);
+}
+
 static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
 {
        int ret;
 
        trace_nfs_refresh_inode_enter(inode);
 
+       nfs_inode_attrs_handle_layoutcommit(inode, fattr);
+
        if (nfs_inode_attrs_need_update(inode, fattr))
                ret = nfs_update_inode(inode, fattr);
        else
@@ -1434,7 +1451,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
        unsigned long now = jiffies;
        unsigned long save_cache_validity;
 
-       dfprintk(VFS, "NFS: %s(%s/%ld fh_crc=0x%08x ct=%d info=0x%x)\n",
+       dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
                        __func__, inode->i_sb->s_id, inode->i_ino,
                        nfs_display_fhandle_hash(NFS_FH(inode)),
                        atomic_read(&inode->i_count), fattr->valid);
@@ -1455,7 +1472,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                /*
                * Big trouble! The inode has become a different object.
                */
-               printk(KERN_DEBUG "NFS: %s: inode %ld mode changed, %07o to %07o\n",
+               printk(KERN_DEBUG "NFS: %s: inode %lu mode changed, %07o to %07o\n",
                                __func__, inode->i_ino, inode->i_mode, fattr->mode);
                goto out_err;
        }
@@ -1517,8 +1534,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                if (new_isize != cur_isize) {
                        /* Do we perhaps have any outstanding writes, or has
                         * the file grown beyond our last write? */
-                       if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) ||
-                            new_isize > cur_isize) {
+                       if ((nfsi->npages == 0) || new_isize > cur_isize) {
                                i_size_write(inode, new_isize);
                                invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
                        }
@@ -1641,10 +1657,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
                return NULL;
        nfsi->flags = 0UL;
        nfsi->cache_validity = 0UL;
-#ifdef CONFIG_NFS_V3_ACL
-       nfsi->acl_access = ERR_PTR(-EAGAIN);
-       nfsi->acl_default = ERR_PTR(-EAGAIN);
-#endif
 #if IS_ENABLED(CONFIG_NFS_V4)
        nfsi->nfs4_acl = NULL;
 #endif /* CONFIG_NFS_V4 */
index 4a1aafba6a20030532ba589ac9db021b10c21ceb..9a5ca03fa539fc5fb61ea4516b0ce0b6f4ae10ea 100644 (file)
 
 #define NFSDBG_FACILITY        NFSDBG_PROC
 
-ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl;
-       int pos=0, len=0;
-
-#      define output(s) do {                                           \
-                       if (pos + sizeof(s) <= size) {                  \
-                               memcpy(buffer + pos, s, sizeof(s));     \
-                               pos += sizeof(s);                       \
-                       }                                               \
-                       len += sizeof(s);                               \
-               } while(0)
-
-       acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl) {
-               output("system.posix_acl_access");
-               posix_acl_release(acl);
-       }
-
-       if (S_ISDIR(inode->i_mode)) {
-               acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               if (acl) {
-                       output("system.posix_acl_default");
-                       posix_acl_release(acl);
-               }
-       }
-
-#      undef output
-
-       if (!buffer || len <= size)
-               return len;
-       return -ERANGE;
-}
-
-ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
-               void *buffer, size_t size)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl;
-       int type, error = 0;
-
-       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
-               type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
-               type = ACL_TYPE_DEFAULT;
-       else
-               return -EOPNOTSUPP;
-
-       acl = nfs3_proc_getacl(inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       else if (acl) {
-               if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
-                       error = -ENODATA;
-               else
-                       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-               posix_acl_release(acl);
-       } else
-               error = -ENODATA;
-
-       return error;
-}
-
-int nfs3_setxattr(struct dentry *dentry, const char *name,
-            const void *value, size_t size, int flags)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl;
-       int type, error;
-
-       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
-               type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
-               type = ACL_TYPE_DEFAULT;
-       else
-               return -EOPNOTSUPP;
-
-       acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       error = nfs3_proc_setacl(inode, type, acl);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-int nfs3_removexattr(struct dentry *dentry, const char *name)
-{
-       struct inode *inode = dentry->d_inode;
-       int type;
-
-       if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
-               type = ACL_TYPE_ACCESS;
-       else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
-               type = ACL_TYPE_DEFAULT;
-       else
-               return -EOPNOTSUPP;
-
-       return nfs3_proc_setacl(inode, type, NULL);
-}
-
-static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
-{
-       if (!IS_ERR(nfsi->acl_access)) {
-               posix_acl_release(nfsi->acl_access);
-               nfsi->acl_access = ERR_PTR(-EAGAIN);
-       }
-       if (!IS_ERR(nfsi->acl_default)) {
-               posix_acl_release(nfsi->acl_default);
-               nfsi->acl_default = ERR_PTR(-EAGAIN);
-       }
-}
-
-void nfs3_forget_cached_acls(struct inode *inode)
-{
-       dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
-               inode->i_ino);
-       spin_lock(&inode->i_lock);
-       __nfs3_forget_cached_acls(NFS_I(inode));
-       spin_unlock(&inode->i_lock);
-}
-
-static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-       struct posix_acl *acl = ERR_PTR(-EINVAL);
-
-       spin_lock(&inode->i_lock);
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       acl = nfsi->acl_access;
-                       break;
-
-               case ACL_TYPE_DEFAULT:
-                       acl = nfsi->acl_default;
-                       break;
-
-               default:
-                       goto out;
-       }
-       if (IS_ERR(acl))
-               acl = ERR_PTR(-EAGAIN);
-       else
-               acl = posix_acl_dup(acl);
-out:
-       spin_unlock(&inode->i_lock);
-       dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
-               inode->i_ino, type, acl);
-       return acl;
-}
-
-static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
-                   struct posix_acl *dfacl)
-{
-       struct nfs_inode *nfsi = NFS_I(inode);
-
-       dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
-               inode->i_ino, acl, dfacl);
-       spin_lock(&inode->i_lock);
-       __nfs3_forget_cached_acls(NFS_I(inode));
-       if (!IS_ERR(acl))
-               nfsi->acl_access = posix_acl_dup(acl);
-       if (!IS_ERR(dfacl))
-               nfsi->acl_default = posix_acl_dup(dfacl);
-       spin_unlock(&inode->i_lock);
-}
-
-struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
+struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
 {
        struct nfs_server *server = NFS_SERVER(inode);
        struct page *pages[NFSACL_MAXPAGES] = { };
@@ -198,7 +26,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
                .rpc_argp       = &args,
                .rpc_resp       = &res,
        };
-       struct posix_acl *acl;
        int status, count;
 
        if (!nfs_server_capable(inode, NFS_CAP_ACLS))
@@ -207,10 +34,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
        status = nfs_revalidate_inode(server, inode);
        if (status < 0)
                return ERR_PTR(status);
-       acl = nfs3_get_cached_acl(inode, type);
-       if (acl != ERR_PTR(-EAGAIN))
-               return acl;
-       acl = NULL;
 
        /*
         * Only get the access acl when explicitly requested: We don't
@@ -257,40 +80,41 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
        }
 
        if (res.acl_access != NULL) {
-               if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
+               if (posix_acl_equiv_mode(res.acl_access, NULL) ||
+                   res.acl_access->a_count == 0) {
                        posix_acl_release(res.acl_access);
                        res.acl_access = NULL;
                }
        }
-       nfs3_cache_acls(inode,
-               (res.mask & NFS_ACL)   ? res.acl_access  : ERR_PTR(-EINVAL),
-               (res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
 
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       acl = res.acl_access;
-                       res.acl_access = NULL;
-                       break;
+       if (res.mask & NFS_ACL)
+               set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access);
+       else
+               forget_cached_acl(inode, ACL_TYPE_ACCESS);
 
-               case ACL_TYPE_DEFAULT:
-                       acl = res.acl_default;
-                       res.acl_default = NULL;
+       if (res.mask & NFS_DFACL)
+               set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default);
+       else
+               forget_cached_acl(inode, ACL_TYPE_DEFAULT);
+
+       nfs_free_fattr(res.fattr);
+       if (type == ACL_TYPE_ACCESS) {
+               posix_acl_release(res.acl_default);
+               return res.acl_access;
+       } else {
+               posix_acl_release(res.acl_access);
+               return res.acl_default;
        }
 
 getout:
        posix_acl_release(res.acl_access);
        posix_acl_release(res.acl_default);
        nfs_free_fattr(res.fattr);
-
-       if (status != 0) {
-               posix_acl_release(acl);
-               acl = ERR_PTR(status);
-       }
-       return acl;
+       return ERR_PTR(status);
 }
 
-static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
-                 struct posix_acl *dfacl)
+int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+               struct posix_acl *dfacl)
 {
        struct nfs_server *server = NFS_SERVER(inode);
        struct nfs_fattr *fattr;
@@ -353,7 +177,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
        switch (status) {
                case 0:
                        status = nfs_refresh_inode(inode, fattr);
-                       nfs3_cache_acls(inode, acl, dfacl);
+                       set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+                       set_cached_acl(inode, ACL_TYPE_DEFAULT, dfacl);
                        break;
                case -EPFNOSUPPORT:
                case -EPROTONOSUPPORT:
@@ -373,33 +198,27 @@ out:
        return status;
 }
 
-int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
+int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        struct posix_acl *alloc = NULL, *dfacl = NULL;
        int status;
 
        if (S_ISDIR(inode->i_mode)) {
                switch(type) {
-                       case ACL_TYPE_ACCESS:
-                               alloc = dfacl = nfs3_proc_getacl(inode,
-                                               ACL_TYPE_DEFAULT);
-                               if (IS_ERR(alloc))
-                                       goto fail;
-                               break;
-
-                       case ACL_TYPE_DEFAULT:
-                               dfacl = acl;
-                               alloc = acl = nfs3_proc_getacl(inode,
-                                               ACL_TYPE_ACCESS);
-                               if (IS_ERR(alloc))
-                                       goto fail;
-                               break;
-
-                       default:
-                               return -EINVAL;
+               case ACL_TYPE_ACCESS:
+                       alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT);
+                       if (IS_ERR(alloc))
+                               goto fail;
+                       break;
+
+               case ACL_TYPE_DEFAULT:
+                       dfacl = acl;
+                       alloc = acl = get_acl(inode, ACL_TYPE_ACCESS);
+                       if (IS_ERR(alloc))
+                               goto fail;
+                       break;
                }
-       } else if (type != ACL_TYPE_ACCESS)
-                       return -EINVAL;
+       }
 
        if (acl == NULL) {
                alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
@@ -417,24 +236,24 @@ fail:
 int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
                umode_t mode)
 {
-       struct posix_acl *dfacl, *acl;
-       int error = 0;
+       struct posix_acl *default_acl, *acl;
+       int error;
 
-       dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(dfacl)) {
-               error = PTR_ERR(dfacl);
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
                return (error == -EOPNOTSUPP) ? 0 : error;
-       }
-       if (!dfacl)
-               return 0;
-       acl = posix_acl_dup(dfacl);
-       error = posix_acl_create(&acl, GFP_KERNEL, &mode);
-       if (error < 0)
-               goto out_release_dfacl;
-       error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
-                                                     dfacl : NULL);
-       posix_acl_release(acl);
-out_release_dfacl:
-       posix_acl_release(dfacl);
+
+       error = nfs3_proc_setacls(inode, acl, default_acl);
+
+       if (acl)
+               posix_acl_release(acl);
+       if (default_acl)
+               posix_acl_release(default_acl);
        return error;
 }
+
+const struct xattr_handler *nfs3_xattr_handlers[] = {
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
+       NULL,
+};
index 01b6f6a49d162ef0ea8720786e259fd5f66aa9d3..d2255d7054210ef1daf54396d804bf6a45109ace 100644 (file)
@@ -317,8 +317,8 @@ static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                 int flags)
 {
+       struct posix_acl *default_acl, *acl;
        struct nfs3_createdata *data;
-       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  create %pd\n", dentry);
@@ -340,7 +340,9 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                data->arg.create.verifier[1] = cpu_to_be32(current->pid);
        }
 
-       sattr->ia_mode &= ~current_umask();
+       status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
+       if (status)
+               goto out;
 
        for (;;) {
                status = nfs3_do_create(dir, dentry, data);
@@ -366,7 +368,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        }
 
        if (status != 0)
-               goto out;
+               goto out_release_acls;
 
        /* When we created the file with exclusive semantics, make
         * sure we set the attributes afterwards. */
@@ -385,9 +387,14 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
                dprintk("NFS reply setattr (post-create): %d\n", status);
                if (status != 0)
-                       goto out;
+                       goto out_release_acls;
        }
-       status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+
+       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+
+out_release_acls:
+       posix_acl_release(acl);
+       posix_acl_release(default_acl);
 out:
        nfs3_free_createdata(data);
        dprintk("NFS reply create: %d\n", status);
@@ -572,18 +579,20 @@ out:
 static int
 nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 {
+       struct posix_acl *default_acl, *acl;
        struct nfs3_createdata *data;
-       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mkdir %pd\n", dentry);
 
-       sattr->ia_mode &= ~current_umask();
-
        data = nfs3_alloc_createdata();
        if (data == NULL)
                goto out;
 
+       status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
+       if (status)
+               goto out;
+
        data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
        data->arg.mkdir.fh = NFS_FH(dir);
        data->arg.mkdir.name = dentry->d_name.name;
@@ -592,9 +601,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 
        status = nfs3_do_create(dir, dentry, data);
        if (status != 0)
-               goto out;
+               goto out_release_acls;
 
-       status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+
+out_release_acls:
+       posix_acl_release(acl);
+       posix_acl_release(default_acl);
 out:
        nfs3_free_createdata(data);
        dprintk("NFS reply mkdir: %d\n", status);
@@ -691,19 +704,21 @@ static int
 nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                dev_t rdev)
 {
+       struct posix_acl *default_acl, *acl;
        struct nfs3_createdata *data;
-       umode_t mode = sattr->ia_mode;
        int status = -ENOMEM;
 
        dprintk("NFS call  mknod %pd %u:%u\n", dentry,
                        MAJOR(rdev), MINOR(rdev));
 
-       sattr->ia_mode &= ~current_umask();
-
        data = nfs3_alloc_createdata();
        if (data == NULL)
                goto out;
 
+       status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
+       if (status)
+               goto out;
+
        data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
        data->arg.mknod.fh = NFS_FH(dir);
        data->arg.mknod.name = dentry->d_name.name;
@@ -731,8 +746,13 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 
        status = nfs3_do_create(dir, dentry, data);
        if (status != 0)
-               goto out;
-       status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+               goto out_release_acls;
+
+       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+
+out_release_acls:
+       posix_acl_release(acl);
+       posix_acl_release(default_acl);
 out:
        nfs3_free_createdata(data);
        dprintk("NFS reply mknod: %d\n", status);
@@ -904,20 +924,28 @@ static const struct inode_operations nfs3_dir_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
-       .listxattr      = nfs3_listxattr,
-       .getxattr       = nfs3_getxattr,
-       .setxattr       = nfs3_setxattr,
-       .removexattr    = nfs3_removexattr,
+       .listxattr      = generic_listxattr,
+       .getxattr       = generic_getxattr,
+       .setxattr       = generic_setxattr,
+       .removexattr    = generic_removexattr,
+#ifdef CONFIG_NFS_V3_ACL
+       .get_acl        = nfs3_get_acl,
+       .set_acl        = nfs3_set_acl,
+#endif
 };
 
 static const struct inode_operations nfs3_file_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
-       .listxattr      = nfs3_listxattr,
-       .getxattr       = nfs3_getxattr,
-       .setxattr       = nfs3_setxattr,
-       .removexattr    = nfs3_removexattr,
+       .listxattr      = generic_listxattr,
+       .getxattr       = generic_getxattr,
+       .setxattr       = generic_setxattr,
+       .removexattr    = generic_removexattr,
+#ifdef CONFIG_NFS_V3_ACL
+       .get_acl        = nfs3_get_acl,
+       .set_acl        = nfs3_set_acl,
+#endif
 };
 
 const struct nfs_rpc_ops nfs_v3_clientops = {
@@ -965,7 +993,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare,
        .commit_done    = nfs3_commit_done,
        .lock           = nfs3_proc_lock,
-       .clear_acl_cache = nfs3_forget_cached_acls,
+       .clear_acl_cache = forget_all_cached_acls,
        .close_context  = nfs_close_context,
        .have_delegation = nfs3_have_delegation,
        .return_delegation = nfs3_return_delegation,
index cc471c7252300060c4dae042f77c0190762961f5..d6a98949af191e5e79e8cf74adb26f2b8f3cc462 100644 (file)
@@ -12,6 +12,9 @@ static struct nfs_subversion nfs_v3 = {
        .rpc_vers = &nfs_version3,
        .rpc_ops  = &nfs_v3_clientops,
        .sops     = &nfs_sops,
+#ifdef CONFIG_NFS_V3_ACL
+       .xattr    = nfs3_xattr_handlers,
+#endif
 };
 
 static int __init init_nfs_v3(void)
index b4a160a405ce2b60f64255433c1555a4284c61e9..73d4ecda1e367e250378cb46f8fe79ad3533db11 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/xprt.h>
 #include <linux/sunrpc/bc_xprt.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
 #include "internal.h"
 #include "callback.h"
 #include "delegation.h"
@@ -370,7 +371,11 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
                __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
        __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
        __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
-       error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
+
+       error = -EINVAL;
+       if (gssd_running(clp->cl_net))
+               error = nfs_create_rpc_client(clp, timeparms,
+                                             RPC_AUTH_GSS_KRB5I);
        if (error == -EINVAL)
                error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
        if (error < 0)
@@ -409,13 +414,11 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
        error = nfs4_discover_server_trunking(clp, &old);
        if (error < 0)
                goto error;
-       nfs_put_client(clp);
-       if (clp != old) {
-               clp->cl_preserve_clid = true;
-               clp = old;
-       }
 
-       return clp;
+       if (clp != old)
+               clp->cl_preserve_clid = true;
+       nfs_put_client(clp);
+       return old;
 
 error:
        nfs_mark_client_ready(clp, error);
@@ -493,9 +496,10 @@ int nfs40_walk_client_list(struct nfs_client *new,
                        prev = pos;
 
                        status = nfs_wait_client_init_complete(pos);
-                       spin_lock(&nn->nfs_client_lock);
                        if (status < 0)
-                               continue;
+                               goto out;
+                       status = -NFS4ERR_STALE_CLIENTID;
+                       spin_lock(&nn->nfs_client_lock);
                }
                if (pos->cl_cons_state != NFS_CS_READY)
                        continue;
@@ -633,7 +637,8 @@ int nfs41_walk_client_list(struct nfs_client *new,
                        }
                        spin_lock(&nn->nfs_client_lock);
                        if (status < 0)
-                               continue;
+                               break;
+                       status = -NFS4ERR_STALE_CLIENTID;
                }
                if (pos->cl_cons_state != NFS_CS_READY)
                        continue;
index b86464ba25e119711142e2b2959c1647d563f3e6..03fd8be8c0c50b3455ee94ae115fb77fa3d5e4fe 100644 (file)
@@ -91,10 +91,10 @@ static void filelayout_reset_write(struct nfs_write_data *data)
 
        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
                dprintk("%s Reset task %5u for i/o through MDS "
-                       "(req %s/%lld, %u bytes @ offset %llu)\n", __func__,
+                       "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
                        data->task.tk_pid,
                        hdr->inode->i_sb->s_id,
-                       (long long)NFS_FILEID(hdr->inode),
+                       (unsigned long long)NFS_FILEID(hdr->inode),
                        data->args.count,
                        (unsigned long long)data->args.offset);
 
@@ -112,10 +112,10 @@ static void filelayout_reset_read(struct nfs_read_data *data)
 
        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
                dprintk("%s Reset task %5u for i/o through MDS "
-                       "(req %s/%lld, %u bytes @ offset %llu)\n", __func__,
+                       "(req %s/%llu, %u bytes @ offset %llu)\n", __func__,
                        data->task.tk_pid,
                        hdr->inode->i_sb->s_id,
-                       (long long)NFS_FILEID(hdr->inode),
+                       (unsigned long long)NFS_FILEID(hdr->inode),
                        data->args.count,
                        (unsigned long long)data->args.offset);
 
@@ -1216,17 +1216,17 @@ static void filelayout_recover_commit_reqs(struct list_head *dst,
        struct pnfs_commit_bucket *b;
        int i;
 
-       /* NOTE cinfo->lock is NOT held, relying on fact that this is
-        * only called on single thread per dreq.
-        * Can't take the lock because need to do pnfs_put_lseg
-        */
+       spin_lock(cinfo->lock);
        for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
                if (transfer_commit_list(&b->written, dst, cinfo, 0)) {
+                       spin_unlock(cinfo->lock);
                        pnfs_put_lseg(b->wlseg);
                        b->wlseg = NULL;
+                       spin_lock(cinfo->lock);
                }
        }
        cinfo->ds->nwritten = 0;
+       spin_unlock(cinfo->lock);
 }
 
 static unsigned int
index c7c295e556ed87501c069053d0c133e44dcadc97..efac602edb37027a944601621baa8361c09f9fc9 100644 (file)
@@ -95,7 +95,7 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
                b6 = (struct sockaddr_in6 *)addr2;
 
                /* LINKLOCAL addresses must have matching scope_id */
-               if (ipv6_addr_scope(&a6->sin6_addr) ==
+               if (ipv6_addr_src_scope(&a6->sin6_addr) ==
                    IPV6_ADDR_SCOPE_LINKLOCAL &&
                    a6->sin6_scope_id != b6->sin6_scope_id)
                        return false;
index 15052b81df4245e4f797adb0d0b2e523338b23cc..a1965329a12c078781431c289bdb1c8b10954782 100644 (file)
@@ -7409,9 +7409,9 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
        struct nfs_server *server = NFS_SERVER(inode);
        struct pnfs_layout_hdr *lo;
        struct nfs4_state *state = NULL;
-       unsigned long timeo, giveup;
+       unsigned long timeo, now, giveup;
 
-       dprintk("--> %s\n", __func__);
+       dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
 
        if (!nfs41_sequence_done(task, &lgp->res.seq_res))
                goto out;
@@ -7419,12 +7419,38 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
        switch (task->tk_status) {
        case 0:
                goto out;
+       /*
+        * NFS4ERR_LAYOUTTRYLATER is a conflict with another client
+        * (or clients) writing to the same RAID stripe
+        */
        case -NFS4ERR_LAYOUTTRYLATER:
+       /*
+        * NFS4ERR_RECALLCONFLICT is when conflict with self (must recall
+        * existing layout before getting a new one).
+        */
        case -NFS4ERR_RECALLCONFLICT:
                timeo = rpc_get_timeout(task->tk_client);
                giveup = lgp->args.timestamp + timeo;
-               if (time_after(giveup, jiffies))
-                       task->tk_status = -NFS4ERR_DELAY;
+               now = jiffies;
+               if (time_after(giveup, now)) {
+                       unsigned long delay;
+
+                       /* Delay for:
+                        * - Not less then NFS4_POLL_RETRY_MIN.
+                        * - One last time a jiffie before we give up
+                        * - exponential backoff (time_now minus start_attempt)
+                        */
+                       delay = max_t(unsigned long, NFS4_POLL_RETRY_MIN,
+                                   min((giveup - now - 1),
+                                       now - lgp->args.timestamp));
+
+                       dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n",
+                               __func__, delay);
+                       rpc_delay(task, delay);
+                       task->tk_status = 0;
+                       rpc_restart_call_prepare(task);
+                       goto out; /* Do not call nfs4_async_handle_error() */
+               }
                break;
        case -NFS4ERR_EXPIRED:
        case -NFS4ERR_BAD_STATEID:
@@ -7780,10 +7806,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
        case -NFS4ERR_BADLAYOUT:     /* no layout */
        case -NFS4ERR_GRACE:        /* loca_recalim always false */
                task->tk_status = 0;
-               break;
        case 0:
-               nfs_post_op_update_inode_force_wcc(data->args.inode,
-                                                  data->res.fattr);
                break;
        default:
                if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
@@ -7798,6 +7821,8 @@ static void nfs4_layoutcommit_release(void *calldata)
        struct nfs4_layoutcommit_data *data = calldata;
 
        pnfs_cleanup_layoutcommit(data);
+       nfs_post_op_update_inode_force_wcc(data->args.inode,
+                                          data->res.fattr);
        put_rpccred(data->cred);
        kfree(data);
 }
@@ -7920,7 +7945,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle,
                switch (err) {
                case 0:
                case -NFS4ERR_WRONGSEC:
-               case -NFS4ERR_NOTSUPP:
+               case -ENOTSUPP:
                        goto out;
                default:
                        err = nfs4_handle_exception(server, err, &exception);
@@ -7954,7 +7979,7 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
         * Fall back on "guess and check" method if
         * the server doesn't support SECINFO_NO_NAME
         */
-       if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) {
+       if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) {
                err = nfs4_find_root_sec(server, fhandle, info);
                goto out_freepage;
        }
index 059c01b67a7164a6d782139fb7b66b0d3976ad21..e5be72518bd7ebe813522b1c24f7fa16b539421e 100644 (file)
@@ -1071,7 +1071,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
 /*
  * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
  * failed with a seqid incrementing error -
- * see comments nfs_fs.h:seqid_mutating_error()
+ * see comments nfs4.h:seqid_mutating_error()
  */
 static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
 {
@@ -1116,7 +1116,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
 /*
  * Increment the seqid if the LOCK/LOCKU succeeded, or
  * failed with a seqid incrementing error -
- * see comments nfs_fs.h:seqid_mutating_error()
+ * see comments nfs4.h:seqid_mutating_error()
  */
 void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
 {
index 65ab0a0ca1c47242090bc14dc97e9cf1fcec525a..808f295744127918313fa497c1c5347a850e329f 100644 (file)
@@ -77,17 +77,9 @@ static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
        int ret = nfs_write_inode(inode, wbc);
 
-       if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) {
-               int status;
-               bool sync = true;
-
-               if (wbc->sync_mode == WB_SYNC_NONE)
-                       sync = false;
-
-               status = pnfs_layoutcommit_inode(inode, sync);
-               if (status < 0)
-                       return status;
-       }
+       if (ret == 0)
+               ret = pnfs_layoutcommit_inode(inode,
+                               wbc->sync_mode == WB_SYNC_ALL);
        return ret;
 }
 
index 5be2868c02f15e63c33eaea848f077e1e7b3d889..8c21d69a9dc114c8781dc8ae3171f17f67fb4a8d 100644 (file)
@@ -3097,7 +3097,8 @@ out_overflow:
        return -EIO;
 }
 
-static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
+               int *nfs_retval)
 {
        __be32 *p;
        uint32_t opnum;
@@ -3107,19 +3108,32 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
        if (unlikely(!p))
                goto out_overflow;
        opnum = be32_to_cpup(p++);
-       if (opnum != expected) {
-               dprintk("nfs: Server returned operation"
-                       " %d but we issued a request for %d\n",
-                               opnum, expected);
-               return -EIO;
-       }
+       if (unlikely(opnum != expected))
+               goto out_bad_operation;
        nfserr = be32_to_cpup(p);
-       if (nfserr != NFS_OK)
-               return nfs4_stat_to_errno(nfserr);
-       return 0;
+       if (nfserr == NFS_OK)
+               *nfs_retval = 0;
+       else
+               *nfs_retval = nfs4_stat_to_errno(nfserr);
+       return true;
+out_bad_operation:
+       dprintk("nfs: Server returned operation"
+               " %d but we issued a request for %d\n",
+                       opnum, expected);
+       *nfs_retval = -EREMOTEIO;
+       return false;
 out_overflow:
        print_overflow_msg(__func__, xdr);
-       return -EIO;
+       *nfs_retval = -EIO;
+       return false;
+}
+
+static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+{
+       int retval;
+
+       __decode_op_hdr(xdr, expected, &retval);
+       return retval;
 }
 
 /* Dummy routine */
@@ -5001,11 +5015,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
        uint32_t savewords, bmlen, i;
        int status;
 
-       status = decode_op_hdr(xdr, OP_OPEN);
-       if (status != -EIO)
-               nfs_increment_open_seqid(status, res->seqid);
-       if (!status)
-               status = decode_stateid(xdr, &res->stateid);
+       if (!__decode_op_hdr(xdr, OP_OPEN, &status))
+               return status;
+       nfs_increment_open_seqid(status, res->seqid);
+       if (status)
+               return status;
+       status = decode_stateid(xdr, &res->stateid);
        if (unlikely(status))
                return status;
 
index d75d938d36cbff83bee4f905e142eeaf95c9b33b..4755858e37a0b93f64643811f683b0de7f0d6def 100644 (file)
@@ -1790,6 +1790,15 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
 
+static void pnfs_clear_layoutcommitting(struct inode *inode)
+{
+       unsigned long *bitlock = &NFS_I(inode)->flags;
+
+       clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+       smp_mb__after_clear_bit();
+       wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+}
+
 /*
  * There can be multiple RW segments.
  */
@@ -1807,7 +1816,6 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
 static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
 {
        struct pnfs_layout_segment *lseg, *tmp;
-       unsigned long *bitlock = &NFS_I(inode)->flags;
 
        /* Matched by references in pnfs_set_layoutcommit */
        list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
@@ -1815,9 +1823,7 @@ static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *lis
                pnfs_put_lseg(lseg);
        }
 
-       clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
-       smp_mb__after_clear_bit();
-       wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+       pnfs_clear_layoutcommitting(inode);
 }
 
 void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
@@ -1881,43 +1887,37 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
        struct nfs4_layoutcommit_data *data;
        struct nfs_inode *nfsi = NFS_I(inode);
        loff_t end_pos;
-       int status = 0;
+       int status;
 
-       dprintk("--> %s inode %lu\n", __func__, inode->i_ino);
-
-       if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+       if (!pnfs_layoutcommit_outstanding(inode))
                return 0;
 
-       /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
-       data = kzalloc(sizeof(*data), GFP_NOFS);
-       if (!data) {
-               status = -ENOMEM;
-               goto out;
-       }
-
-       if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
-               goto out_free;
+       dprintk("--> %s inode %lu\n", __func__, inode->i_ino);
 
+       status = -EAGAIN;
        if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) {
-               if (!sync) {
-                       status = -EAGAIN;
-                       goto out_free;
-               }
-               status = wait_on_bit_lock(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING,
-                                       nfs_wait_bit_killable, TASK_KILLABLE);
+               if (!sync)
+                       goto out;
+               status = wait_on_bit_lock(&nfsi->flags,
+                               NFS_INO_LAYOUTCOMMITTING,
+                               nfs_wait_bit_killable,
+                               TASK_KILLABLE);
                if (status)
-                       goto out_free;
+                       goto out;
        }
 
-       INIT_LIST_HEAD(&data->lseg_list);
+       status = -ENOMEM;
+       /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
+       data = kzalloc(sizeof(*data), GFP_NOFS);
+       if (!data)
+               goto clear_layoutcommitting;
+
+       status = 0;
        spin_lock(&inode->i_lock);
-       if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
-               clear_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags);
-               spin_unlock(&inode->i_lock);
-               wake_up_bit(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING);
-               goto out_free;
-       }
+       if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+               goto out_unlock;
 
+       INIT_LIST_HEAD(&data->lseg_list);
        pnfs_list_write_lseg(inode, &data->lseg_list);
 
        end_pos = nfsi->layout->plh_lwb;
@@ -1940,8 +1940,11 @@ out:
                mark_inode_dirty_sync(inode);
        dprintk("<-- %s status %d\n", __func__, status);
        return status;
-out_free:
+out_unlock:
+       spin_unlock(&inode->i_lock);
        kfree(data);
+clear_layoutcommitting:
+       pnfs_clear_layoutcommitting(inode);
        goto out;
 }
 
index a4f41810a7f497fbe5b34d497d8c1a5078a44524..023793909778ef975b3441d19b8d8632845bc2c4 100644 (file)
@@ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode)
                PNFS_LAYOUTRET_ON_SETATTR;
 }
 
+static inline bool
+pnfs_layoutcommit_outstanding(struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+
+       return test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags) != 0 ||
+               test_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags) != 0;
+}
+
 static inline int pnfs_return_layout(struct inode *ino)
 {
        struct nfs_inode *nfsi = NFS_I(ino);
@@ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src,
        return false;
 }
 
+static inline bool
+pnfs_layoutcommit_outstanding(struct inode *inode)
+{
+       return false;
+}
+
+
 static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
 {
        return NULL;
index 31db5c366b816e4c18d806ae0ae80d0c9207905e..411aedda14bb70c413fc771eb2a44e60817ed8ff 100644 (file)
@@ -163,9 +163,9 @@ static void nfs_readpage_release(struct nfs_page *req)
 
        unlock_page(req->wb_page);
 
-       dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
+       dprintk("NFS: read done (%s/%Lu %d@%Ld)\n",
                        req->wb_context->dentry->d_inode->i_sb->s_id,
-                       (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
        nfs_release_request(req);
@@ -228,11 +228,11 @@ int nfs_initiate_read(struct rpc_clnt *clnt,
        /* Set up the initial task struct. */
        NFS_PROTO(inode)->read_setup(data, &msg);
 
-       dprintk("NFS: %5u initiated read call (req %s/%lld, %u bytes @ "
+       dprintk("NFS: %5u initiated read call (req %s/%llu, %u bytes @ "
                        "offset %llu)\n",
                        data->task.tk_pid,
                        inode->i_sb->s_id,
-                       (long long)NFS_FILEID(inode),
+                       (unsigned long long)NFS_FILEID(inode),
                        data->args.count,
                        (unsigned long long)data->args.offset);
 
@@ -630,9 +630,9 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
        unsigned long npages;
        int ret = -ESTALE;
 
-       dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
+       dprintk("NFS: nfs_readpages (%s/%Lu %d)\n",
                        inode->i_sb->s_id,
-                       (long long)NFS_FILEID(inode),
+                       (unsigned long long)NFS_FILEID(inode),
                        nr_pages);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
 
index c1d548211c31dfab94dec9252cc3d929cfe42daa..a44a87268a6ef640c454600873489cc4e4e1e058 100644 (file)
@@ -922,19 +922,20 @@ out:
  * extend the write to cover the entire page in order to avoid fragmentation
  * inefficiencies.
  *
- * If the file is opened for synchronous writes or if we have a write delegation
- * from the server then we can just skip the rest of the checks.
+ * If the file is opened for synchronous writes then we can just skip the rest
+ * of the checks.
  */
 static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode)
 {
        if (file->f_flags & O_DSYNC)
                return 0;
+       if (!nfs_write_pageuptodate(page, inode))
+               return 0;
        if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE))
                return 1;
-       if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL ||
-                       (inode->i_flock->fl_start == 0 &&
+       if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 &&
                        inode->i_flock->fl_end == OFFSET_MAX &&
-                       inode->i_flock->fl_type != F_RDLCK)))
+                       inode->i_flock->fl_type != F_RDLCK))
                return 1;
        return 0;
 }
@@ -1013,10 +1014,10 @@ int nfs_initiate_write(struct rpc_clnt *clnt,
        NFS_PROTO(inode)->write_setup(data, &msg);
 
        dprintk("NFS: %5u initiated write call "
-               "(req %s/%lld, %u bytes @ offset %llu)\n",
+               "(req %s/%llu, %u bytes @ offset %llu)\n",
                data->task.tk_pid,
                inode->i_sb->s_id,
-               (long long)NFS_FILEID(inode),
+               (unsigned long long)NFS_FILEID(inode),
                data->args.count,
                (unsigned long long)data->args.offset);
 
@@ -1606,9 +1607,9 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                nfs_list_remove_request(req);
                nfs_clear_page_commit(req->wb_page);
 
-               dprintk("NFS:       commit (%s/%lld %d@%lld)",
+               dprintk("NFS:       commit (%s/%llu %d@%lld)",
                        req->wb_context->dentry->d_sb->s_id,
-                       (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode),
                        req->wb_bytes,
                        (long long)req_offset(req));
                if (status < 0) {
index 8b186a4955cc8c1cd5c84e3aadc2397370ea1086..8b68218e2c1c25c188f7585966dd9f694807e096 100644 (file)
@@ -35,7 +35,9 @@
 #ifndef LINUX_NFS4_ACL_H
 #define LINUX_NFS4_ACL_H
 
-#include <linux/posix_acl.h>
+struct nfs4_acl;
+struct svc_fh;
+struct svc_rqst;
 
 /* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
  * fit in a page: */
@@ -45,13 +47,9 @@ struct nfs4_acl *nfs4_acl_new(int);
 int nfs4_acl_get_whotype(char *, u32);
 int nfs4_acl_write_who(int who, char *p);
 
-#define NFS4_ACL_TYPE_DEFAULT  0x01
-#define NFS4_ACL_DIR           0x02
-#define NFS4_ACL_OWNER         0x04
-
-struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
-                               struct posix_acl *, unsigned int flags);
-int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
-                               struct posix_acl **, unsigned int flags);
+int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
+               struct nfs4_acl **acl);
+__be32 nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
+               struct nfs4_acl *acl);
 
 #endif /* LINUX_NFS4_ACL_H */
index 95d76dc6c5da5bf313c4778eaa8220eb91ac1665..11c1fba293124f0eba92a066262ab60f7bd9c600 100644 (file)
@@ -30,8 +30,9 @@ nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
                struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
 {
-       svc_fh *fh;
        struct posix_acl *acl;
+       struct inode *inode;
+       svc_fh *fh;
        __be32 nfserr = 0;
 
        dprintk("nfsd: GETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
@@ -41,6 +42,8 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
        if (nfserr)
                RETURN_STATUS(nfserr);
 
+       inode = fh->fh_dentry->d_inode;
+
        if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
                RETURN_STATUS(nfserr_inval);
        resp->mask = argp->mask;
@@ -50,21 +53,13 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
                goto fail;
 
        if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
-               acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+               acl = get_acl(inode, ACL_TYPE_ACCESS);
                if (IS_ERR(acl)) {
-                       int err = PTR_ERR(acl);
-
-                       if (err == -ENODATA || err == -EOPNOTSUPP)
-                               acl = NULL;
-                       else {
-                               nfserr = nfserrno(err);
-                               goto fail;
-                       }
+                       nfserr = nfserrno(PTR_ERR(acl));
+                       goto fail;
                }
                if (acl == NULL) {
                        /* Solaris returns the inode's minimum ACL. */
-
-                       struct inode *inode = fh->fh_dentry->d_inode;
                        acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
                }
                resp->acl_access = acl;
@@ -72,17 +67,10 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
        if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
                /* Check how Solaris handles requests for the Default ACL
                   of a non-directory! */
-
-               acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+               acl = get_acl(inode, ACL_TYPE_DEFAULT);
                if (IS_ERR(acl)) {
-                       int err = PTR_ERR(acl);
-
-                       if (err == -ENODATA || err == -EOPNOTSUPP)
-                               acl = NULL;
-                       else {
-                               nfserr = nfserrno(err);
-                               goto fail;
-                       }
+                       nfserr = nfserrno(PTR_ERR(acl));
+                       goto fail;
                }
                resp->acl_default = acl;
        }
@@ -103,31 +91,51 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
                struct nfsd3_setaclargs *argp,
                struct nfsd_attrstat *resp)
 {
+       struct inode *inode;
        svc_fh *fh;
        __be32 nfserr = 0;
+       int error;
 
        dprintk("nfsd: SETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
 
        fh = fh_copy(&resp->fh, &argp->fh);
        nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
+       if (nfserr)
+               goto out;
 
-       if (!nfserr) {
-               nfserr = nfserrno( nfsd_set_posix_acl(
-                       fh, ACL_TYPE_ACCESS, argp->acl_access) );
-       }
-       if (!nfserr) {
-               nfserr = nfserrno( nfsd_set_posix_acl(
-                       fh, ACL_TYPE_DEFAULT, argp->acl_default) );
-       }
-       if (!nfserr) {
-               nfserr = fh_getattr(fh, &resp->stat);
+       inode = fh->fh_dentry->d_inode;
+       if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
+               error = -EOPNOTSUPP;
+               goto out_errno;
        }
 
+       error = fh_want_write(fh);
+       if (error)
+               goto out_errno;
+
+       error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+       if (error)
+               goto out_drop_write;
+       error = inode->i_op->set_acl(inode, argp->acl_default,
+                                    ACL_TYPE_DEFAULT);
+       if (error)
+               goto out_drop_write;
+
+       fh_drop_write(fh);
+
+       nfserr = fh_getattr(fh, &resp->stat);
+
+out:
        /* argp->acl_{access,default} may have been allocated in
           nfssvc_decode_setaclargs. */
        posix_acl_release(argp->acl_access);
        posix_acl_release(argp->acl_default);
        return nfserr;
+out_drop_write:
+       fh_drop_write(fh);
+out_errno:
+       nfserr = nfserrno(error);
+       goto out;
 }
 
 /*
index 9cbc1a841f87b39d47e81f40cf1e8eac6161a3d2..adc5f1b1dc2677eda3eae5ee895e6df915d4f5cd 100644 (file)
@@ -29,8 +29,9 @@ nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
                struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
 {
-       svc_fh *fh;
        struct posix_acl *acl;
+       struct inode *inode;
+       svc_fh *fh;
        __be32 nfserr = 0;
 
        fh = fh_copy(&resp->fh, &argp->fh);
@@ -38,26 +39,20 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
        if (nfserr)
                RETURN_STATUS(nfserr);
 
+       inode = fh->fh_dentry->d_inode;
+
        if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
                RETURN_STATUS(nfserr_inval);
        resp->mask = argp->mask;
 
        if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
-               acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+               acl = get_acl(inode, ACL_TYPE_ACCESS);
                if (IS_ERR(acl)) {
-                       int err = PTR_ERR(acl);
-
-                       if (err == -ENODATA || err == -EOPNOTSUPP)
-                               acl = NULL;
-                       else {
-                               nfserr = nfserrno(err);
-                               goto fail;
-                       }
+                       nfserr = nfserrno(PTR_ERR(acl));
+                       goto fail;
                }
                if (acl == NULL) {
                        /* Solaris returns the inode's minimum ACL. */
-
-                       struct inode *inode = fh->fh_dentry->d_inode;
                        acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
                }
                resp->acl_access = acl;
@@ -65,17 +60,10 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
        if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
                /* Check how Solaris handles requests for the Default ACL
                   of a non-directory! */
-
-               acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+               acl = get_acl(inode, ACL_TYPE_DEFAULT);
                if (IS_ERR(acl)) {
-                       int err = PTR_ERR(acl);
-
-                       if (err == -ENODATA || err == -EOPNOTSUPP)
-                               acl = NULL;
-                       else {
-                               nfserr = nfserrno(err);
-                               goto fail;
-                       }
+                       nfserr = nfserrno(PTR_ERR(acl));
+                       goto fail;
                }
                resp->acl_default = acl;
        }
@@ -96,21 +84,37 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
                struct nfsd3_setaclargs *argp,
                struct nfsd3_attrstat *resp)
 {
+       struct inode *inode;
        svc_fh *fh;
        __be32 nfserr = 0;
+       int error;
 
        fh = fh_copy(&resp->fh, &argp->fh);
        nfserr = fh_verify(rqstp, &resp->fh, 0, NFSD_MAY_SATTR);
+       if (nfserr)
+               goto out;
 
-       if (!nfserr) {
-               nfserr = nfserrno( nfsd_set_posix_acl(
-                       fh, ACL_TYPE_ACCESS, argp->acl_access) );
-       }
-       if (!nfserr) {
-               nfserr = nfserrno( nfsd_set_posix_acl(
-                       fh, ACL_TYPE_DEFAULT, argp->acl_default) );
+       inode = fh->fh_dentry->d_inode;
+       if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
+               error = -EOPNOTSUPP;
+               goto out_errno;
        }
 
+       error = fh_want_write(fh);
+       if (error)
+               goto out_errno;
+
+       error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+       if (error)
+               goto out_drop_write;
+       error = inode->i_op->set_acl(inode, argp->acl_default,
+                                    ACL_TYPE_DEFAULT);
+
+out_drop_write:
+       fh_drop_write(fh);
+out_errno:
+       nfserr = nfserrno(error);
+out:
        /* argp->acl_{access,default} may have been allocated in
           nfs3svc_decode_setaclargs. */
        posix_acl_release(argp->acl_access);
index 8a50b3c18093b0bc3a6bd04bc80d7767ef8b7ae7..649ad7cf22044bb10bd6cb64527cba7295226a97 100644 (file)
 #include <linux/slab.h>
 #include <linux/nfs_fs.h>
 #include <linux/export.h>
+#include "nfsfh.h"
 #include "acl.h"
+#include "vfs.h"
 
+#define NFS4_ACL_TYPE_DEFAULT  0x01
+#define NFS4_ACL_DIR           0x02
+#define NFS4_ACL_OWNER         0x04
 
 /* mode bit translations: */
 #define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
@@ -130,36 +135,50 @@ static short ace2type(struct nfs4_ace *);
 static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
                                unsigned int);
 
-struct nfs4_acl *
-nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
-                       unsigned int flags)
+int
+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
+               struct nfs4_acl **acl)
 {
-       struct nfs4_acl *acl;
+       struct inode *inode = dentry->d_inode;
+       int error = 0;
+       struct posix_acl *pacl = NULL, *dpacl = NULL;
+       unsigned int flags = 0;
        int size = 0;
 
-       if (pacl) {
-               if (posix_acl_valid(pacl) < 0)
-                       return ERR_PTR(-EINVAL);
-               size += 2*pacl->a_count;
+       pacl = get_acl(inode, ACL_TYPE_ACCESS);
+       if (!pacl) {
+               pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+               if (IS_ERR(pacl))
+                       return PTR_ERR(pacl);
+               /* allocate for worst case: one (deny, allow) pair each: */
+               size += 2 * pacl->a_count;
        }
-       if (dpacl) {
-               if (posix_acl_valid(dpacl) < 0)
-                       return ERR_PTR(-EINVAL);
-               size += 2*dpacl->a_count;
+
+       if (S_ISDIR(inode->i_mode)) {
+               flags = NFS4_ACL_DIR;
+               dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
+               if (dpacl)
+                       size += 2 * dpacl->a_count;
+       } else {
+               dpacl = NULL;
        }
 
-       /* Allocate for worst case: one (deny, allow) pair each: */
-       acl = nfs4_acl_new(size);
-       if (acl == NULL)
-               return ERR_PTR(-ENOMEM);
+       *acl = nfs4_acl_new(size);
+       if (*acl == NULL) {
+               error = -ENOMEM;
+               goto out;
+       }
 
        if (pacl)
-               _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
+               _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
 
        if (dpacl)
-               _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
+               _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
 
-       return acl;
+ out:
+       posix_acl_release(pacl);
+       posix_acl_release(dpacl);
+       return error;
 }
 
 struct posix_acl_summary {
@@ -719,8 +738,9 @@ static void process_one_v4_ace(struct posix_acl_state *state,
        }
 }
 
-int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
-                           struct posix_acl **dpacl, unsigned int flags)
+static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
+               struct posix_acl **pacl, struct posix_acl **dpacl,
+               unsigned int flags)
 {
        struct posix_acl_state effective_acl_state, default_acl_state;
        struct nfs4_ace *ace;
@@ -780,6 +800,57 @@ out_estate:
        return ret;
 }
 
+__be32
+nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
+               struct nfs4_acl *acl)
+{
+       __be32 error;
+       int host_error;
+       struct dentry *dentry;
+       struct inode *inode;
+       struct posix_acl *pacl = NULL, *dpacl = NULL;
+       unsigned int flags = 0;
+
+       /* Get inode */
+       error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
+       if (error)
+               return error;
+
+       dentry = fhp->fh_dentry;
+       inode = dentry->d_inode;
+
+       if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
+               return nfserr_attrnotsupp;
+
+       if (S_ISDIR(inode->i_mode))
+               flags = NFS4_ACL_DIR;
+
+       host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
+       if (host_error == -EINVAL)
+               return nfserr_attrnotsupp;
+       if (host_error < 0)
+               goto out_nfserr;
+
+       host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
+       if (host_error < 0)
+               goto out_release;
+
+       if (S_ISDIR(inode->i_mode)) {
+               host_error = inode->i_op->set_acl(inode, dpacl,
+                                                 ACL_TYPE_DEFAULT);
+       }
+
+out_release:
+       posix_acl_release(pacl);
+       posix_acl_release(dpacl);
+out_nfserr:
+       if (host_error == -EOPNOTSUPP)
+               return nfserr_attrnotsupp;
+       else
+               return nfserrno(host_error);
+}
+
+
 static short
 ace2type(struct nfs4_ace *ace)
 {
@@ -798,9 +869,6 @@ ace2type(struct nfs4_ace *ace)
        return -1;
 }
 
-EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
-EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
-
 struct nfs4_acl *
 nfs4_acl_new(int n)
 {
@@ -862,7 +930,3 @@ nfs4_acl_write_who(int who, char *p)
        BUG();
        return -1;
 }
-
-EXPORT_SYMBOL(nfs4_acl_new);
-EXPORT_SYMBOL(nfs4_acl_get_whotype);
-EXPORT_SYMBOL(nfs4_acl_write_who);
index 419572f33b72dafaf04a770fb53e29e250e5f42b..825b8a99b99b42aaf1675518ea979a77b67c1955 100644 (file)
@@ -41,6 +41,7 @@
 #include "vfs.h"
 #include "current_stateid.h"
 #include "netns.h"
+#include "acl.h"
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
 #include <linux/security.h>
index 7eea63cada1d4a3ea5f9dd95401f83714689fcb0..1426eb66c8c699cf4104bde226986dda77ccc4c8 100644 (file)
@@ -468,158 +468,7 @@ out:
        return err;
 }
 
-#if defined(CONFIG_NFSD_V2_ACL) || \
-    defined(CONFIG_NFSD_V3_ACL) || \
-    defined(CONFIG_NFSD_V4)
-static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
-{
-       ssize_t buflen;
-       ssize_t ret;
-
-       buflen = vfs_getxattr(dentry, key, NULL, 0);
-       if (buflen <= 0)
-               return buflen;
-
-       *buf = kmalloc(buflen, GFP_KERNEL);
-       if (!*buf)
-               return -ENOMEM;
-
-       ret = vfs_getxattr(dentry, key, *buf, buflen);
-       if (ret < 0)
-               kfree(*buf);
-       return ret;
-}
-#endif
-
 #if defined(CONFIG_NFSD_V4)
-static int
-set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
-{
-       int len;
-       size_t buflen;
-       char *buf = NULL;
-       int error = 0;
-
-       buflen = posix_acl_xattr_size(pacl->a_count);
-       buf = kmalloc(buflen, GFP_KERNEL);
-       error = -ENOMEM;
-       if (buf == NULL)
-               goto out;
-
-       len = posix_acl_to_xattr(&init_user_ns, pacl, buf, buflen);
-       if (len < 0) {
-               error = len;
-               goto out;
-       }
-
-       error = vfs_setxattr(dentry, key, buf, len, 0);
-out:
-       kfree(buf);
-       return error;
-}
-
-__be32
-nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
-    struct nfs4_acl *acl)
-{
-       __be32 error;
-       int host_error;
-       struct dentry *dentry;
-       struct inode *inode;
-       struct posix_acl *pacl = NULL, *dpacl = NULL;
-       unsigned int flags = 0;
-
-       /* Get inode */
-       error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR);
-       if (error)
-               return error;
-
-       dentry = fhp->fh_dentry;
-       inode = dentry->d_inode;
-       if (S_ISDIR(inode->i_mode))
-               flags = NFS4_ACL_DIR;
-
-       host_error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
-       if (host_error == -EINVAL) {
-               return nfserr_attrnotsupp;
-       } else if (host_error < 0)
-               goto out_nfserr;
-
-       host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
-       if (host_error < 0)
-               goto out_release;
-
-       if (S_ISDIR(inode->i_mode))
-               host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
-
-out_release:
-       posix_acl_release(pacl);
-       posix_acl_release(dpacl);
-out_nfserr:
-       if (host_error == -EOPNOTSUPP)
-               return nfserr_attrnotsupp;
-       else
-               return nfserrno(host_error);
-}
-
-static struct posix_acl *
-_get_posix_acl(struct dentry *dentry, char *key)
-{
-       void *buf = NULL;
-       struct posix_acl *pacl = NULL;
-       int buflen;
-
-       buflen = nfsd_getxattr(dentry, key, &buf);
-       if (!buflen)
-               buflen = -ENODATA;
-       if (buflen <= 0)
-               return ERR_PTR(buflen);
-
-       pacl = posix_acl_from_xattr(&init_user_ns, buf, buflen);
-       kfree(buf);
-       return pacl;
-}
-
-int
-nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
-{
-       struct inode *inode = dentry->d_inode;
-       int error = 0;
-       struct posix_acl *pacl = NULL, *dpacl = NULL;
-       unsigned int flags = 0;
-
-       pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
-       if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
-               pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
-       if (IS_ERR(pacl)) {
-               error = PTR_ERR(pacl);
-               pacl = NULL;
-               goto out;
-       }
-
-       if (S_ISDIR(inode->i_mode)) {
-               dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
-               if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
-                       dpacl = NULL;
-               else if (IS_ERR(dpacl)) {
-                       error = PTR_ERR(dpacl);
-                       dpacl = NULL;
-                       goto out;
-               }
-               flags = NFS4_ACL_DIR;
-       }
-
-       *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
-       if (IS_ERR(*acl)) {
-               error = PTR_ERR(*acl);
-               *acl = NULL;
-       }
- out:
-       posix_acl_release(pacl);
-       posix_acl_release(dpacl);
-       return error;
-}
-
 /*
  * NFS junction information is stored in an extended attribute.
  */
@@ -2284,93 +2133,3 @@ out_nomem:
        nfsd_racache_shutdown();
        return -ENOMEM;
 }
-
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-struct posix_acl *
-nfsd_get_posix_acl(struct svc_fh *fhp, int type)
-{
-       struct inode *inode = fhp->fh_dentry->d_inode;
-       char *name;
-       void *value = NULL;
-       ssize_t size;
-       struct posix_acl *acl;
-
-       if (!IS_POSIXACL(inode))
-               return ERR_PTR(-EOPNOTSUPP);
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               name = POSIX_ACL_XATTR_ACCESS;
-               break;
-       case ACL_TYPE_DEFAULT:
-               name = POSIX_ACL_XATTR_DEFAULT;
-               break;
-       default:
-               return ERR_PTR(-EOPNOTSUPP);
-       }
-
-       size = nfsd_getxattr(fhp->fh_dentry, name, &value);
-       if (size < 0)
-               return ERR_PTR(size);
-
-       acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       kfree(value);
-       return acl;
-}
-
-int
-nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
-{
-       struct inode *inode = fhp->fh_dentry->d_inode;
-       char *name;
-       void *value = NULL;
-       size_t size;
-       int error;
-
-       if (!IS_POSIXACL(inode) ||
-           !inode->i_op->setxattr || !inode->i_op->removexattr)
-               return -EOPNOTSUPP;
-       switch(type) {
-               case ACL_TYPE_ACCESS:
-                       name = POSIX_ACL_XATTR_ACCESS;
-                       break;
-               case ACL_TYPE_DEFAULT:
-                       name = POSIX_ACL_XATTR_DEFAULT;
-                       break;
-               default:
-                       return -EOPNOTSUPP;
-       }
-
-       if (acl && acl->a_count) {
-               size = posix_acl_xattr_size(acl->a_count);
-               value = kmalloc(size, GFP_KERNEL);
-               if (!value)
-                       return -ENOMEM;
-               error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
-               if (error < 0)
-                       goto getout;
-               size = error;
-       } else
-               size = 0;
-
-       error = fh_want_write(fhp);
-       if (error)
-               goto getout;
-       if (size)
-               error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
-       else {
-               if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
-                       error = 0;
-               else {
-                       error = vfs_removexattr(fhp->fh_dentry, name);
-                       if (error == -ENODATA)
-                               error = 0;
-               }
-       }
-       fh_drop_write(fhp);
-
-getout:
-       kfree(value);
-       return error;
-}
-#endif  /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
index a4be2e3896704047f1aae87ac924990fb2d0f834..1bc1d440a1a5677899a7d85d6b5926bb2f3f7900 100644 (file)
@@ -52,9 +52,6 @@ __be32                nfsd_setattr(struct svc_rqst *, struct svc_fh *,
                                struct iattr *, int, time_t);
 int nfsd_mountpoint(struct dentry *, struct svc_export *);
 #ifdef CONFIG_NFSD_V4
-__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
-                    struct nfs4_acl *);
-int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
 __be32          nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
                    struct xdr_netobj *);
 #endif /* CONFIG_NFSD_V4 */
@@ -101,11 +98,6 @@ __be32              nfsd_statfs(struct svc_rqst *, struct svc_fh *,
 __be32         nfsd_permission(struct svc_rqst *, struct svc_export *,
                                struct dentry *, int);
 
-#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
-struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
-int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
-#endif
-
 static inline int fh_want_write(struct svc_fh *fh)
 {
        int ret = mnt_want_write(fh->fh_export->ex_path.mnt);
index 634a8b717b02199ee310180ba35c9f8947a5e897..266c2d7d50bdaed476be1a44fc0a12f3ac8b9625 100644 (file)
@@ -583,7 +583,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macceltic(void)
index 979e6265ac5e823d355ca9171d8a8debe6195347..9789c6057551a3c16a7de3d9b5cf7302ade3a85f 100644 (file)
@@ -513,7 +513,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_maccenteuro(void)
index dd3f675911ee3716a9a835f5fd428db3d723cd8f..bb19e7a07d436496b5ad2f4833dfb1da7c50f588 100644 (file)
@@ -583,7 +583,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_maccroatian(void)
index 1112c84dd8bb7183d5fec826cea8c06e866d0ee8..2a7dea36acba0e13d706a255868ce82af88dbd51 100644 (file)
@@ -478,7 +478,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_maccyrillic(void)
index 2de9158409c85ec468619e5f93289c5e133af66b..77b001653588076ea42a71a254bd2c42aa0e279d 100644 (file)
@@ -548,7 +548,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macgaelic(void)
index a863100828028f5f9d98a62f1dbacb1c62fa4ca0..1eccf499e2ebc5bb2aff772b17a834fec615d802 100644 (file)
@@ -478,7 +478,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macgreek(void)
index babe2998d5ced2d0a1a8d237edb4fe5a2cd25604..cbd0875c6d6948b3a7ada49d75c909c69da347ba 100644 (file)
@@ -583,7 +583,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_maciceland(void)
index 312364f010dcc7e5a8af3d95f9763c54f37f85d2..fba8357aaf03899d3929902070f8e2c01e91b541 100644 (file)
@@ -513,7 +513,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macinuit(void)
index 53ce0809cbd28eec842fab86b808c19b91c5dcc7..b6a98a5208cd6196b48b7d703c1a4a6ad953201e 100644 (file)
@@ -618,7 +618,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macroman(void)
index add6f7a0c6663c6ddf251bf749fc13812548d181..25547f023638453396876470e74cd66ba2b34ce1 100644 (file)
@@ -583,7 +583,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macromanian(void)
index dffa96d5de00243d29940c68dd613666d7fad25c..b5454bc7b7fa390b34f758d0ef49a54c9ece70ad 100644 (file)
@@ -583,7 +583,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_macturkish(void)
index 7020e940f74e9dbcb4f7a420d67391fa6532f779..a2620650d5e45f6d6a9e4113fbae7fcf29a5e25d 100644 (file)
@@ -148,7 +148,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_ascii(void)
index fea6bd5831dce3d84868316c424266c1232949fd..52ccd34b1e792370597b77f7d228c4d79bf96600 100644 (file)
@@ -232,13 +232,14 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian,
 }
 EXPORT_SYMBOL(utf16s_to_utf8s);
 
-int register_nls(struct nls_table * nls)
+int __register_nls(struct nls_table *nls, struct module *owner)
 {
        struct nls_table ** tmp = &tables;
 
        if (nls->next)
                return -EBUSY;
 
+       nls->owner = owner;
        spin_lock(&nls_lock);
        while (*tmp) {
                if (nls == *tmp) {
@@ -252,6 +253,7 @@ int register_nls(struct nls_table * nls)
        spin_unlock(&nls_lock);
        return 0;       
 }
+EXPORT_SYMBOL(__register_nls);
 
 int unregister_nls(struct nls_table * nls)
 {
@@ -538,7 +540,6 @@ struct nls_table *load_nls_default(void)
                return &default_table;
 }
 
-EXPORT_SYMBOL(register_nls);
 EXPORT_SYMBOL(unregister_nls);
 EXPORT_SYMBOL(unload_nls);
 EXPORT_SYMBOL(load_nls);
index c8471fe78e4e5893dade5b391b2d60dda9197bc6..ace3e19d3407671f36eaa5a43aaa27f341028e3c 100644 (file)
@@ -329,7 +329,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp1250(void)
index 1939b46e772f42a6c5ba0377bd6b8c1939030aa9..9273ddfd08a1eec6f2801101897150a46e947c48 100644 (file)
@@ -283,7 +283,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp1251(void)
index 8120ae2e091a78ebe3ee240c0bf35133ceff9a54..1caf5dfed85b7ec9c06688cfd97282ad6b807e36 100644 (file)
@@ -365,7 +365,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp1255(void)
index ff37a4628ce48e5c9e86d4febdeea81565dec65b..7ddb830da3fdb78a9384b026060f6633a32d4e21 100644 (file)
@@ -369,7 +369,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp437(void)
index f5576b8be1b92bb3e43f6a01226f5acae3e641e2..c593f683a0cd2139c68d82b7dd7bd8baffc36e01 100644 (file)
@@ -332,7 +332,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp737(void)
index 4905635d1c00986735d49df059cb0f2efab5b1c0..554c863745f2b6e12ae31afee3935b6fce825c1c 100644 (file)
@@ -301,7 +301,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp775(void)
index fe5bdad50e2b39ac4783653e8666b1c2be9a92de..56cccd14b40be93a1a49abe57aedfb472c2d9259 100644 (file)
@@ -297,7 +297,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp850(void)
index ceb1c0166dd8988909cfee453b79d94ab30213ff..7cdc05ac1d402e8d5a5eca44ec74eb06483abe45 100644 (file)
@@ -319,7 +319,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp852(void)
index cc7f5fb2e0c24849f401b47018270609d29ee5ab..7426eea05663731dd90b25b96902c31214a633ec 100644 (file)
@@ -281,7 +281,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp855(void)
index e418e198e8d866586e8317f7327dfdfc924c8188..098309733ebd1406316b7c7fb9dcd86f6a88b04c 100644 (file)
@@ -283,7 +283,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp857(void)
index a86c97d1aa3484747df369573918cbf01aa97a88..84224478e731a5f9f4e3c566cf78464479dfad3b 100644 (file)
@@ -346,7 +346,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp860(void)
index bd920227acdfd0869b450c8d0b58105cf9ae5037..dc873e4be092a233698a0b9fb5e45361af1cf64d 100644 (file)
@@ -369,7 +369,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp861(void)
index e9b68eb3daf04d21cb39ed60ab1d4b6120bbf24d..d5263e3c5566cf51f2d0892f2d57e735b62f8b52 100644 (file)
@@ -403,7 +403,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp862(void)
index f8a9b07ab4e2f64cc80d247b567250d90b034fea..051c9832e36a96e19da30441a95ce5688071d35a 100644 (file)
@@ -363,7 +363,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp863(void)
index 8d31f435fc6f9a31f662d929d6870402766688af..97eb1273b2f7456b10c172ab5e229b745f1e7f01 100644 (file)
@@ -389,7 +389,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp864(void)
index 4bd902fe3ec94065d05f3ab36515efac885f3e13..11121422852513544cba0d316668cdfc08225f4a 100644 (file)
@@ -369,7 +369,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp865(void)
index bdc7cb391398828330db1cfedb8c47d7174f3d3b..ffdcbc3fc38d71f2b4e258b660c3eb32c2a387f7 100644 (file)
@@ -287,7 +287,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp866(void)
index 9f283a2b151a2c2f7004ecdfceae58b5f3c53a06..3b5a345893543fb2702023c6796a72216efbdfd8 100644 (file)
@@ -297,7 +297,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp869(void)
index 0b3c4886f8c03d2927ecd9a16a13d964f5cb97e4..8dfaa10710fa7165c4b6261b0b0081a4f37357cf 100644 (file)
@@ -256,7 +256,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp874(void)
index 0ffed6f1cebb6cb8d9c5618cc4876c6f053457d3..67b7398e84832bcacd334a65e60cda21f0a045b4 100644 (file)
@@ -7914,7 +7914,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp932(void)
index 82770301bc3da82849a2118db40aaeb1e4b92d7c..c96546cfec9fd81b5c726121501ba7e4c1640690 100644 (file)
@@ -11092,7 +11092,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp936(void)
index 8a7a2fe85c65a7ca551f6417e0a3d181d9aa7e46..199171e97aa4a014ae0bdaecbf05759bad99b76b 100644 (file)
@@ -13927,7 +13927,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp949(void)
index ef2536829aa589a393d1b5d9528d1e28ab2ac47e..8e14187082098216c78d7bb9b39d269dd544eec5 100644 (file)
@@ -9463,7 +9463,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_cp950(void)
index 7424929a278b0088ba92772ffb1b3a7644864906..162b3f160353c6ab076644079c861a2b4f1fd736 100644 (file)
@@ -553,7 +553,6 @@ static struct nls_table table = {
        .charset        = "euc-jp",
        .uni2char       = uni2char,
        .char2uni       = char2uni,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_euc_jp(void)
index 7b951bb5849cb52e48a30dc8c3f3187949c581bb..69ac020d43b1ce0dc7fc640476faee082a91b6fc 100644 (file)
@@ -239,7 +239,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_1(void)
index c4d52ea9f0921a6530bc96de8e02529643856f9e..afb3f8f275f079df23746a779bcf0223fbba81b8 100644 (file)
@@ -267,7 +267,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_13(void)
index dc02600c7fe16828d3bb4688652bd46be363e485..046370f0b6f0ca1284aa70cadcc041fd1386be87 100644 (file)
@@ -323,7 +323,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_14(void)
index 3c7dfc832ef1309fb095d445a33ad529ebdd3a11..7e34a841a056727cd647784ef1eeca625fd3ea7e 100644 (file)
@@ -289,7 +289,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_15(void)
index a2d2197e4c7740e5ea808e196945b8806e74fbc8..7dd5711817414d2bc03564d28ca2249d15bcd0bf 100644 (file)
@@ -290,7 +290,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_2(void)
index a61e0daa3a860a6472e52b29f1b640b599f9b0a4..740b75ec44936919b7458f89e34f02fd83d914e4 100644 (file)
@@ -290,7 +290,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_3(void)
index e8ff555483b673526845585366b71ba573b27d04..8826021e32f59a2cf6323ecbbd2d8f4da1aa27ad 100644 (file)
@@ -290,7 +290,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_4(void)
index 4721e89301249c2e7e765ac19efdabee4cb9baec..7c04057a1ad82c44cc9903abbac1ddb6336086d8 100644 (file)
@@ -254,7 +254,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_5(void)
index 01a517d6d306a18fe7d48b811529a00a59c5eb39..d4a881400d74951308788241b1d7240c81d02c7a 100644 (file)
@@ -245,7 +245,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_6(void)
index 2d27b93ef19e152bd4415e6e9f62e8bcc2472394..37b75d825a754ec2690a62cf7f0a2ee2d28058ec 100644 (file)
@@ -299,7 +299,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_7(void)
index 694bf070c72102535c122499bfd0e88bb6adacf7..557b98250d3790b89a3883f9cb8a6cecbe201eaf 100644 (file)
@@ -254,7 +254,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_9(void)
index 43875310540dd83d3cf354013fdc0b91bbf35140..811f232fccfba77f79627f26aa338553d1cf3a6e 100644 (file)
@@ -305,7 +305,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_koi8_r(void)
index e7bc1d75c78c4e9a79a373707559ab51f091d456..a80a741a8676dc5a6ead28c9a584169050fc3c79 100644 (file)
@@ -55,7 +55,6 @@ static struct nls_table table = {
        .charset        = "koi8-ru",
        .uni2char       = uni2char,
        .char2uni       = char2uni,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_koi8_ru(void)
index 8c9f0292b5ae88318249c53708b31ae600dafa81..7e029e4c188a241ef37de1e2e419bf61dbf8eba3 100644 (file)
@@ -312,7 +312,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = charset2lower,
        .charset2upper  = charset2upper,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_koi8_u(void)
index 0d60a44acacd42b7eee10349a672a9ec9a74240a..afcfbc4a14dbf82c6d8b171477d8f5e0eb0dc00f 100644 (file)
@@ -46,7 +46,6 @@ static struct nls_table table = {
        .char2uni       = char2uni,
        .charset2lower  = identity,     /* no conversion */
        .charset2upper  = identity,
-       .owner          = THIS_MODULE,
 };
 
 static int __init init_nls_utf8(void)
index 58772623f02a90e7e7c4355921ba0c8457024175..0e792f5e3147c3cfcf38a980716075ea509b0e46 100644 (file)
@@ -16,12 +16,6 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 {
        struct fanotify_event_info *old, *new;
 
-#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       /* dont merge two permission events */
-       if ((old_fsn->mask & FAN_ALL_PERM_EVENTS) &&
-           (new_fsn->mask & FAN_ALL_PERM_EVENTS))
-               return false;
-#endif
        pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
        old = FANOTIFY_E(old_fsn);
        new = FANOTIFY_E(new_fsn);
@@ -34,14 +28,23 @@ static bool should_merge(struct fsnotify_event *old_fsn,
 }
 
 /* and the list better be locked by something too! */
-static struct fsnotify_event *fanotify_merge(struct list_head *list,
-                                            struct fsnotify_event *event)
+static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
 {
        struct fsnotify_event *test_event;
        bool do_merge = false;
 
        pr_debug("%s: list=%p event=%p\n", __func__, list, event);
 
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       /*
+        * Don't merge a permission event with any other event so that we know
+        * the event structure we have created in fanotify_handle_event() is the
+        * one we should check for permission response.
+        */
+       if (event->mask & FAN_ALL_PERM_EVENTS)
+               return 0;
+#endif
+
        list_for_each_entry_reverse(test_event, list, list) {
                if (should_merge(test_event, event)) {
                        do_merge = true;
@@ -50,10 +53,10 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list,
        }
 
        if (!do_merge)
-               return NULL;
+               return 0;
 
        test_event->mask |= event->mask;
-       return test_event;
+       return 1;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -149,7 +152,6 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        int ret = 0;
        struct fanotify_event_info *event;
        struct fsnotify_event *fsn_event;
-       struct fsnotify_event *notify_fsn_event;
 
        BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
        BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
@@ -188,21 +190,19 @@ static int fanotify_handle_event(struct fsnotify_group *group,
        event->response = 0;
 #endif
 
-       notify_fsn_event = fsnotify_add_notify_event(group, fsn_event,
-                                                    fanotify_merge);
-       if (notify_fsn_event) {
+       ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
+       if (ret) {
+               BUG_ON(mask & FAN_ALL_PERM_EVENTS);
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               if (IS_ERR(notify_fsn_event))
-                       return PTR_ERR(notify_fsn_event);
-               /* We need to ask about a different events after a merge... */
-               event = FANOTIFY_E(notify_fsn_event);
-               fsn_event = notify_fsn_event;
+               ret = 0;
        }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
-       if (fsn_event->mask & FAN_ALL_PERM_EVENTS)
+       if (mask & FAN_ALL_PERM_EVENTS) {
                ret = fanotify_get_response_from_access(group, event);
+               fsnotify_destroy_event(group, fsn_event);
+       }
 #endif
        return ret;
 }
index 0e90174a116a2c337f77af9e11760f1c21e00e43..32a2f034fb94b5915d1e8362ecbac21f362653fb 100644 (file)
@@ -4,6 +4,13 @@
 
 extern struct kmem_cache *fanotify_event_cachep;
 
+/*
+ * Lifetime of the structure differs for normal and permission events. In both
+ * cases the structure is allocated in fanotify_handle_event(). For normal
+ * events the structure is freed immediately after reporting it to userspace.
+ * For permission events we free it only after we receive response from
+ * userspace.
+ */
 struct fanotify_event_info {
        struct fsnotify_event fse;
        /*
index 57d7c083cb4b89c9c49858680a05e69c36b7ef09..b6175fa11bf856809d1ee6a43ee9b861980e9160 100644 (file)
@@ -319,7 +319,12 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
                        if (IS_ERR(kevent))
                                break;
                        ret = copy_event_to_user(group, kevent, buf);
-                       fsnotify_destroy_event(group, kevent);
+                       /*
+                        * Permission events get destroyed after we
+                        * receive response
+                        */
+                       if (!(kevent->mask & FAN_ALL_PERM_EVENTS))
+                               fsnotify_destroy_event(group, kevent);
                        if (ret < 0)
                                break;
                        buf += ret;
@@ -886,9 +891,9 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark,
 {
        return sys_fanotify_mark(fanotify_fd, flags,
 #ifdef __BIG_ENDIAN
-                               ((__u64)mask1 << 32) | mask0,
-#else
                                ((__u64)mask0 << 32) | mask1,
+#else
+                               ((__u64)mask1 << 32) | mask0,
 #endif
                                 dfd, pathname);
 }
index aad1a35e9af117fdc397cca897ba6f192f2de7a0..d5ee56348bb803fd0ddff46d4f3da7d0fa7016d1 100644 (file)
@@ -53,15 +53,13 @@ static bool event_compare(struct fsnotify_event *old_fsn,
        return false;
 }
 
-static struct fsnotify_event *inotify_merge(struct list_head *list,
-                                           struct fsnotify_event *event)
+static int inotify_merge(struct list_head *list,
+                         struct fsnotify_event *event)
 {
        struct fsnotify_event *last_event;
 
        last_event = list_entry(list->prev, struct fsnotify_event, list);
-       if (!event_compare(last_event, event))
-               return NULL;
-       return last_event;
+       return event_compare(last_event, event);
 }
 
 int inotify_handle_event(struct fsnotify_group *group,
@@ -73,9 +71,8 @@ int inotify_handle_event(struct fsnotify_group *group,
 {
        struct inotify_inode_mark *i_mark;
        struct inotify_event_info *event;
-       struct fsnotify_event *added_event;
        struct fsnotify_event *fsn_event;
-       int ret = 0;
+       int ret;
        int len = 0;
        int alloc_len = sizeof(struct inotify_event_info);
 
@@ -110,18 +107,16 @@ int inotify_handle_event(struct fsnotify_group *group,
        if (len)
                strcpy(event->name, file_name);
 
-       added_event = fsnotify_add_notify_event(group, fsn_event, inotify_merge);
-       if (added_event) {
+       ret = fsnotify_add_notify_event(group, fsn_event, inotify_merge);
+       if (ret) {
                /* Our event wasn't used in the end. Free it. */
                fsnotify_destroy_event(group, fsn_event);
-               if (IS_ERR(added_event))
-                       ret = PTR_ERR(added_event);
        }
 
        if (inode_mark->mask & IN_ONESHOT)
                fsnotify_destroy_mark(inode_mark, group);
 
-       return ret;
+       return 0;
 }
 
 static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group)
index 952237b8e2d27bbea9466bf41db33ba854b937c6..18b3c4427dcac0f2c9125581cc171be3f1eb3a9f 100644 (file)
@@ -79,15 +79,15 @@ void fsnotify_destroy_event(struct fsnotify_group *group,
 
 /*
  * Add an event to the group notification queue.  The group can later pull this
- * event off the queue to deal with.  If the event is successfully added to the
- * group's notification queue, a reference is taken on event.
+ * event off the queue to deal with.  The function returns 0 if the event was
+ * added to the queue, 1 if the event was merged with some other queued event.
  */
-struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
-                                                struct fsnotify_event *event,
-                                                struct fsnotify_event *(*merge)(struct list_head *,
-                                                                                struct fsnotify_event *))
+int fsnotify_add_notify_event(struct fsnotify_group *group,
+                             struct fsnotify_event *event,
+                             int (*merge)(struct list_head *,
+                                          struct fsnotify_event *))
 {
-       struct fsnotify_event *return_event = NULL;
+       int ret = 0;
        struct list_head *list = &group->notification_list;
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -98,14 +98,14 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
                /* Queue overflow event only if it isn't already queued */
                if (list_empty(&group->overflow_event.list))
                        event = &group->overflow_event;
-               return_event = event;
+               ret = 1;
        }
 
        if (!list_empty(list) && merge) {
-               return_event = merge(list, event);
-               if (return_event) {
+               ret = merge(list, event);
+               if (ret) {
                        mutex_unlock(&group->notification_mutex);
-                       return return_event;
+                       return ret;
                }
        }
 
@@ -115,7 +115,7 @@ struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
 
        wake_up(&group->notification_waitq);
        kill_fasync(&group->fsn_fa, SIGIO, POLL_IN);
-       return return_event;
+       return ret;
 }
 
 /*
index b4f788e0ca318955ab797f2350f8dffa320a53cb..555f4cddefe3a913d7c1d05fba89a1ea36fdd3c1 100644 (file)
@@ -160,36 +160,6 @@ static struct posix_acl *ocfs2_get_acl_nolock(struct inode *inode,
        return acl;
 }
 
-
-/*
- * Get posix acl.
- */
-static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
-{
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct buffer_head *di_bh = NULL;
-       struct posix_acl *acl;
-       int ret;
-
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return NULL;
-
-       ret = ocfs2_inode_lock(inode, &di_bh, 0);
-       if (ret < 0) {
-               mlog_errno(ret);
-               acl = ERR_PTR(ret);
-               return acl;
-       }
-
-       acl = ocfs2_get_acl_nolock(inode, type, di_bh);
-
-       ocfs2_inode_unlock(inode, 0);
-
-       brelse(di_bh);
-
-       return acl;
-}
-
 /*
  * Helper function to set i_mode in memory and disk. Some call paths
  * will not have di_bh or a journal handle to pass, in which case it
@@ -250,7 +220,7 @@ out:
 /*
  * Set the access or default ACL of an inode.
  */
-static int ocfs2_set_acl(handle_t *handle,
+int ocfs2_set_acl(handle_t *handle,
                         struct inode *inode,
                         struct buffer_head *di_bh,
                         int type,
@@ -313,6 +283,11 @@ static int ocfs2_set_acl(handle_t *handle,
        return ret;
 }
 
+int ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+       return ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
+}
+
 struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
 {
        struct ocfs2_super *osb;
@@ -334,200 +309,3 @@ struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type)
 
        return acl;
 }
-
-int ocfs2_acl_chmod(struct inode *inode)
-{
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct posix_acl *acl;
-       int ret;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return 0;
-
-       acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-       ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (ret)
-               return ret;
-       ret = ocfs2_set_acl(NULL, inode, NULL, ACL_TYPE_ACCESS,
-                           acl, NULL, NULL);
-       posix_acl_release(acl);
-       return ret;
-}
-
-/*
- * Initialize the ACLs of a new inode. If parent directory has default ACL,
- * then clone to new inode. Called from ocfs2_mknod.
- */
-int ocfs2_init_acl(handle_t *handle,
-                  struct inode *inode,
-                  struct inode *dir,
-                  struct buffer_head *di_bh,
-                  struct buffer_head *dir_bh,
-                  struct ocfs2_alloc_context *meta_ac,
-                  struct ocfs2_alloc_context *data_ac)
-{
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct posix_acl *acl = NULL;
-       int ret = 0, ret2;
-       umode_t mode;
-
-       if (!S_ISLNK(inode->i_mode)) {
-               if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
-                       acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT,
-                                                  dir_bh);
-                       if (IS_ERR(acl))
-                               return PTR_ERR(acl);
-               }
-               if (!acl) {
-                       mode = inode->i_mode & ~current_umask();
-                       ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
-                       if (ret) {
-                               mlog_errno(ret);
-                               goto cleanup;
-                       }
-               }
-       }
-       if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
-               if (S_ISDIR(inode->i_mode)) {
-                       ret = ocfs2_set_acl(handle, inode, di_bh,
-                                           ACL_TYPE_DEFAULT, acl,
-                                           meta_ac, data_ac);
-                       if (ret)
-                               goto cleanup;
-               }
-               mode = inode->i_mode;
-               ret = posix_acl_create(&acl, GFP_NOFS, &mode);
-               if (ret < 0)
-                       return ret;
-
-               ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
-               if (ret2) {
-                       mlog_errno(ret2);
-                       ret = ret2;
-                       goto cleanup;
-               }
-               if (ret > 0) {
-                       ret = ocfs2_set_acl(handle, inode,
-                                           di_bh, ACL_TYPE_ACCESS,
-                                           acl, meta_ac, data_ac);
-               }
-       }
-cleanup:
-       posix_acl_release(acl);
-       return ret;
-}
-
-static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry,
-                                         char *list,
-                                         size_t list_len,
-                                         const char *name,
-                                         size_t name_len,
-                                         int type)
-{
-       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
-       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return 0;
-
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-       return size;
-}
-
-static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry,
-                                          char *list,
-                                          size_t list_len,
-                                          const char *name,
-                                          size_t name_len,
-                                          int type)
-{
-       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
-       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return 0;
-
-       if (list && size <= list_len)
-               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-       return size;
-}
-
-static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
-{
-       struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
-       struct posix_acl *acl;
-       int ret;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       acl = ocfs2_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       ret = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
-       return ret;
-}
-
-static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-       struct posix_acl *acl;
-       int ret = 0;
-
-       if (strcmp(name, "") != 0)
-               return -EINVAL;
-       if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
-               return -EOPNOTSUPP;
-
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl))
-                       return PTR_ERR(acl);
-               else if (acl) {
-                       ret = posix_acl_valid(acl);
-                       if (ret)
-                               goto cleanup;
-               }
-       } else
-               acl = NULL;
-
-       ret = ocfs2_set_acl(NULL, inode, NULL, type, acl, NULL, NULL);
-
-cleanup:
-       posix_acl_release(acl);
-       return ret;
-}
-
-const struct xattr_handler ocfs2_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .list   = ocfs2_xattr_list_acl_access,
-       .get    = ocfs2_xattr_get_acl,
-       .set    = ocfs2_xattr_set_acl,
-};
-
-const struct xattr_handler ocfs2_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .list   = ocfs2_xattr_list_acl_default,
-       .get    = ocfs2_xattr_get_acl,
-       .set    = ocfs2_xattr_set_acl,
-};
index 071fbd380f2f52889fe4ddc459df3bf603d7629e..3fce68d086251a6e26ea9805361e3a1ccb351d46 100644 (file)
@@ -27,10 +27,13 @@ struct ocfs2_acl_entry {
 };
 
 struct posix_acl *ocfs2_iop_get_acl(struct inode *inode, int type);
-extern int ocfs2_acl_chmod(struct inode *);
-extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *,
-                         struct buffer_head *, struct buffer_head *,
-                         struct ocfs2_alloc_context *,
-                         struct ocfs2_alloc_context *);
+int ocfs2_iop_set_acl(struct inode *inode, struct posix_acl *acl, int type);
+int ocfs2_set_acl(handle_t *handle,
+                        struct inode *inode,
+                        struct buffer_head *di_bh,
+                        int type,
+                        struct posix_acl *acl,
+                        struct ocfs2_alloc_context *meta_ac,
+                        struct ocfs2_alloc_context *data_ac);
 
 #endif /* OCFS2_ACL_H */
index f42eecef64781ecac5af385adbb9a91b19f02e51..d77d71ead8d12071a52b1f0f63c66f1077c93f84 100644 (file)
@@ -1236,7 +1236,7 @@ bail:
                dqput(transfer_to[qtype]);
 
        if (!status && attr->ia_valid & ATTR_MODE) {
-               status = ocfs2_acl_chmod(inode);
+               status = posix_acl_chmod(inode, inode->i_mode);
                if (status < 0)
                        mlog_errno(status);
        }
@@ -2662,6 +2662,7 @@ const struct inode_operations ocfs2_file_iops = {
        .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
 };
 
 const struct inode_operations ocfs2_special_file_iops = {
@@ -2669,6 +2670,7 @@ const struct inode_operations ocfs2_special_file_iops = {
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
 };
 
 /*
index 4f791f6d27d0463f8bef77dc20a5f5274df8ddea..f4d609be940086794ff8e64b1ed7cd832ba517f5 100644 (file)
@@ -230,6 +230,7 @@ static int ocfs2_mknod(struct inode *dir,
        struct ocfs2_dir_lookup_result lookup = { NULL, };
        sigset_t oldset;
        int did_block_signals = 0;
+       struct posix_acl *default_acl = NULL, *acl = NULL;
 
        trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
                          (unsigned long long)OCFS2_I(dir)->ip_blkno,
@@ -331,6 +332,12 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
+       status = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (status) {
+               mlog_errno(status);
+               goto leave;
+       }
+
        handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
                                                            S_ISDIR(mode),
                                                            xattr_credits));
@@ -379,8 +386,17 @@ static int ocfs2_mknod(struct inode *dir,
                inc_nlink(dir);
        }
 
-       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
-                               meta_ac, data_ac);
+       if (default_acl) {
+               status = ocfs2_set_acl(handle, inode, new_fe_bh,
+                                      ACL_TYPE_DEFAULT, default_acl,
+                                      meta_ac, data_ac);
+       }
+       if (!status && acl) {
+               status = ocfs2_set_acl(handle, inode, new_fe_bh,
+                                      ACL_TYPE_ACCESS, acl,
+                                      meta_ac, data_ac);
+       }
+
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -419,6 +435,10 @@ static int ocfs2_mknod(struct inode *dir,
        d_instantiate(dentry, inode);
        status = 0;
 leave:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        if (status < 0 && did_quota_inode)
                dquot_free_inode(inode);
        if (handle)
@@ -948,7 +968,7 @@ leave:
        ocfs2_free_dir_lookup_result(&orphan_insert);
        ocfs2_free_dir_lookup_result(&lookup);
 
-       if (status && (status != -ENOTEMPTY))
+       if (status && (status != -ENOTEMPTY) && (status != -ENOENT))
                mlog_errno(status);
 
        return status;
@@ -2504,4 +2524,5 @@ const struct inode_operations ocfs2_dir_iops = {
        .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
 };
index 55767e1ba72492431dcb3ae9fe204526d93f28d2..6ba4bcbc479601bcad6a98ba7a73ccc80dc40710 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/quotaops.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/posix_acl.h>
 
 struct ocfs2_cow_context {
        struct inode *inode;
@@ -4268,11 +4269,20 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
        struct inode *inode = old_dentry->d_inode;
        struct buffer_head *old_bh = NULL;
        struct inode *new_orphan_inode = NULL;
+       struct posix_acl *default_acl, *acl;
+       umode_t mode;
 
        if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
                return -EOPNOTSUPP;
 
-       error = ocfs2_create_inode_in_orphan(dir, inode->i_mode,
+       mode = inode->i_mode;
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error) {
+               mlog_errno(error);
+               goto out;
+       }
+
+       error = ocfs2_create_inode_in_orphan(dir, mode,
                                             &new_orphan_inode);
        if (error) {
                mlog_errno(error);
@@ -4303,11 +4313,16 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
        /* If the security isn't preserved, we need to re-initialize them. */
        if (!preserve) {
                error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
-                                                   &new_dentry->d_name);
+                                                   &new_dentry->d_name,
+                                                   default_acl, acl);
                if (error)
                        mlog_errno(error);
        }
 out:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        if (!error) {
                error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode,
                                                       new_dentry);
index f0a1326d9bba89812f5ae736938ca3cfbee1284d..185fa3b7f962a482f06f9926cca946185672c7d6 100644 (file)
@@ -99,8 +99,8 @@ static struct ocfs2_xattr_def_value_root def_xv = {
 
 const struct xattr_handler *ocfs2_xattr_handlers[] = {
        &ocfs2_xattr_user_handler,
-       &ocfs2_xattr_acl_access_handler,
-       &ocfs2_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
        &ocfs2_xattr_trusted_handler,
        &ocfs2_xattr_security_handler,
        NULL
@@ -109,9 +109,9 @@ const struct xattr_handler *ocfs2_xattr_handlers[] = {
 static const struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
        [OCFS2_XATTR_INDEX_USER]        = &ocfs2_xattr_user_handler,
        [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
-                                       = &ocfs2_xattr_acl_access_handler,
+                                       = &posix_acl_access_xattr_handler,
        [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
-                                       = &ocfs2_xattr_acl_default_handler,
+                                       = &posix_acl_default_xattr_handler,
        [OCFS2_XATTR_INDEX_TRUSTED]     = &ocfs2_xattr_trusted_handler,
        [OCFS2_XATTR_INDEX_SECURITY]    = &ocfs2_xattr_security_handler,
 };
@@ -7190,10 +7190,12 @@ out:
  */
 int ocfs2_init_security_and_acl(struct inode *dir,
                                struct inode *inode,
-                               const struct qstr *qstr)
+                               const struct qstr *qstr,
+                               struct posix_acl *default_acl,
+                               struct posix_acl *acl)
 {
-       int ret = 0;
        struct buffer_head *dir_bh = NULL;
+       int ret = 0;
 
        ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
        if (ret) {
@@ -7207,9 +7209,10 @@ int ocfs2_init_security_and_acl(struct inode *dir,
                goto leave;
        }
 
-       ret = ocfs2_init_acl(NULL, inode, dir, NULL, dir_bh, NULL, NULL);
-       if (ret)
-               mlog_errno(ret);
+       if (!ret && default_acl)
+               ret = ocfs2_iop_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+       if (!ret && acl)
+               ret = ocfs2_iop_set_acl(inode, acl, ACL_TYPE_ACCESS);
 
        ocfs2_inode_unlock(dir, 0);
        brelse(dir_bh);
index 19f134e896a9a8bdd69a387015819e4ebc3c2705..f10d5b93c366c8a7d12ddc1c90766ea88ed3dc56 100644 (file)
@@ -40,8 +40,6 @@ struct ocfs2_security_xattr_info {
 extern const struct xattr_handler ocfs2_xattr_user_handler;
 extern const struct xattr_handler ocfs2_xattr_trusted_handler;
 extern const struct xattr_handler ocfs2_xattr_security_handler;
-extern const struct xattr_handler ocfs2_xattr_acl_access_handler;
-extern const struct xattr_handler ocfs2_xattr_acl_default_handler;
 extern const struct xattr_handler *ocfs2_xattr_handlers[];
 
 ssize_t ocfs2_listxattr(struct dentry *, char *, size_t);
@@ -96,5 +94,7 @@ int ocfs2_reflink_xattrs(struct inode *old_inode,
                         bool preserve_security);
 int ocfs2_init_security_and_acl(struct inode *dir,
                                struct inode *inode,
-                               const struct qstr *qstr);
+                               const struct qstr *qstr,
+                               struct posix_acl *default_acl,
+                               struct posix_acl *acl);
 #endif /* OCFS2_XATTR_H */
index 551e61ba15b6047c909594968163eaf26c8cb605..38bae5a0ea257ebc414aef89727f3a652d904c96 100644 (file)
@@ -1,10 +1,8 @@
 /*
- * linux/fs/posix_acl.c
+ * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
  *
- *  Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
- *
- *  Fixes from William Schumacher incorporated on 15 March 2001.
- *     (Reported by Charles Bertsch, <CBertsch@microtest.com>).
+ * Fixes from William Schumacher incorporated on 15 March 2001.
+ *    (Reported by Charles Bertsch, <CBertsch@microtest.com>).
  */
 
 /*
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
 #include <linux/export.h>
-
-#include <linux/errno.h>
+#include <linux/user_namespace.h>
 
 struct posix_acl **acl_by_type(struct inode *inode, int type)
 {
@@ -97,6 +96,33 @@ void forget_all_cached_acls(struct inode *inode)
 }
 EXPORT_SYMBOL(forget_all_cached_acls);
 
+struct posix_acl *get_acl(struct inode *inode, int type)
+{
+       struct posix_acl *acl;
+
+       acl = get_cached_acl(inode, type);
+       if (acl != ACL_NOT_CACHED)
+               return acl;
+
+       if (!IS_POSIXACL(inode))
+               return NULL;
+
+       /*
+        * A filesystem can force a ACL callback by just never filling the
+        * ACL cache. But normally you'd fill the cache either at inode
+        * instantiation time, or on the first ->get_acl call.
+        *
+        * If the filesystem doesn't have a get_acl() function at all, we'll
+        * just create the negative cache entry.
+        */
+       if (!inode->i_op->get_acl) {
+               set_cached_acl(inode, type, NULL);
+               return NULL;
+       }
+       return inode->i_op->get_acl(inode, type);
+}
+EXPORT_SYMBOL(get_acl);
+
 /*
  * Init a fresh posix_acl
  */
@@ -402,7 +428,7 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p)
 /*
  * Modify the ACL for the chmod syscall.
  */
-static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
+static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
 {
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
        struct posix_acl_entry *pa, *pe;
@@ -448,7 +474,7 @@ static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
 }
 
 int
-posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
+__posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
@@ -463,15 +489,15 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
        *acl = clone;
        return err;
 }
-EXPORT_SYMBOL(posix_acl_create);
+EXPORT_SYMBOL(__posix_acl_create);
 
 int
-posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
+__posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
 {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
        if (clone) {
-               err = posix_acl_chmod_masq(clone, mode);
+               err = __posix_acl_chmod_masq(clone, mode);
                if (err) {
                        posix_acl_release(clone);
                        clone = NULL;
@@ -481,4 +507,382 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
        *acl = clone;
        return err;
 }
+EXPORT_SYMBOL(__posix_acl_chmod);
+
+int
+posix_acl_chmod(struct inode *inode, umode_t mode)
+{
+       struct posix_acl *acl;
+       int ret = 0;
+
+       if (!IS_POSIXACL(inode))
+               return 0;
+       if (!inode->i_op->set_acl)
+               return -EOPNOTSUPP;
+
+       acl = get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR_OR_NULL(acl))
+               return PTR_ERR(acl);
+
+       ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
+       if (ret)
+               return ret;
+       ret = inode->i_op->set_acl(inode, acl, ACL_TYPE_ACCESS);
+       posix_acl_release(acl);
+       return ret;
+}
 EXPORT_SYMBOL(posix_acl_chmod);
+
+int
+posix_acl_create(struct inode *dir, umode_t *mode,
+               struct posix_acl **default_acl, struct posix_acl **acl)
+{
+       struct posix_acl *p;
+       int ret;
+
+       if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
+               goto no_acl;
+
+       p = get_acl(dir, ACL_TYPE_DEFAULT);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       if (!p) {
+               *mode &= ~current_umask();
+               goto no_acl;
+       }
+
+       *acl = posix_acl_clone(p, GFP_NOFS);
+       if (!*acl)
+               return -ENOMEM;
+
+       ret = posix_acl_create_masq(*acl, mode);
+       if (ret < 0) {
+               posix_acl_release(*acl);
+               return -ENOMEM;
+       }
+
+       if (ret == 0) {
+               posix_acl_release(*acl);
+               *acl = NULL;
+       }
+
+       if (!S_ISDIR(*mode)) {
+               posix_acl_release(p);
+               *default_acl = NULL;
+       } else {
+               *default_acl = p;
+       }
+       return 0;
+
+no_acl:
+       *default_acl = NULL;
+       *acl = NULL;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(posix_acl_create);
+
+/*
+ * Fix up the uids and gids in posix acl extended attributes in place.
+ */
+static void posix_acl_fix_xattr_userns(
+       struct user_namespace *to, struct user_namespace *from,
+       void *value, size_t size)
+{
+       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
+       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+       int count;
+       kuid_t uid;
+       kgid_t gid;
+
+       if (!value)
+               return;
+       if (size < sizeof(posix_acl_xattr_header))
+               return;
+       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
+               return;
+
+       count = posix_acl_xattr_count(size);
+       if (count < 0)
+               return;
+       if (count == 0)
+               return;
+
+       for (end = entry + count; entry != end; entry++) {
+               switch(le16_to_cpu(entry->e_tag)) {
+               case ACL_USER:
+                       uid = make_kuid(from, le32_to_cpu(entry->e_id));
+                       entry->e_id = cpu_to_le32(from_kuid(to, uid));
+                       break;
+               case ACL_GROUP:
+                       gid = make_kgid(from, le32_to_cpu(entry->e_id));
+                       entry->e_id = cpu_to_le32(from_kgid(to, gid));
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+void posix_acl_fix_xattr_from_user(void *value, size_t size)
+{
+       struct user_namespace *user_ns = current_user_ns();
+       if (user_ns == &init_user_ns)
+               return;
+       posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
+}
+
+void posix_acl_fix_xattr_to_user(void *value, size_t size)
+{
+       struct user_namespace *user_ns = current_user_ns();
+       if (user_ns == &init_user_ns)
+               return;
+       posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
+}
+
+/*
+ * Convert from extended attribute to in-memory representation.
+ */
+struct posix_acl *
+posix_acl_from_xattr(struct user_namespace *user_ns,
+                    const void *value, size_t size)
+{
+       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
+       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+       int count;
+       struct posix_acl *acl;
+       struct posix_acl_entry *acl_e;
+
+       if (!value)
+               return NULL;
+       if (size < sizeof(posix_acl_xattr_header))
+                return ERR_PTR(-EINVAL);
+       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       count = posix_acl_xattr_count(size);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+       
+       acl = posix_acl_alloc(count, GFP_NOFS);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+       acl_e = acl->a_entries;
+       
+       for (end = entry + count; entry != end; acl_e++, entry++) {
+               acl_e->e_tag  = le16_to_cpu(entry->e_tag);
+               acl_e->e_perm = le16_to_cpu(entry->e_perm);
+
+               switch(acl_e->e_tag) {
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               break;
+
+                       case ACL_USER:
+                               acl_e->e_uid =
+                                       make_kuid(user_ns,
+                                                 le32_to_cpu(entry->e_id));
+                               if (!uid_valid(acl_e->e_uid))
+                                       goto fail;
+                               break;
+                       case ACL_GROUP:
+                               acl_e->e_gid =
+                                       make_kgid(user_ns,
+                                                 le32_to_cpu(entry->e_id));
+                               if (!gid_valid(acl_e->e_gid))
+                                       goto fail;
+                               break;
+
+                       default:
+                               goto fail;
+               }
+       }
+       return acl;
+
+fail:
+       posix_acl_release(acl);
+       return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL (posix_acl_from_xattr);
+
+/*
+ * Convert from in-memory to extended attribute representation.
+ */
+int
+posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
+                  void *buffer, size_t size)
+{
+       posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
+       posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
+       int real_size, n;
+
+       real_size = posix_acl_xattr_size(acl->a_count);
+       if (!buffer)
+               return real_size;
+       if (real_size > size)
+               return -ERANGE;
+       
+       ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
+
+       for (n=0; n < acl->a_count; n++, ext_entry++) {
+               const struct posix_acl_entry *acl_e = &acl->a_entries[n];
+               ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
+               ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
+               switch(acl_e->e_tag) {
+               case ACL_USER:
+                       ext_entry->e_id =
+                               cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
+                       break;
+               case ACL_GROUP:
+                       ext_entry->e_id =
+                               cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
+                       break;
+               default:
+                       ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
+                       break;
+               }
+       }
+       return real_size;
+}
+EXPORT_SYMBOL (posix_acl_to_xattr);
+
+static int
+posix_acl_xattr_get(struct dentry *dentry, const char *name,
+               void *value, size_t size, int type)
+{
+       struct posix_acl *acl;
+       int error;
+
+       if (!IS_POSIXACL(dentry->d_inode))
+               return -EOPNOTSUPP;
+       if (S_ISLNK(dentry->d_inode->i_mode))
+               return -EOPNOTSUPP;
+
+       acl = get_acl(dentry->d_inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl == NULL)
+               return -ENODATA;
+
+       error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
+       posix_acl_release(acl);
+
+       return error;
+}
+
+static int
+posix_acl_xattr_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+{
+       struct inode *inode = dentry->d_inode;
+       struct posix_acl *acl = NULL;
+       int ret;
+
+       if (!IS_POSIXACL(inode))
+               return -EOPNOTSUPP;
+       if (!inode->i_op->set_acl)
+               return -EOPNOTSUPP;
+
+       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+               return value ? -EACCES : 0;
+       if (!inode_owner_or_capable(inode))
+               return -EPERM;
+
+       if (value) {
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+
+               if (acl) {
+                       ret = posix_acl_valid(acl);
+                       if (ret)
+                               goto out;
+               }
+       }
+
+       ret = inode->i_op->set_acl(inode, acl, type);
+out:
+       posix_acl_release(acl);
+       return ret;
+}
+
+static size_t
+posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
+{
+       const char *xname;
+       size_t size;
+
+       if (!IS_POSIXACL(dentry->d_inode))
+               return -EOPNOTSUPP;
+       if (S_ISLNK(dentry->d_inode->i_mode))
+               return -EOPNOTSUPP;
+
+       if (type == ACL_TYPE_ACCESS)
+               xname = POSIX_ACL_XATTR_ACCESS;
+       else
+               xname = POSIX_ACL_XATTR_DEFAULT;
+
+       size = strlen(xname) + 1;
+       if (list && size <= list_size)
+               memcpy(list, xname, size);
+       return size;
+}
+
+const struct xattr_handler posix_acl_access_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags = ACL_TYPE_ACCESS,
+       .list = posix_acl_xattr_list,
+       .get = posix_acl_xattr_get,
+       .set = posix_acl_xattr_set,
+};
+EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
+
+const struct xattr_handler posix_acl_default_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags = ACL_TYPE_DEFAULT,
+       .list = posix_acl_xattr_list,
+       .get = posix_acl_xattr_get,
+       .set = posix_acl_xattr_set,
+};
+EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
+
+int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+{
+       int error;
+
+       if (type == ACL_TYPE_ACCESS) {
+               error = posix_acl_equiv_mode(acl, &inode->i_mode);
+               if (error < 0)
+                       return 0;
+               if (error == 0)
+                       acl = NULL;
+       }
+
+       inode->i_ctime = CURRENT_TIME;
+       set_cached_acl(inode, type, acl);
+       return 0;
+}
+
+int simple_acl_create(struct inode *dir, struct inode *inode)
+{
+       struct posix_acl *default_acl, *acl;
+       int error;
+
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (error)
+               return error;
+
+       set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
+       set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
+       return 0;
+}
index 2e8caa62da78a71cc1ee46ce49634aab9408a779..89558810381c497389c184856d30efd0a2ce9717 100644 (file)
@@ -27,7 +27,6 @@
 
 static const struct super_operations qnx4_sops;
 
-static void qnx4_put_super(struct super_block *sb);
 static struct inode *qnx4_alloc_inode(struct super_block *sb);
 static void qnx4_destroy_inode(struct inode *inode);
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
@@ -37,7 +36,6 @@ static const struct super_operations qnx4_sops =
 {
        .alloc_inode    = qnx4_alloc_inode,
        .destroy_inode  = qnx4_destroy_inode,
-       .put_super      = qnx4_put_super,
        .statfs         = qnx4_statfs,
        .remount_fs     = qnx4_remount,
 };
@@ -148,18 +146,19 @@ static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
  * it really _is_ a qnx4 filesystem, and to check the size
  * of the directory entry.
  */
-static const char *qnx4_checkroot(struct super_block *sb)
+static const char *qnx4_checkroot(struct super_block *sb,
+                                 struct qnx4_super_block *s)
 {
        struct buffer_head *bh;
        struct qnx4_inode_entry *rootdir;
        int rd, rl;
        int i, j;
 
-       if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/')
+       if (s->RootDir.di_fname[0] != '/' || s->RootDir.di_fname[1] != '\0')
                return "no qnx4 filesystem (no root dir).";
        QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id));
-       rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
-       rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size);
+       rd = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_blk) - 1;
+       rl = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_size);
        for (j = 0; j < rl; j++) {
                bh = sb_bread(sb, rd + j);      /* root dir, first block */
                if (bh == NULL)
@@ -189,7 +188,6 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        struct inode *root;
        const char *errmsg;
        struct qnx4_sb_info *qs;
-       int ret = -EINVAL;
 
        qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
        if (!qs)
@@ -198,67 +196,50 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
 
        sb_set_blocksize(s, QNX4_BLOCK_SIZE);
 
+       s->s_op = &qnx4_sops;
+       s->s_magic = QNX4_SUPER_MAGIC;
+       s->s_flags |= MS_RDONLY;        /* Yup, read-only yet */
+
        /* Check the superblock signature. Since the qnx4 code is
           dangerous, we should leave as quickly as possible
           if we don't belong here... */
        bh = sb_bread(s, 1);
        if (!bh) {
                printk(KERN_ERR "qnx4: unable to read the superblock\n");
-               goto outnobh;
+               return -EINVAL;
        }
-       if ( le32_to_cpup((__le32*) bh->b_data) != QNX4_SUPER_MAGIC ) {
-               if (!silent)
-                       printk(KERN_ERR "qnx4: wrong fsid in superblock.\n");
-               goto out;
-       }
-       s->s_op = &qnx4_sops;
-       s->s_magic = QNX4_SUPER_MAGIC;
-       s->s_flags |= MS_RDONLY;        /* Yup, read-only yet */
-       qnx4_sb(s)->sb_buf = bh;
-       qnx4_sb(s)->sb = (struct qnx4_super_block *) bh->b_data;
-
 
        /* check before allocating dentries, inodes, .. */
-       errmsg = qnx4_checkroot(s);
+       errmsg = qnx4_checkroot(s, (struct qnx4_super_block *) bh->b_data);
+       brelse(bh);
        if (errmsg != NULL) {
                if (!silent)
                        printk(KERN_ERR "qnx4: %s\n", errmsg);
-               goto out;
+               return -EINVAL;
        }
 
        /* does root not have inode number QNX4_ROOT_INO ?? */
        root = qnx4_iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
        if (IS_ERR(root)) {
                printk(KERN_ERR "qnx4: get inode failed\n");
-               ret = PTR_ERR(root);
-               goto outb;
+               return PTR_ERR(root);
        }
 
-       ret = -ENOMEM;
        s->s_root = d_make_root(root);
        if (s->s_root == NULL)
-               goto outb;
+               return -ENOMEM;
 
-       brelse(bh);
        return 0;
-
-      outb:
-       kfree(qs->BitMap);
-      out:
-       brelse(bh);
-      outnobh:
-       kfree(qs);
-       s->s_fs_info = NULL;
-       return ret;
 }
 
-static void qnx4_put_super(struct super_block *sb)
+static void qnx4_kill_sb(struct super_block *sb)
 {
        struct qnx4_sb_info *qs = qnx4_sb(sb);
-       kfree( qs->BitMap );
-       kfree( qs );
-       sb->s_fs_info = NULL;
-       return;
+       kill_block_super(sb);
+       if (qs) {
+               kfree(qs->BitMap);
+               kfree(qs);
+       }
 }
 
 static int qnx4_readpage(struct file *file, struct page *page)
@@ -409,7 +390,7 @@ static struct file_system_type qnx4_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "qnx4",
        .mount          = qnx4_mount,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = qnx4_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("qnx4");
index 34e2d329c97e057f330d83f835fd111f931607be..c9b1be2c164dd9339b94cddd2a9d21ad2abd7577 100644 (file)
@@ -10,8 +10,6 @@
 #endif
 
 struct qnx4_sb_info {
-       struct buffer_head      *sb_buf;        /* superblock buffer */
-       struct qnx4_super_block *sb;            /* our superblock */
        unsigned int            Version;        /* may be useful */
        struct qnx4_inode_entry *BitMap;        /* useful */
 };
index 1193ffd0356547b63cdf0a503a2eb68ae84d8ba6..edc5746a902a090ce4dbda6b8b1205e729dff5b3 100644 (file)
@@ -964,9 +964,9 @@ out:
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE3(readv, unsigned long, fd,
+COMPAT_SYSCALL_DEFINE3(readv, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
-               unsigned long, vlen)
+               compat_ulong_t, vlen)
 {
        struct fd f = fdget(fd);
        ssize_t ret;
@@ -1001,9 +1001,9 @@ COMPAT_SYSCALL_DEFINE4(preadv64, unsigned long, fd,
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE5(preadv, unsigned long, fd,
+COMPAT_SYSCALL_DEFINE5(preadv, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
-               unsigned long, vlen, u32, pos_low, u32, pos_high)
+               compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        return compat_sys_preadv64(fd, vec, vlen, pos);
@@ -1031,9 +1031,9 @@ out:
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE3(writev, unsigned long, fd,
+COMPAT_SYSCALL_DEFINE3(writev, compat_ulong_t, fd,
                const struct compat_iovec __user *, vec,
-               unsigned long, vlen)
+               compat_ulong_t, vlen)
 {
        struct fd f = fdget(fd);
        ssize_t ret;
@@ -1068,9 +1068,9 @@ COMPAT_SYSCALL_DEFINE4(pwritev64, unsigned long, fd,
        return ret;
 }
 
-COMPAT_SYSCALL_DEFINE5(pwritev, unsigned long, fd,
+COMPAT_SYSCALL_DEFINE5(pwritev, compat_ulong_t, fd,
                const struct compat_iovec __user *,vec,
-               unsigned long, vlen, u32, pos_low, u32, pos_high)
+               compat_ulong_t, vlen, u32, pos_low, u32, pos_high)
 {
        loff_t pos = ((loff_t)pos_high << 32) | pos_low;
        return compat_sys_pwritev64(fd, vec, vlen, pos);
index f096b80e73d8145dc35bcdb36f008d29a61f07d9..4a211f5b34b81f00dc123c251a3adc7aff9dcf93 100644 (file)
@@ -48,18 +48,18 @@ static inline int reiserfs_acl_count(size_t size)
 
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
 struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
+int reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 int reiserfs_acl_chmod(struct inode *inode);
 int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
                                 struct inode *dir, struct dentry *dentry,
                                 struct inode *inode);
 int reiserfs_cache_default_acl(struct inode *dir);
-extern const struct xattr_handler reiserfs_posix_acl_default_handler;
-extern const struct xattr_handler reiserfs_posix_acl_access_handler;
 
 #else
 
 #define reiserfs_cache_default_acl(inode) 0
 #define reiserfs_get_acl NULL
+#define reiserfs_set_acl NULL
 
 static inline int reiserfs_acl_chmod(struct inode *inode)
 {
index dcaafcfc23b007c845f490a4f293cc485c324b51..ed58d843d57856ac3cdc87288465d0d5156708e9 100644 (file)
@@ -260,4 +260,5 @@ const struct inode_operations reiserfs_file_inode_operations = {
        .removexattr = reiserfs_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
+       .set_acl = reiserfs_set_acl,
 };
index dc5236f6de1be129e44caf8f78f16d010d7ad7fb..e825f8b63e6b7433c125e040117de525a2d0cf31 100644 (file)
@@ -1522,6 +1522,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
        .removexattr = reiserfs_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
+       .set_acl = reiserfs_set_acl,
 };
 
 /*
@@ -1538,8 +1539,6 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
        .listxattr = reiserfs_listxattr,
        .removexattr = reiserfs_removexattr,
        .permission = reiserfs_permission,
-       .get_acl = reiserfs_get_acl,
-
 };
 
 /*
@@ -1553,4 +1552,5 @@ const struct inode_operations reiserfs_special_inode_operations = {
        .removexattr = reiserfs_removexattr,
        .permission = reiserfs_permission,
        .get_acl = reiserfs_get_acl,
+       .set_acl = reiserfs_set_acl,
 };
index a958444a75fc310627d56de6a37e28a15a99273a..02b0b7d0f7d532e0ed0238161118ae627f5d9b7c 100644 (file)
@@ -419,7 +419,7 @@ int reiserfs_proc_info_init(struct super_block *sb)
        char *s;
 
        /* Some block devices use /'s */
-       strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
+       strlcpy(b, sb->s_id, BDEVNAME_SIZE);
        s = strchr(b, '/');
        if (s)
                *s = '!';
@@ -449,7 +449,7 @@ int reiserfs_proc_info_done(struct super_block *sb)
                char *s;
 
                /* Some block devices use /'s */
-               strlcpy(b, reiserfs_bdevname(sb), BDEVNAME_SIZE);
+               strlcpy(b, sb->s_id, BDEVNAME_SIZE);
                s = strchr(b, '/');
                if (s)
                        *s = '!';
index dfb617b2bad2ae1ada39a9ff36684793cfed51f1..8d06adf899488a53e13e97b5d2973ca536e430b0 100644 (file)
@@ -608,14 +608,6 @@ int reiserfs_resize(struct super_block *, unsigned long);
 
 #define SB_DISK_JOURNAL_HEAD(s) (SB_JOURNAL(s)->j_header_bh->)
 
-/* A safe version of the "bdevname", which returns the "s_id" field of
- * a superblock or else "Null superblock" if the super block is NULL.
- */
-static inline char *reiserfs_bdevname(struct super_block *s)
-{
-       return (s == NULL) ? "Null superblock" : s->s_id;
-}
-
 #define reiserfs_is_journal_aborted(journal) (unlikely (__reiserfs_is_journal_aborted (journal)))
 static inline int __reiserfs_is_journal_aborted(struct reiserfs_journal
                                                *journal)
index 3ead145dadc406646f742f519befe3ef9a2db6b9..2c803353f8ac4f70099f7cef6a590c46556c21d6 100644 (file)
@@ -1479,7 +1479,7 @@ static int read_super_block(struct super_block *s, int offset)
        if (!bh) {
                reiserfs_warning(s, "sh-2006",
                                 "bread failed (dev %s, block %lu, size %lu)",
-                                reiserfs_bdevname(s), offset / s->s_blocksize,
+                                s->s_id, offset / s->s_blocksize,
                                 s->s_blocksize);
                return 1;
        }
@@ -1500,7 +1500,7 @@ static int read_super_block(struct super_block *s, int offset)
        if (!bh) {
                reiserfs_warning(s, "sh-2007",
                                 "bread failed (dev %s, block %lu, size %lu)",
-                                reiserfs_bdevname(s), offset / s->s_blocksize,
+                                s->s_id, offset / s->s_blocksize,
                                 s->s_blocksize);
                return 1;
        }
@@ -1509,7 +1509,7 @@ static int read_super_block(struct super_block *s, int offset)
        if (sb_blocksize(rs) != s->s_blocksize) {
                reiserfs_warning(s, "sh-2011", "can't find a reiserfs "
                                 "filesystem on (dev %s, block %Lu, size %lu)",
-                                reiserfs_bdevname(s),
+                                s->s_id,
                                 (unsigned long long)bh->b_blocknr,
                                 s->s_blocksize);
                brelse(bh);
@@ -1825,7 +1825,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        /* try new format (64-th 1k block), which can contain reiserfs super block */
        else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
                SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
-                     reiserfs_bdevname(s));
+                     s->s_id);
                goto error_unlocked;
        }
 
index 8a9e2dcfe004919da6fe48e4c292c7ddfeef8476..5cdfbd638b5c929382d844d358105619301eed48 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/stat.h>
 #include <linux/quotaops.h>
 #include <linux/security.h>
+#include <linux/posix_acl_xattr.h>
 
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
@@ -904,8 +905,8 @@ static const struct xattr_handler *reiserfs_xattr_handlers[] = {
        &reiserfs_xattr_security_handler,
 #endif
 #ifdef CONFIG_REISERFS_FS_POSIX_ACL
-       &reiserfs_posix_acl_access_handler,
-       &reiserfs_posix_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL
 };
index 06c04f73da6529d012ee0c8b0d364cef939709ea..a6ce532402dc7ec9851e18fe572c3ad1faf14a2a 100644 (file)
 #include "acl.h"
 #include <asm/uaccess.h>
 
-static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
+static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,
                            struct inode *inode, int type,
                            struct posix_acl *acl);
 
-static int
-posix_acl_set(struct dentry *dentry, const char *name, const void *value,
-               size_t size, int flags, int type)
+
+int
+reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl;
        int error, error2;
        struct reiserfs_transaction_handle th;
        size_t jcreate_blocks;
-       if (!reiserfs_posixacl(inode->i_sb))
-               return -EOPNOTSUPP;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (value) {
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-               if (IS_ERR(acl)) {
-                       return PTR_ERR(acl);
-               } else if (acl) {
-                       error = posix_acl_valid(acl);
-                       if (error)
-                               goto release_and_out;
-               }
-       } else
-               acl = NULL;
+       int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
+
 
        /* Pessimism: We can't assume that anything from the xattr root up
         * has been created. */
@@ -51,7 +35,7 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value,
        error = journal_begin(&th, inode->i_sb, jcreate_blocks);
        reiserfs_write_unlock(inode->i_sb);
        if (error == 0) {
-               error = reiserfs_set_acl(&th, inode, type, acl);
+               error = __reiserfs_set_acl(&th, inode, type, acl);
                reiserfs_write_lock(inode->i_sb);
                error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
                reiserfs_write_unlock(inode->i_sb);
@@ -59,36 +43,13 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value,
                        error = error2;
        }
 
-      release_and_out:
-       posix_acl_release(acl);
-       return error;
-}
-
-static int
-posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
-               size_t size, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (!reiserfs_posixacl(dentry->d_sb))
-               return -EOPNOTSUPP;
-
-       acl = reiserfs_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-       error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
-       posix_acl_release(acl);
-
        return error;
 }
 
 /*
  * Convert from filesystem to in-memory representation.
  */
-static struct posix_acl *posix_acl_from_disk(const void *value, size_t size)
+static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)
 {
        const char *end = (char *)value + size;
        int n, count;
@@ -158,7 +119,7 @@ static struct posix_acl *posix_acl_from_disk(const void *value, size_t size)
 /*
  * Convert from in-memory to filesystem representation.
  */
-static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
+static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
 {
        reiserfs_acl_header *ext_acl;
        char *e;
@@ -221,10 +182,6 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
        int size;
        int retval;
 
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
@@ -257,7 +214,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
        } else if (retval < 0) {
                acl = ERR_PTR(retval);
        } else {
-               acl = posix_acl_from_disk(value, retval);
+               acl = reiserfs_posix_acl_from_disk(value, retval);
        }
        if (!IS_ERR(acl))
                set_cached_acl(inode, type, acl);
@@ -273,7 +230,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
  * BKL held [before 2.5.x]
  */
 static int
-reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
+__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
                 int type, struct posix_acl *acl)
 {
        char *name;
@@ -281,9 +238,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
        size_t size = 0;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                name = POSIX_ACL_XATTR_ACCESS;
@@ -307,7 +261,7 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
        }
 
        if (acl) {
-               value = posix_acl_to_disk(acl, &size);
+               value = reiserfs_posix_acl_to_disk(acl, &size);
                if (IS_ERR(value))
                        return (int)PTR_ERR(value);
        }
@@ -343,7 +297,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
                             struct inode *dir, struct dentry *dentry,
                             struct inode *inode)
 {
-       struct posix_acl *acl;
+       struct posix_acl *default_acl, *acl;
        int err = 0;
 
        /* ACLs only get applied to files and directories */
@@ -363,37 +317,28 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
                goto apply_umask;
        }
 
-       acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
+       err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (err)
+               return err;
 
+       if (default_acl) {
+               err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
+                                        default_acl);
+               posix_acl_release(default_acl);
+       }
        if (acl) {
-               /* Copy the default ACL to the default ACL of a new directory */
-               if (S_ISDIR(inode->i_mode)) {
-                       err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
-                                              acl);
-                       if (err)
-                               goto cleanup;
-               }
-
-               /* Now we reconcile the new ACL and the mode,
-                  potentially modifying both */
-               err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
-               if (err < 0)
-                       return err;
-
-               /* If we need an ACL.. */
-               if (err > 0)
-                       err = reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS, acl);
-             cleanup:
+               if (!err)
+                       err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,
+                                                acl);
                posix_acl_release(acl);
-       } else {
-             apply_umask:
-               /* no ACL, apply umask */
-               inode->i_mode &= ~current_umask();
        }
 
        return err;
+
+      apply_umask:
+       /* no ACL, apply umask */
+       inode->i_mode &= ~current_umask();
+       return err;
 }
 
 /* This is used to cache the default acl before a new object is created.
@@ -442,84 +387,11 @@ int reiserfs_cache_default_acl(struct inode *inode)
  */
 int reiserfs_acl_chmod(struct inode *inode)
 {
-       struct reiserfs_transaction_handle th;
-       struct posix_acl *acl;
-       size_t size;
-       int error;
-
        if (IS_PRIVATE(inode))
                return 0;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
-           !reiserfs_posixacl(inode->i_sb)) {
+           !reiserfs_posixacl(inode->i_sb))
                return 0;
-       }
 
-       acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (!acl)
-               return 0;
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       error = posix_acl_chmod(&acl, GFP_NOFS, inode->i_mode);
-       if (error)
-               return error;
-
-       size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
-       reiserfs_write_lock(inode->i_sb);
-       error = journal_begin(&th, inode->i_sb, size * 2);
-       reiserfs_write_unlock(inode->i_sb);
-       if (!error) {
-               int error2;
-               error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
-               reiserfs_write_lock(inode->i_sb);
-               error2 = journal_end(&th, inode->i_sb, size * 2);
-               reiserfs_write_unlock(inode->i_sb);
-               if (error2)
-                       error = error2;
-       }
-       posix_acl_release(acl);
-       return error;
-}
-
-static size_t posix_acl_access_list(struct dentry *dentry, char *list,
-                                   size_t list_size, const char *name,
-                                   size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-       if (!reiserfs_posixacl(dentry->d_sb))
-               return 0;
-       if (list && size <= list_size)
-               memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-       return size;
+       return posix_acl_chmod(inode, inode->i_mode);
 }
-
-const struct xattr_handler reiserfs_posix_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags = ACL_TYPE_ACCESS,
-       .get = posix_acl_get,
-       .set = posix_acl_set,
-       .list = posix_acl_access_list,
-};
-
-static size_t posix_acl_default_list(struct dentry *dentry, char *list,
-                                    size_t list_size, const char *name,
-                                    size_t name_len, int type)
-{
-       const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-       if (!reiserfs_posixacl(dentry->d_sb))
-               return 0;
-       if (list && size <= list_size)
-               memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-       return size;
-}
-
-const struct xattr_handler reiserfs_posix_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags = ACL_TYPE_DEFAULT,
-       .get = posix_acl_get,
-       .set = posix_acl_set,
-       .list = posix_acl_default_list,
-};
diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c
deleted file mode 100644 (file)
index 9fbea87..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * linux/fs/xattr_acl.c
- *
- * Almost all from linux/fs/ext2/acl.c:
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
- */
-
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/posix_acl_xattr.h>
-#include <linux/gfp.h>
-#include <linux/user_namespace.h>
-
-/*
- * Fix up the uids and gids in posix acl extended attributes in place.
- */
-static void posix_acl_fix_xattr_userns(
-       struct user_namespace *to, struct user_namespace *from,
-       void *value, size_t size)
-{
-       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
-       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
-       int count;
-       kuid_t uid;
-       kgid_t gid;
-
-       if (!value)
-               return;
-       if (size < sizeof(posix_acl_xattr_header))
-               return;
-       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
-               return;
-
-       count = posix_acl_xattr_count(size);
-       if (count < 0)
-               return;
-       if (count == 0)
-               return;
-
-       for (end = entry + count; entry != end; entry++) {
-               switch(le16_to_cpu(entry->e_tag)) {
-               case ACL_USER:
-                       uid = make_kuid(from, le32_to_cpu(entry->e_id));
-                       entry->e_id = cpu_to_le32(from_kuid(to, uid));
-                       break;
-               case ACL_GROUP:
-                       gid = make_kgid(from, le32_to_cpu(entry->e_id));
-                       entry->e_id = cpu_to_le32(from_kgid(to, gid));
-                       break;
-               default:
-                       break;
-               }
-       }
-}
-
-void posix_acl_fix_xattr_from_user(void *value, size_t size)
-{
-       struct user_namespace *user_ns = current_user_ns();
-       if (user_ns == &init_user_ns)
-               return;
-       posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
-}
-
-void posix_acl_fix_xattr_to_user(void *value, size_t size)
-{
-       struct user_namespace *user_ns = current_user_ns();
-       if (user_ns == &init_user_ns)
-               return;
-       posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
-}
-
-/*
- * Convert from extended attribute to in-memory representation.
- */
-struct posix_acl *
-posix_acl_from_xattr(struct user_namespace *user_ns,
-                    const void *value, size_t size)
-{
-       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
-       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
-       int count;
-       struct posix_acl *acl;
-       struct posix_acl_entry *acl_e;
-
-       if (!value)
-               return NULL;
-       if (size < sizeof(posix_acl_xattr_header))
-                return ERR_PTR(-EINVAL);
-       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
-               return ERR_PTR(-EOPNOTSUPP);
-
-       count = posix_acl_xattr_count(size);
-       if (count < 0)
-               return ERR_PTR(-EINVAL);
-       if (count == 0)
-               return NULL;
-       
-       acl = posix_acl_alloc(count, GFP_NOFS);
-       if (!acl)
-               return ERR_PTR(-ENOMEM);
-       acl_e = acl->a_entries;
-       
-       for (end = entry + count; entry != end; acl_e++, entry++) {
-               acl_e->e_tag  = le16_to_cpu(entry->e_tag);
-               acl_e->e_perm = le16_to_cpu(entry->e_perm);
-
-               switch(acl_e->e_tag) {
-                       case ACL_USER_OBJ:
-                       case ACL_GROUP_OBJ:
-                       case ACL_MASK:
-                       case ACL_OTHER:
-                               break;
-
-                       case ACL_USER:
-                               acl_e->e_uid =
-                                       make_kuid(user_ns,
-                                                 le32_to_cpu(entry->e_id));
-                               if (!uid_valid(acl_e->e_uid))
-                                       goto fail;
-                               break;
-                       case ACL_GROUP:
-                               acl_e->e_gid =
-                                       make_kgid(user_ns,
-                                                 le32_to_cpu(entry->e_id));
-                               if (!gid_valid(acl_e->e_gid))
-                                       goto fail;
-                               break;
-
-                       default:
-                               goto fail;
-               }
-       }
-       return acl;
-
-fail:
-       posix_acl_release(acl);
-       return ERR_PTR(-EINVAL);
-}
-EXPORT_SYMBOL (posix_acl_from_xattr);
-
-/*
- * Convert from in-memory to extended attribute representation.
- */
-int
-posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
-                  void *buffer, size_t size)
-{
-       posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
-       posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
-       int real_size, n;
-
-       real_size = posix_acl_xattr_size(acl->a_count);
-       if (!buffer)
-               return real_size;
-       if (real_size > size)
-               return -ERANGE;
-       
-       ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
-
-       for (n=0; n < acl->a_count; n++, ext_entry++) {
-               const struct posix_acl_entry *acl_e = &acl->a_entries[n];
-               ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
-               ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
-               switch(acl_e->e_tag) {
-               case ACL_USER:
-                       ext_entry->e_id =
-                               cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
-                       break;
-               case ACL_GROUP:
-                       ext_entry->e_id =
-                               cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
-                       break;
-               default:
-                       ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
-                       break;
-               }
-       }
-       return real_size;
-}
-EXPORT_SYMBOL (posix_acl_to_xattr);
index 370eb3e121d1b2f292c65ddabd660ad08ae65537..0ecec1896f25439f198c53c93bc058ff3bff9c89 100644 (file)
@@ -124,16 +124,12 @@ struct posix_acl *
 xfs_get_acl(struct inode *inode, int type)
 {
        struct xfs_inode *ip = XFS_I(inode);
-       struct posix_acl *acl;
+       struct posix_acl *acl = NULL;
        struct xfs_acl *xfs_acl;
        unsigned char *ea_name;
        int error;
        int len;
 
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        trace_xfs_get_acl(ip);
 
        switch (type) {
@@ -164,10 +160,8 @@ xfs_get_acl(struct inode *inode, int type)
                 * cache entry, for any other error assume it is transient and
                 * leave the cache entry as ACL_NOT_CACHED.
                 */
-               if (error == -ENOATTR) {
-                       acl = NULL;
+               if (error == -ENOATTR)
                        goto out_update_cache;
-               }
                goto out;
        }
 
@@ -183,15 +177,12 @@ out:
 }
 
 STATIC int
-xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+__xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 {
        struct xfs_inode *ip = XFS_I(inode);
        unsigned char *ea_name;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                ea_name = SGI_ACL_FILE;
@@ -282,131 +273,23 @@ posix_acl_default_exists(struct inode *inode)
        return xfs_acl_exists(inode, SGI_ACL_DEFAULT);
 }
 
-/*
- * No need for i_mutex because the inode is not yet exposed to the VFS.
- */
 int
-xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
+xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       umode_t mode = inode->i_mode;
-       int error = 0, inherit = 0;
-
-       if (S_ISDIR(inode->i_mode)) {
-               error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
-               if (error)
-                       goto out;
-       }
-
-       error = posix_acl_create(&acl, GFP_KERNEL, &mode);
-       if (error < 0)
-               return error;
-
-       /*
-        * If posix_acl_create returns a positive value we need to
-        * inherit a permission that can't be represented using the Unix
-        * mode bits and we actually need to set an ACL.
-        */
-       if (error > 0)
-               inherit = 1;
-
-       error = xfs_set_mode(inode, mode);
-       if (error)
-               goto out;
-
-       if (inherit)
-               error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
-
-out:
-       posix_acl_release(acl);
-       return error;
-}
-
-int
-xfs_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-
-       error = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (error)
-               return error;
-
-       error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
-       posix_acl_release(acl);
-       return error;
-}
-
-static int
-xfs_xattr_acl_get(struct dentry *dentry, const char *name,
-               void *value, size_t size, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       acl = xfs_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-
-       error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-xfs_xattr_acl_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl = NULL;
        int error = 0;
 
-       if (flags & XATTR_CREATE)
-               return -EINVAL;
-       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-               return value ? -EACCES : 0;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (!value)
+       if (!acl)
                goto set_acl;
 
-       acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       if (!acl) {
-               /*
-                * acl_set_file(3) may request that we set default ACLs with
-                * zero length -- defend (gracefully) against that here.
-                */
-               goto out;
-       }
-       if (IS_ERR(acl)) {
-               error = PTR_ERR(acl);
-               goto out;
-       }
-
-       error = posix_acl_valid(acl);
-       if (error)
-               goto out_release;
-
        error = -EINVAL;
        if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
-               goto out_release;
+               return error;
 
        if (type == ACL_TYPE_ACCESS) {
                umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
-                       posix_acl_release(acl);
                        acl = NULL;
 
                        if (error < 0)
@@ -415,27 +298,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
 
                error = xfs_set_mode(inode, mode);
                if (error)
-                       goto out_release;
+                       return error;
        }
 
  set_acl:
-       error = xfs_set_acl(inode, type, acl);
- out_release:
-       posix_acl_release(acl);
- out:
-       return error;
+       return __xfs_set_acl(inode, type, acl);
 }
-
-const struct xattr_handler xfs_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .get    = xfs_xattr_acl_get,
-       .set    = xfs_xattr_acl_set,
-};
-
-const struct xattr_handler xfs_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .get    = xfs_xattr_acl_get,
-       .set    = xfs_xattr_acl_set,
-};
index 4016a567b83cc2e00d46b5f4629bfc83785a7dff..5dc163744511b7c4de1f93e1dd33080d8becd062 100644 (file)
@@ -60,20 +60,15 @@ struct xfs_acl {
 
 #ifdef CONFIG_XFS_POSIX_ACL
 extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
-extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
-extern int xfs_acl_chmod(struct inode *inode);
+extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int posix_acl_access_exists(struct inode *inode);
 extern int posix_acl_default_exists(struct inode *inode);
-
-extern const struct xattr_handler xfs_xattr_acl_access_handler;
-extern const struct xattr_handler xfs_xattr_acl_default_handler;
 #else
 static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
 {
        return NULL;
 }
-# define xfs_inherit_acl(inode, default_acl)           0
-# define xfs_acl_chmod(inode)                          0
+# define xfs_set_acl                                   NULL
 # define posix_acl_access_exists(inode)                        0
 # define posix_acl_default_exists(inode)               0
 #endif /* CONFIG_XFS_POSIX_ACL */
index 9fccfb59429119be16786e1fd2d9b6104546ef93..51757113a822abc57334bbc25f0251671fdd3266 100644 (file)
@@ -445,8 +445,8 @@ _xfs_buf_find(
        numbytes = BBTOB(numblks);
 
        /* Check for IOs smaller than the sector size / not sector aligned */
-       ASSERT(!(numbytes < (1 << btp->bt_sshift)));
-       ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask));
+       ASSERT(!(numbytes < btp->bt_meta_sectorsize));
+       ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_meta_sectormask));
 
        /*
         * Corrupted block numbers can get through to here, unfortunately, so we
@@ -1599,9 +1599,9 @@ xfs_setsize_buftarg(
        unsigned int            blocksize,
        unsigned int            sectorsize)
 {
-       btp->bt_bsize = blocksize;
-       btp->bt_sshift = ffs(sectorsize) - 1;
-       btp->bt_smask = sectorsize - 1;
+       /* Set up metadata sector size info */
+       btp->bt_meta_sectorsize = sectorsize;
+       btp->bt_meta_sectormask = sectorsize - 1;
 
        if (set_blocksize(btp->bt_bdev, sectorsize)) {
                char name[BDEVNAME_SIZE];
@@ -1614,6 +1614,10 @@ xfs_setsize_buftarg(
                return EINVAL;
        }
 
+       /* Set up device logical sector size mask */
+       btp->bt_logical_sectorsize = bdev_logical_block_size(btp->bt_bdev);
+       btp->bt_logical_sectormask = bdev_logical_block_size(btp->bt_bdev) - 1;
+
        return 0;
 }
 
index 1cf21a4a9f221de465299bf820fa710c3b3aa40e..995339534db6a4b65c6ec332055734f7415ca621 100644 (file)
@@ -88,14 +88,28 @@ typedef unsigned int xfs_buf_flags_t;
  */
 #define XFS_BSTATE_DISPOSE      (1 << 0)       /* buffer being discarded */
 
+/*
+ * The xfs_buftarg contains 2 notions of "sector size" -
+ *
+ * 1) The metadata sector size, which is the minimum unit and
+ *    alignment of IO which will be performed by metadata operations.
+ * 2) The device logical sector size
+ *
+ * The first is specified at mkfs time, and is stored on-disk in the
+ * superblock's sb_sectsize.
+ *
+ * The latter is derived from the underlying device, and controls direct IO
+ * alignment constraints.
+ */
 typedef struct xfs_buftarg {
        dev_t                   bt_dev;
        struct block_device     *bt_bdev;
        struct backing_dev_info *bt_bdi;
        struct xfs_mount        *bt_mount;
-       unsigned int            bt_bsize;
-       unsigned int            bt_sshift;
-       size_t                  bt_smask;
+       unsigned int            bt_meta_sectorsize;
+       size_t                  bt_meta_sectormask;
+       size_t                  bt_logical_sectorsize;
+       size_t                  bt_logical_sectormask;
 
        /* LRU control structures */
        struct shrinker         bt_shrinker;
index e001215926326c6a87ce1d5d9887a11aafeb84ca..2e7989e3a2d67374d17e5086ec3b15bfbcb32e2d 100644 (file)
@@ -261,7 +261,8 @@ xfs_file_aio_read(
                xfs_buftarg_t   *target =
                        XFS_IS_REALTIME_INODE(ip) ?
                                mp->m_rtdev_targp : mp->m_ddev_targp;
-               if ((pos & target->bt_smask) || (size & target->bt_smask)) {
+               /* DIO must be aligned to device logical sector size */
+               if ((pos | size) & target->bt_logical_sectormask) {
                        if (pos == i_size_read(inode))
                                return 0;
                        return -XFS_ERROR(EINVAL);
@@ -641,9 +642,11 @@ xfs_file_dio_aio_write(
        struct xfs_buftarg      *target = XFS_IS_REALTIME_INODE(ip) ?
                                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
-       if ((pos & target->bt_smask) || (count & target->bt_smask))
+       /* DIO must be aligned to device logical sector size */
+       if ((pos | count) & target->bt_logical_sectormask)
                return -XFS_ERROR(EINVAL);
 
+       /* "unaligned" here means not aligned to a filesystem block */
        if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
                unaligned_io = 1;
 
index 518aa56b8f2e46d1602bb800c03f5c3d06b9fb38..bcfe61202115510b22509ad49aadc16bcbbb4368 100644 (file)
@@ -1583,7 +1583,7 @@ xfs_file_ioctl(
                        XFS_IS_REALTIME_INODE(ip) ?
                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
-               da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
+               da.d_mem =  da.d_miniosz = target->bt_logical_sectorsize;
                da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
 
                if (copy_to_user(arg, &da, sizeof(da)))
index 0ce1d759156e48ae092d566d30e713d7e597f29c..f35d5c953ff953dcde133c4b55568d1920db3589 100644 (file)
@@ -123,7 +123,7 @@ xfs_vn_mknod(
 {
        struct inode    *inode;
        struct xfs_inode *ip = NULL;
-       struct posix_acl *default_acl = NULL;
+       struct posix_acl *default_acl, *acl;
        struct xfs_name name;
        int             error;
 
@@ -139,14 +139,9 @@ xfs_vn_mknod(
                rdev = 0;
        }
 
-       if (IS_POSIXACL(dir)) {
-               default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
-               if (IS_ERR(default_acl))
-                       return PTR_ERR(default_acl);
-
-               if (!default_acl)
-                       mode &= ~current_umask();
-       }
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
+               return error;
 
        xfs_dentry_to_name(&name, dentry, mode);
        error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
@@ -159,22 +154,30 @@ xfs_vn_mknod(
        if (unlikely(error))
                goto out_cleanup_inode;
 
+#ifdef CONFIG_XFS_POSIX_ACL
        if (default_acl) {
-               error = -xfs_inherit_acl(inode, default_acl);
-               default_acl = NULL;
-               if (unlikely(error))
+               error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               if (error)
                        goto out_cleanup_inode;
        }
-
+       if (acl) {
+               error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               if (error)
+                       goto out_cleanup_inode;
+       }
+#endif
 
        d_instantiate(dentry, inode);
+ out_free_acl:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        return -error;
 
  out_cleanup_inode:
        xfs_cleanup_inode(dir, inode, dentry);
- out_free_acl:
-       posix_acl_release(default_acl);
-       return -error;
+       goto out_free_acl;
 }
 
 STATIC int
@@ -391,18 +394,6 @@ xfs_vn_follow_link(
        return NULL;
 }
 
-STATIC void
-xfs_vn_put_link(
-       struct dentry   *dentry,
-       struct nameidata *nd,
-       void            *p)
-{
-       char            *s = nd_get_link(nd);
-
-       if (!IS_ERR(s))
-               kfree(s);
-}
-
 STATIC int
 xfs_vn_getattr(
        struct vfsmount         *mnt,
@@ -688,7 +679,7 @@ xfs_setattr_nonsize(
         *           Posix ACL code seems to care about this issue either.
         */
        if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
-               error = -xfs_acl_chmod(inode);
+               error = -posix_acl_chmod(inode, inode->i_mode);
                if (error)
                        return XFS_ERROR(error);
        }
@@ -1045,6 +1036,7 @@ xfs_vn_fiemap(
 
 static const struct inode_operations xfs_inode_operations = {
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1072,6 +1064,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1098,6 +1091,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1110,8 +1104,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 static const struct inode_operations xfs_symlink_inode_operations = {
        .readlink               = generic_readlink,
        .follow_link            = xfs_vn_follow_link,
-       .put_link               = xfs_vn_put_link,
-       .get_acl                = xfs_get_acl,
+       .put_link               = kfree_put_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
index d2c5057b5cc4b4b701d05478e045cbf02a3ed408..1c34e4335920021d5829c5507be2f2c6c6bf60e1 100644 (file)
@@ -30,7 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *);
 /*
  * Internal setattr interfaces.
  */
-#define XFS_ATTR_NOACL         0x01    /* Don't call xfs_acl_chmod */
+#define XFS_ATTR_NOACL         0x01    /* Don't call posix_acl_chmod */
 
 extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
                               int flags);
index 9d479073ba415d6b482fbecbf160b6b99e4e859c..78ed92a46fdd3323c9bada9a35257f839285c630 100644 (file)
@@ -102,8 +102,8 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
        &xfs_xattr_trusted_handler,
        &xfs_xattr_security_handler,
 #ifdef CONFIG_XFS_POSIX_ACL
-       &xfs_xattr_acl_access_handler,
-       &xfs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL
 };
index db09234589409760b91cb9e696472a3e828476f9..8e4f41d9af4d47279e13a33edd317ce5de32e451 100644 (file)
@@ -558,6 +558,18 @@ static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
 }
 #endif
 
+#ifndef pmd_move_must_withdraw
+static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl,
+                                        spinlock_t *old_pmd_ptl)
+{
+       /*
+        * With split pmd lock we also need to move preallocated
+        * PTE page table if new_pmd is on different PMD page table.
+        */
+       return new_pmd_ptl != old_pmd_ptl;
+}
+#endif
+
 /*
  * This function is meant to be used by sites walking pagetables with
  * the mmap_sem hold in read mode to protect against MADV_DONTNEED and
index 04d318d1187aa072723b615b05087ae5f4c16bb2..032ed87ef0f332afbe94f79ae3b982f060a181ce 100644 (file)
@@ -57,7 +57,7 @@
 #define EXTPCLK_CLK_SRC                                        40
 #define HDMI_CLK_SRC                                   41
 #define VSYNC_CLK_SRC                                  42
-#define RBCPR_CLK_SRC                                  43
+#define MMSS_RBCPR_CLK_SRC                             43
 #define CAMSS_CCI_CCI_AHB_CLK                          44
 #define CAMSS_CCI_CCI_CLK                              45
 #define CAMSS_CSI0_AHB_CLK                             46
index 2fae55def608b0cc82fba2ac07f2f3c14941d9f6..b388223bd4a9a9c1b5d91f8b1217fe57b328d940 100644 (file)
@@ -175,6 +175,27 @@ static inline void * __init memblock_virt_alloc_nopanic(
                                                    NUMA_NO_NODE);
 }
 
+#ifndef ARCH_LOW_ADDRESS_LIMIT
+#define ARCH_LOW_ADDRESS_LIMIT  0xffffffffUL
+#endif
+
+static inline void * __init memblock_virt_alloc_low(
+                                       phys_addr_t size, phys_addr_t align)
+{
+       return memblock_virt_alloc_try_nid(size, align,
+                                                  BOOTMEM_LOW_LIMIT,
+                                                  ARCH_LOW_ADDRESS_LIMIT,
+                                                  NUMA_NO_NODE);
+}
+static inline void * __init memblock_virt_alloc_low_nopanic(
+                                       phys_addr_t size, phys_addr_t align)
+{
+       return memblock_virt_alloc_try_nid_nopanic(size, align,
+                                                  BOOTMEM_LOW_LIMIT,
+                                                  ARCH_LOW_ADDRESS_LIMIT,
+                                                  NUMA_NO_NODE);
+}
+
 static inline void * __init memblock_virt_alloc_from_nopanic(
                phys_addr_t size, phys_addr_t align, phys_addr_t min_addr)
 {
@@ -238,6 +259,22 @@ static inline void * __init memblock_virt_alloc_nopanic(
        return __alloc_bootmem_nopanic(size, align, BOOTMEM_LOW_LIMIT);
 }
 
+static inline void * __init memblock_virt_alloc_low(
+                                       phys_addr_t size, phys_addr_t align)
+{
+       if (!align)
+               align = SMP_CACHE_BYTES;
+       return __alloc_bootmem_low(size, align, BOOTMEM_LOW_LIMIT);
+}
+
+static inline void * __init memblock_virt_alloc_low_nopanic(
+                                       phys_addr_t size, phys_addr_t align)
+{
+       if (!align)
+               align = SMP_CACHE_BYTES;
+       return __alloc_bootmem_low_nopanic(size, align, BOOTMEM_LOW_LIMIT);
+}
+
 static inline void * __init memblock_virt_alloc_from_nopanic(
                phys_addr_t size, phys_addr_t align, phys_addr_t min_addr)
 {
index 58d19014068f29e9feda88f5aecf48cace545211..07ad423cc37fbe4e61febe918d5aed38fdcdf2b7 100644 (file)
@@ -17,7 +17,6 @@ struct ceph_buffer {
        struct kref kref;
        struct kvec vec;
        size_t alloc_len;
-       bool is_vmalloc;
 };
 
 extern struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp);
index 4c42080347aff5d843763dfaedc51c98fe21dfea..138448f766b44fdf2939ac0eff1cad12c205240c 100644 (file)
@@ -4,42 +4,73 @@
 /*
  * feature bits
  */
-#define CEPH_FEATURE_UID            (1<<0)
-#define CEPH_FEATURE_NOSRCADDR      (1<<1)
-#define CEPH_FEATURE_MONCLOCKCHECK  (1<<2)
-#define CEPH_FEATURE_FLOCK          (1<<3)
-#define CEPH_FEATURE_SUBSCRIBE2     (1<<4)
-#define CEPH_FEATURE_MONNAMES       (1<<5)
-#define CEPH_FEATURE_RECONNECT_SEQ  (1<<6)
-#define CEPH_FEATURE_DIRLAYOUTHASH  (1<<7)
-#define CEPH_FEATURE_OBJECTLOCATOR  (1<<8)
-#define CEPH_FEATURE_PGID64         (1<<9)
-#define CEPH_FEATURE_INCSUBOSDMAP   (1<<10)
-#define CEPH_FEATURE_PGPOOL3        (1<<11)
-#define CEPH_FEATURE_OSDREPLYMUX    (1<<12)
-#define CEPH_FEATURE_OSDENC         (1<<13)
-#define CEPH_FEATURE_OMAP           (1<<14)
-#define CEPH_FEATURE_MONENC         (1<<15)
-#define CEPH_FEATURE_QUERY_T        (1<<16)
-#define CEPH_FEATURE_INDEP_PG_MAP   (1<<17)
-#define CEPH_FEATURE_CRUSH_TUNABLES (1<<18)
-#define CEPH_FEATURE_CHUNKY_SCRUB   (1<<19)
-#define CEPH_FEATURE_MON_NULLROUTE  (1<<20)
-#define CEPH_FEATURE_MON_GV         (1<<21)
-#define CEPH_FEATURE_BACKFILL_RESERVATION (1<<22)
-#define CEPH_FEATURE_MSG_AUTH      (1<<23)
-#define CEPH_FEATURE_RECOVERY_RESERVATION (1<<24)
-#define CEPH_FEATURE_CRUSH_TUNABLES2 (1<<25)
-#define CEPH_FEATURE_CREATEPOOLID   (1<<26)
-#define CEPH_FEATURE_REPLY_CREATE_INODE   (1<<27)
-#define CEPH_FEATURE_OSD_HBMSGS     (1<<28)
-#define CEPH_FEATURE_MDSENC         (1<<29)
-#define CEPH_FEATURE_OSDHASHPSPOOL  (1<<30)
+#define CEPH_FEATURE_UID            (1ULL<<0)
+#define CEPH_FEATURE_NOSRCADDR      (1ULL<<1)
+#define CEPH_FEATURE_MONCLOCKCHECK  (1ULL<<2)
+#define CEPH_FEATURE_FLOCK          (1ULL<<3)
+#define CEPH_FEATURE_SUBSCRIBE2     (1ULL<<4)
+#define CEPH_FEATURE_MONNAMES       (1ULL<<5)
+#define CEPH_FEATURE_RECONNECT_SEQ  (1ULL<<6)
+#define CEPH_FEATURE_DIRLAYOUTHASH  (1ULL<<7)
+#define CEPH_FEATURE_OBJECTLOCATOR  (1ULL<<8)
+#define CEPH_FEATURE_PGID64         (1ULL<<9)
+#define CEPH_FEATURE_INCSUBOSDMAP   (1ULL<<10)
+#define CEPH_FEATURE_PGPOOL3        (1ULL<<11)
+#define CEPH_FEATURE_OSDREPLYMUX    (1ULL<<12)
+#define CEPH_FEATURE_OSDENC         (1ULL<<13)
+#define CEPH_FEATURE_OMAP           (1ULL<<14)
+#define CEPH_FEATURE_MONENC         (1ULL<<15)
+#define CEPH_FEATURE_QUERY_T        (1ULL<<16)
+#define CEPH_FEATURE_INDEP_PG_MAP   (1ULL<<17)
+#define CEPH_FEATURE_CRUSH_TUNABLES (1ULL<<18)
+#define CEPH_FEATURE_CHUNKY_SCRUB   (1ULL<<19)
+#define CEPH_FEATURE_MON_NULLROUTE  (1ULL<<20)
+#define CEPH_FEATURE_MON_GV         (1ULL<<21)
+#define CEPH_FEATURE_BACKFILL_RESERVATION (1ULL<<22)
+#define CEPH_FEATURE_MSG_AUTH      (1ULL<<23)
+#define CEPH_FEATURE_RECOVERY_RESERVATION (1ULL<<24)
+#define CEPH_FEATURE_CRUSH_TUNABLES2 (1ULL<<25)
+#define CEPH_FEATURE_CREATEPOOLID   (1ULL<<26)
+#define CEPH_FEATURE_REPLY_CREATE_INODE   (1ULL<<27)
+#define CEPH_FEATURE_OSD_HBMSGS     (1ULL<<28)
+#define CEPH_FEATURE_MDSENC         (1ULL<<29)
+#define CEPH_FEATURE_OSDHASHPSPOOL  (1ULL<<30)
+#define CEPH_FEATURE_MON_SINGLE_PAXOS (1ULL<<31)
+#define CEPH_FEATURE_OSD_SNAPMAPPER (1ULL<<32)
+#define CEPH_FEATURE_MON_SCRUB      (1ULL<<33)
+#define CEPH_FEATURE_OSD_PACKED_RECOVERY (1ULL<<34)
+#define CEPH_FEATURE_OSD_CACHEPOOL (1ULL<<35)
+#define CEPH_FEATURE_CRUSH_V2      (1ULL<<36)  /* new indep; SET_* steps */
+#define CEPH_FEATURE_EXPORT_PEER   (1ULL<<37)
+#define CEPH_FEATURE_OSD_ERASURE_CODES (1ULL<<38)
+
+/*
+ * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature
+ * vector to evaluate to 64 bit ~0.  To cope, we designate 1ULL << 63
+ * to mean 33 bit ~0, and introduce a helper below to do the
+ * translation.
+ *
+ * This was introduced by ceph.git commit
+ *   9ea02b84104045c2ffd7e7f4e7af512953855ecd v0.58-657-g9ea02b8
+ * and fixed by ceph.git commit
+ *   4255b5c2fb54ae40c53284b3ab700fdfc7e61748 v0.65-263-g4255b5c
+ */
+#define CEPH_FEATURE_RESERVED (1ULL<<63)
+
+static inline u64 ceph_sanitize_features(u64 features)
+{
+       if (features & CEPH_FEATURE_RESERVED) {
+               /* everything through OSD_SNAPMAPPER */
+               return 0x1ffffffffull;
+       } else {
+               return features;
+       }
+}
 
 /*
  * Features supported.
  */
-#define CEPH_FEATURES_SUPPORTED_DEFAULT  \
+#define CEPH_FEATURES_SUPPORTED_DEFAULT                \
        (CEPH_FEATURE_NOSRCADDR |               \
         CEPH_FEATURE_RECONNECT_SEQ |           \
         CEPH_FEATURE_PGID64 |                  \
         CEPH_FEATURE_CRUSH_TUNABLES |          \
         CEPH_FEATURE_CRUSH_TUNABLES2 |         \
         CEPH_FEATURE_REPLY_CREATE_INODE |      \
-        CEPH_FEATURE_OSDHASHPSPOOL)
+        CEPH_FEATURE_OSDHASHPSPOOL |           \
+        CEPH_FEATURE_OSD_CACHEPOOL |           \
+        CEPH_FEATURE_CRUSH_V2 |                \
+        CEPH_FEATURE_EXPORT_PEER)
 
 #define CEPH_FEATURES_REQUIRED_DEFAULT   \
        (CEPH_FEATURE_NOSRCADDR |        \
@@ -56,4 +90,5 @@
         CEPH_FEATURE_PGID64 |           \
         CEPH_FEATURE_PGPOOL3 |          \
         CEPH_FEATURE_OSDENC)
+
 #endif
index 2ad7b860f06232d76ae5a4f208d081a17825a9ae..2623cffc73a17b32cf9660bf67cf05bd9ae4b45f 100644 (file)
@@ -53,6 +53,29 @@ struct ceph_file_layout {
        __le32 fl_pg_pool;      /* namespace, crush ruleset, rep level */
 } __attribute__ ((packed));
 
+#define ceph_file_layout_su(l) ((__s32)le32_to_cpu((l).fl_stripe_unit))
+#define ceph_file_layout_stripe_count(l) \
+       ((__s32)le32_to_cpu((l).fl_stripe_count))
+#define ceph_file_layout_object_size(l) ((__s32)le32_to_cpu((l).fl_object_size))
+#define ceph_file_layout_cas_hash(l) ((__s32)le32_to_cpu((l).fl_cas_hash))
+#define ceph_file_layout_object_su(l) \
+       ((__s32)le32_to_cpu((l).fl_object_stripe_unit))
+#define ceph_file_layout_pg_pool(l) \
+       ((__s32)le32_to_cpu((l).fl_pg_pool))
+
+static inline unsigned ceph_file_layout_stripe_width(struct ceph_file_layout *l)
+{
+       return le32_to_cpu(l->fl_stripe_unit) *
+               le32_to_cpu(l->fl_stripe_count);
+}
+
+/* "period" == bytes before i start on a new set of objects */
+static inline unsigned ceph_file_layout_period(struct ceph_file_layout *l)
+{
+       return le32_to_cpu(l->fl_object_size) *
+               le32_to_cpu(l->fl_stripe_count);
+}
+
 #define CEPH_MIN_STRIPE_UNIT 65536
 
 int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
@@ -282,6 +305,8 @@ enum {
        CEPH_SESSION_RENEWCAPS,
        CEPH_SESSION_STALE,
        CEPH_SESSION_RECALL_STATE,
+       CEPH_SESSION_FLUSHMSG,
+       CEPH_SESSION_FLUSHMSG_ACK,
 };
 
 extern const char *ceph_session_op_name(int op);
@@ -457,7 +482,8 @@ struct ceph_mds_reply_cap {
        __u8 flags;                    /* CEPH_CAP_FLAG_* */
 } __attribute__ ((packed));
 
-#define CEPH_CAP_FLAG_AUTH  1          /* cap is issued by auth mds */
+#define CEPH_CAP_FLAG_AUTH     (1 << 0)  /* cap is issued by auth mds */
+#define CEPH_CAP_FLAG_RELEASE  (1 << 1)  /* release the cap */
 
 /* inode record, for bundling with mds reply */
 struct ceph_mds_reply_inode {
@@ -658,6 +684,14 @@ struct ceph_mds_caps {
        __le32 time_warp_seq;
 } __attribute__ ((packed));
 
+struct ceph_mds_cap_peer {
+       __le64 cap_id;
+       __le32 seq;
+       __le32 mseq;
+       __le32 mds;
+       __u8   flags;
+} __attribute__ ((packed));
+
 /* cap release msg head */
 struct ceph_mds_cap_release {
        __le32 num;                /* number of cap_items that follow */
index 2e3024881a5e3e3939264c032b000f1c9d80d367..2f49aa4c4f7f1d2feb361422e2b5f024c55a9519 100644 (file)
@@ -122,8 +122,8 @@ struct ceph_client {
 
        int (*extra_mon_dispatch)(struct ceph_client *, struct ceph_msg *);
 
-       u32 supported_features;
-       u32 required_features;
+       u64 supported_features;
+       u64 required_features;
 
        struct ceph_messenger msgr;   /* messenger instance */
        struct ceph_mon_client monc;
@@ -173,15 +173,18 @@ static inline int calc_pages_for(u64 off, u64 len)
                (off >> PAGE_CACHE_SHIFT);
 }
 
+extern struct kmem_cache *ceph_inode_cachep;
+extern struct kmem_cache *ceph_cap_cachep;
+extern struct kmem_cache *ceph_dentry_cachep;
+extern struct kmem_cache *ceph_file_cachep;
+
 /* ceph_common.c */
 extern bool libceph_compatible(void *data);
 
 extern const char *ceph_msg_type_name(int type);
 extern int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid);
-extern struct kmem_cache *ceph_inode_cachep;
-extern struct kmem_cache *ceph_cap_cachep;
-extern struct kmem_cache *ceph_dentry_cachep;
-extern struct kmem_cache *ceph_file_cachep;
+extern void *ceph_kvmalloc(size_t size, gfp_t flags);
+extern void ceph_kvfree(const void *ptr);
 
 extern struct ceph_options *ceph_parse_options(char *options,
                              const char *dev_name, const char *dev_name_end,
@@ -192,8 +195,8 @@ extern int ceph_compare_options(struct ceph_options *new_opt,
                                struct ceph_client *client);
 extern struct ceph_client *ceph_create_client(struct ceph_options *opt,
                                              void *private,
-                                             unsigned supported_features,
-                                             unsigned required_features);
+                                             u64 supported_features,
+                                             u64 required_features);
 extern u64 ceph_client_id(struct ceph_client *client);
 extern void ceph_destroy_client(struct ceph_client *client);
 extern int __ceph_open_session(struct ceph_client *client,
index 7c1420bb1dcef40e6f8e4cc571ef5ea2c25df913..20ee8b63a96848ad1bc63fb29ce97c853502d700 100644 (file)
@@ -60,8 +60,8 @@ struct ceph_messenger {
        u32 global_seq;
        spinlock_t global_seq_lock;
 
-       u32 supported_features;
-       u32 required_features;
+       u64 supported_features;
+       u64 required_features;
 };
 
 enum ceph_msg_data_type {
@@ -154,10 +154,9 @@ struct ceph_msg {
        struct list_head list_head;     /* links for connection lists */
 
        struct kref kref;
-       bool front_is_vmalloc;
        bool more_to_follow;
        bool needs_out_seq;
-       int front_max;
+       int front_alloc_len;
        unsigned long ack_stamp;        /* tx: when we were acked */
 
        struct ceph_msgpool *pool;
@@ -192,7 +191,7 @@ struct ceph_connection {
 
        struct ceph_entity_name peer_name; /* peer name */
 
-       unsigned peer_features;
+       u64 peer_features;
        u32 connect_seq;      /* identify the most recent connection
                                 attempt for this connection, client */
        u32 peer_global_seq;  /* peer's global seq for this connection */
@@ -256,8 +255,8 @@ extern void ceph_msgr_flush(void);
 
 extern void ceph_messenger_init(struct ceph_messenger *msgr,
                        struct ceph_entity_addr *myaddr,
-                       u32 supported_features,
-                       u32 required_features,
+                       u64 supported_features,
+                       u64 required_features,
                        bool nocrc);
 
 extern void ceph_con_init(struct ceph_connection *con, void *private,
index 8f47625a06615dbf5cbc79ef5df2e2fd5cee6041..fd47e872ebcc7a35380160dbf2f83ab1563dd878 100644 (file)
 #include <linux/ceph/auth.h>
 #include <linux/ceph/pagelist.h>
 
-/* 
- * Maximum object name size 
- * (must be at least as big as RBD_MAX_MD_NAME_LEN -- currently 100) 
- */
-#define MAX_OBJ_NAME_SIZE 100
-
 struct ceph_msg;
 struct ceph_snap_context;
 struct ceph_osd_request;
@@ -138,6 +132,7 @@ struct ceph_osd_request {
        __le64           *r_request_pool;
        void             *r_request_pgid;
        __le32           *r_request_attempts;
+       bool              r_paused;
        struct ceph_eversion *r_request_reassert_version;
 
        int               r_result;
@@ -158,15 +153,21 @@ struct ceph_osd_request {
        struct inode *r_inode;                /* for use by callbacks */
        void *r_priv;                         /* ditto */
 
-       char              r_oid[MAX_OBJ_NAME_SIZE];          /* object name */
-       int               r_oid_len;
+       struct ceph_object_locator r_base_oloc;
+       struct ceph_object_id r_base_oid;
+       struct ceph_object_locator r_target_oloc;
+       struct ceph_object_id r_target_oid;
+
        u64               r_snapid;
        unsigned long     r_stamp;            /* send OR check time */
 
-       struct ceph_file_layout r_file_layout;
        struct ceph_snap_context *r_snapc;    /* snap context for writes */
 };
 
+struct ceph_request_redirect {
+       struct ceph_object_locator oloc;
+};
+
 struct ceph_osd_event {
        u64 cookie;
        int one_shot;
index d05cc4451af62dd158929b39e6684fc19fd85cb2..49ff69f0746bd6f28ee517ac6146716ff0e27fa5 100644 (file)
@@ -35,13 +35,26 @@ struct ceph_pg_pool_info {
        u8 object_hash;
        u32 pg_num, pgp_num;
        int pg_num_mask, pgp_num_mask;
+       s64 read_tier;
+       s64 write_tier; /* wins for read+write ops */
        u64 flags;
        char *name;
 };
 
 struct ceph_object_locator {
-       uint64_t pool;
-       char *key;
+       s64 pool;
+};
+
+/*
+ * Maximum supported by kernel client object name length
+ *
+ * (probably outdated: must be >= RBD_MAX_MD_NAME_LEN -- currently 100)
+ */
+#define CEPH_MAX_OID_NAME_LEN 100
+
+struct ceph_object_id {
+       char name[CEPH_MAX_OID_NAME_LEN];
+       int name_len;
 };
 
 struct ceph_pg_mapping {
@@ -73,33 +86,30 @@ struct ceph_osdmap {
        struct crush_map *crush;
 };
 
-/*
- * file layout helpers
- */
-#define ceph_file_layout_su(l) ((__s32)le32_to_cpu((l).fl_stripe_unit))
-#define ceph_file_layout_stripe_count(l) \
-       ((__s32)le32_to_cpu((l).fl_stripe_count))
-#define ceph_file_layout_object_size(l) ((__s32)le32_to_cpu((l).fl_object_size))
-#define ceph_file_layout_cas_hash(l) ((__s32)le32_to_cpu((l).fl_cas_hash))
-#define ceph_file_layout_object_su(l) \
-       ((__s32)le32_to_cpu((l).fl_object_stripe_unit))
-#define ceph_file_layout_pg_pool(l) \
-       ((__s32)le32_to_cpu((l).fl_pg_pool))
-
-static inline unsigned ceph_file_layout_stripe_width(struct ceph_file_layout *l)
+static inline void ceph_oid_set_name(struct ceph_object_id *oid,
+                                    const char *name)
 {
-       return le32_to_cpu(l->fl_stripe_unit) *
-               le32_to_cpu(l->fl_stripe_count);
+       int len;
+
+       len = strlen(name);
+       if (len > sizeof(oid->name)) {
+               WARN(1, "ceph_oid_set_name '%s' len %d vs %zu, truncating\n",
+                    name, len, sizeof(oid->name));
+               len = sizeof(oid->name);
+       }
+
+       memcpy(oid->name, name, len);
+       oid->name_len = len;
 }
 
-/* "period" == bytes before i start on a new set of objects */
-static inline unsigned ceph_file_layout_period(struct ceph_file_layout *l)
+static inline void ceph_oid_copy(struct ceph_object_id *dest,
+                                struct ceph_object_id *src)
 {
-       return le32_to_cpu(l->fl_object_size) *
-               le32_to_cpu(l->fl_stripe_count);
+       BUG_ON(src->name_len > sizeof(dest->name));
+       memcpy(dest->name, src->name, src->name_len);
+       dest->name_len = src->name_len;
 }
 
-
 static inline int ceph_osd_is_up(struct ceph_osdmap *map, int osd)
 {
        return (osd < map->max_osd) && (map->osd_state[osd] & CEPH_OSD_UP);
@@ -155,14 +165,20 @@ extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
                                         u64 *bno, u64 *oxoff, u64 *oxlen);
 
 /* calculate mapping of object to a placement group */
-extern int ceph_calc_ceph_pg(struct ceph_pg *pg, const char *oid,
-                         struct ceph_osdmap *osdmap, uint64_t pool);
+extern int ceph_oloc_oid_to_pg(struct ceph_osdmap *osdmap,
+                              struct ceph_object_locator *oloc,
+                              struct ceph_object_id *oid,
+                              struct ceph_pg *pg_out);
+
 extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap,
                               struct ceph_pg pgid,
                               int *acting);
 extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
                                struct ceph_pg pgid);
 
+extern struct ceph_pg_pool_info *ceph_pg_pool_by_id(struct ceph_osdmap *map,
+                                                   u64 id);
+
 extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id);
 extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name);
 
index 68c96a508ac20f8ff3aff08b7e29ff9bdf86bccf..96292df4041ba2aaebe32caa2dae5f731b4fb02c 100644 (file)
@@ -344,6 +344,10 @@ enum {
        CEPH_OSD_FLAG_EXEC_PUBLIC =    0x1000,  /* DEPRECATED op may exec (public) */
        CEPH_OSD_FLAG_LOCALIZE_READS = 0x2000,  /* read from nearby replica, if any */
        CEPH_OSD_FLAG_RWORDERED =      0x4000,  /* order wrt concurrent reads */
+       CEPH_OSD_FLAG_IGNORE_CACHE =   0x8000,  /* ignore cache logic */
+       CEPH_OSD_FLAG_SKIPRWLOCKS =   0x10000,  /* skip rw locks */
+       CEPH_OSD_FLAG_IGNORE_OVERLAY = 0x20000, /* ignore pool overlay */
+       CEPH_OSD_FLAG_FLUSH =         0x40000,  /* this is part of flush */
 };
 
 enum {
index 999b28ba38f7270608452cfff436a4e52b22a918..448b2294820fcf70ac442af1a2fcd4974dc340c3 100644 (file)
@@ -488,6 +488,8 @@ struct clk_onecell_data {
        unsigned int clk_num;
 };
 
+extern struct of_device_id __clk_of_table;
+
 #define CLK_OF_DECLARE(name, compat, fn)                       \
        static const struct of_device_id __clk_of_table_##name  \
                __used __section(__clk_of_table)                \
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
new file mode 100644 (file)
index 0000000..092b641
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * TI clock drivers support
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __LINUX_CLK_TI_H__
+#define __LINUX_CLK_TI_H__
+
+#include <linux/clkdev.h>
+
+/**
+ * struct dpll_data - DPLL registers and integration data
+ * @mult_div1_reg: register containing the DPLL M and N bitfields
+ * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
+ * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
+ * @clk_bypass: struct clk pointer to the clock's bypass clock input
+ * @clk_ref: struct clk pointer to the clock's reference clock input
+ * @control_reg: register containing the DPLL mode bitfield
+ * @enable_mask: mask of the DPLL mode bitfield in @control_reg
+ * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
+ * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
+ * @last_rounded_m4xen: cache of the last M4X result of
+ *                     omap4_dpll_regm4xen_round_rate()
+ * @last_rounded_lpmode: cache of the last lpmode result of
+ *                      omap4_dpll_lpmode_recalc()
+ * @max_multiplier: maximum valid non-bypass multiplier value (actual)
+ * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
+ * @min_divider: minimum valid non-bypass divider value (actual)
+ * @max_divider: maximum valid non-bypass divider value (actual)
+ * @modes: possible values of @enable_mask
+ * @autoidle_reg: register containing the DPLL autoidle mode bitfield
+ * @idlest_reg: register containing the DPLL idle status bitfield
+ * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
+ * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
+ * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
+ * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
+ * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
+ * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
+ * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
+ * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
+ * @flags: DPLL type/features (see below)
+ *
+ * Possible values for @flags:
+ * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
+ *
+ * @freqsel_mask is only used on the OMAP34xx family and AM35xx.
+ *
+ * XXX Some DPLLs have multiple bypass inputs, so it's not technically
+ * correct to only have one @clk_bypass pointer.
+ *
+ * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
+ * @last_rounded_n) should be separated from the runtime-fixed fields
+ * and placed into a different structure, so that the runtime-fixed data
+ * can be placed into read-only space.
+ */
+struct dpll_data {
+       void __iomem            *mult_div1_reg;
+       u32                     mult_mask;
+       u32                     div1_mask;
+       struct clk              *clk_bypass;
+       struct clk              *clk_ref;
+       void __iomem            *control_reg;
+       u32                     enable_mask;
+       unsigned long           last_rounded_rate;
+       u16                     last_rounded_m;
+       u8                      last_rounded_m4xen;
+       u8                      last_rounded_lpmode;
+       u16                     max_multiplier;
+       u8                      last_rounded_n;
+       u8                      min_divider;
+       u16                     max_divider;
+       u8                      modes;
+       void __iomem            *autoidle_reg;
+       void __iomem            *idlest_reg;
+       u32                     autoidle_mask;
+       u32                     freqsel_mask;
+       u32                     idlest_mask;
+       u32                     dco_mask;
+       u32                     sddiv_mask;
+       u32                     lpmode_mask;
+       u32                     m4xen_mask;
+       u8                      auto_recal_bit;
+       u8                      recal_en_bit;
+       u8                      recal_st_bit;
+       u8                      flags;
+};
+
+struct clk_hw_omap_ops;
+
+/**
+ * struct clk_hw_omap - OMAP struct clk
+ * @node: list_head connecting this clock into the full clock list
+ * @enable_reg: register to write to enable the clock (see @enable_bit)
+ * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
+ * @flags: see "struct clk.flags possibilities" above
+ * @clksel_reg: for clksel clks, register va containing src/divisor select
+ * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
+ * @clksel: for clksel clks, pointer to struct clksel for this clock
+ * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
+ * @clkdm_name: clockdomain name that this clock is contained in
+ * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
+ * @ops: clock ops for this clock
+ */
+struct clk_hw_omap {
+       struct clk_hw           hw;
+       struct list_head        node;
+       unsigned long           fixed_rate;
+       u8                      fixed_div;
+       void __iomem            *enable_reg;
+       u8                      enable_bit;
+       u8                      flags;
+       void __iomem            *clksel_reg;
+       u32                     clksel_mask;
+       const struct clksel     *clksel;
+       struct dpll_data        *dpll_data;
+       const char              *clkdm_name;
+       struct clockdomain      *clkdm;
+       const struct clk_hw_omap_ops    *ops;
+};
+
+/*
+ * struct clk_hw_omap.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * ENABLE_REG_32BIT: (OMAP1 only) clock control register must be accessed
+ *     with 32bit ops, by default OMAP1 uses 16bit ops.
+ * CLOCK_IDLE_CONTROL: (OMAP1 only) clock has autoidle support.
+ * CLOCK_NO_IDLE_PARENT: (OMAP1 only) when clock is enabled, its parent
+ *     clock is put to no-idle mode.
+ * ENABLE_ON_INIT: Clock is enabled on init.
+ * INVERT_ENABLE: By default, clock enable bit behavior is '1' enable, '0'
+ *     disable. This inverts the behavior making '0' enable and '1' disable.
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ * MEMMAP_ADDRESSING: Use memmap addressing to access clock registers.
+ */
+#define ENABLE_REG_32BIT       (1 << 0)        /* Use 32-bit access */
+#define CLOCK_IDLE_CONTROL     (1 << 1)
+#define CLOCK_NO_IDLE_PARENT   (1 << 2)
+#define ENABLE_ON_INIT         (1 << 3)        /* Enable upon framework init */
+#define INVERT_ENABLE          (1 << 4)        /* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2         (1 << 5)
+#define MEMMAP_ADDRESSING      (1 << 6)
+
+/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
+#define DPLL_LOW_POWER_STOP    0x1
+#define DPLL_LOW_POWER_BYPASS  0x5
+#define DPLL_LOCKED            0x7
+
+/* DPLL Type and DCO Selection Flags */
+#define DPLL_J_TYPE            0x1
+
+/* Composite clock component types */
+enum {
+       CLK_COMPONENT_TYPE_GATE = 0,
+       CLK_COMPONENT_TYPE_DIVIDER,
+       CLK_COMPONENT_TYPE_MUX,
+       CLK_COMPONENT_TYPE_MAX,
+};
+
+/**
+ * struct ti_dt_clk - OMAP DT clock alias declarations
+ * @lk: clock lookup definition
+ * @node_name: clock DT node to map to
+ */
+struct ti_dt_clk {
+       struct clk_lookup               lk;
+       char                            *node_name;
+};
+
+#define DT_CLK(dev, con, name)         \
+       {                               \
+               .lk = {                 \
+                       .dev_id = dev,  \
+                       .con_id = con,  \
+               },                      \
+               .node_name = name,      \
+       }
+
+/* Maximum number of clock memmaps */
+#define CLK_MAX_MEMMAPS                        4
+
+typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
+
+/**
+ * struct clk_omap_reg - OMAP register declaration
+ * @offset: offset from the master IP module base address
+ * @index: index of the master IP module
+ */
+struct clk_omap_reg {
+       u16 offset;
+       u16 index;
+};
+
+/**
+ * struct ti_clk_ll_ops - low-level register access ops for a clock
+ * @clk_readl: pointer to register read function
+ * @clk_writel: pointer to register write function
+ *
+ * Low-level register access ops are generally used by the basic clock types
+ * (clk-gate, clk-mux, clk-divider etc.) to provide support for various
+ * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be
+ * used by other hardware-specific clock drivers if needed.
+ */
+struct ti_clk_ll_ops {
+       u32     (*clk_readl)(void __iomem *reg);
+       void    (*clk_writel)(u32 val, void __iomem *reg);
+};
+
+extern struct ti_clk_ll_ops *ti_clk_ll_ops;
+
+extern const struct clk_ops ti_clk_divider_ops;
+extern const struct clk_ops ti_clk_mux_ops;
+
+#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
+
+void omap2_init_clk_hw_omap_clocks(struct clk *clk);
+int omap3_noncore_dpll_enable(struct clk_hw *hw);
+void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate);
+unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
+                                        unsigned long parent_rate);
+long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                   unsigned long target_rate,
+                                   unsigned long *parent_rate);
+u8 omap2_init_dpll_parent(struct clk_hw *hw);
+unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
+long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+                          unsigned long *parent_rate);
+void omap2_init_clk_clkdm(struct clk_hw *clk);
+unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate);
+int omap2_clkops_enable_clkdm(struct clk_hw *hw);
+void omap2_clkops_disable_clkdm(struct clk_hw *hw);
+int omap2_clk_disable_autoidle_all(void);
+void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
+int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
+                        unsigned long parent_rate);
+int omap2_dflt_clk_enable(struct clk_hw *hw);
+void omap2_dflt_clk_disable(struct clk_hw *hw);
+int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
+void omap3_clk_lock_dpll5(void);
+
+void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
+void ti_dt_clocks_register(struct ti_dt_clk *oclks);
+void ti_dt_clk_init_provider(struct device_node *np, int index);
+void ti_dt_clockdomains_setup(void);
+int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
+                     ti_of_clk_init_cb_t func);
+int of_ti_clk_autoidle_setup(struct device_node *node);
+int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
+
+int omap3430_dt_clk_init(void);
+int omap3630_dt_clk_init(void);
+int am35xx_dt_clk_init(void);
+int ti81xx_dt_clk_init(void);
+int omap4xxx_dt_clk_init(void);
+int omap5xxx_dt_clk_init(void);
+int dra7xx_dt_clk_init(void);
+int am33xx_dt_clk_init(void);
+int am43xx_dt_clk_init(void);
+
+#ifdef CONFIG_OF
+void of_ti_clk_allow_autoidle_all(void);
+void of_ti_clk_deny_autoidle_all(void);
+#else
+static inline void of_ti_clk_allow_autoidle_all(void) { }
+static inline void of_ti_clk_deny_autoidle_all(void) { }
+#endif
+
+extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
+extern const struct clk_hw_omap_ops clkhwops_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
+extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
+extern const struct clk_hw_omap_ops clkhwops_iclk;
+extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
+extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
+
+#endif
index eb8a49d75ab3155bb6910eab585e5dfed9f64dee..19f6003291def61a40a2305a453838d13c92892f 100644 (file)
@@ -327,16 +327,16 @@ asmlinkage long compat_sys_keyctl(u32 option,
                              u32 arg2, u32 arg3, u32 arg4, u32 arg5);
 asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
 
-asmlinkage ssize_t compat_sys_readv(unsigned long fd,
-               const struct compat_iovec __user *vec, unsigned long vlen);
-asmlinkage ssize_t compat_sys_writev(unsigned long fd,
-               const struct compat_iovec __user *vec, unsigned long vlen);
-asmlinkage ssize_t compat_sys_preadv(unsigned long fd,
+asmlinkage ssize_t compat_sys_readv(compat_ulong_t fd,
+               const struct compat_iovec __user *vec, compat_ulong_t vlen);
+asmlinkage ssize_t compat_sys_writev(compat_ulong_t fd,
+               const struct compat_iovec __user *vec, compat_ulong_t vlen);
+asmlinkage ssize_t compat_sys_preadv(compat_ulong_t fd,
                const struct compat_iovec __user *vec,
-               unsigned long vlen, u32 pos_low, u32 pos_high);
-asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
+               compat_ulong_t vlen, u32 pos_low, u32 pos_high);
+asmlinkage ssize_t compat_sys_pwritev(compat_ulong_t fd,
                const struct compat_iovec __user *vec,
-               unsigned long vlen, u32 pos_low, u32 pos_high);
+               compat_ulong_t vlen, u32 pos_low, u32 pos_high);
 asmlinkage long comat_sys_lseek(unsigned int, compat_off_t, unsigned int);
 
 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
@@ -422,7 +422,7 @@ extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
                                  compat_long_t addr, compat_long_t data);
 
-asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, size_t);
+asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, compat_size_t);
 /*
  * epoll (fs/eventpoll.c) compat bits follow ...
  */
diff --git a/include/linux/cramfs_fs_sb.h b/include/linux/cramfs_fs_sb.h
deleted file mode 100644 (file)
index 8390693..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _CRAMFS_FS_SB
-#define _CRAMFS_FS_SB
-
-/*
- * cramfs super-block data in memory
- */
-struct cramfs_sb_info {
-                       unsigned long magic;
-                       unsigned long size;
-                       unsigned long blocks;
-                       unsigned long files;
-                       unsigned long flags;
-};
-
-static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb)
-{
-       return sb->s_fs_info;
-}
-
-#endif
index 6a1101f24cfba84eaf6210f96802984009462dbd..acaa5615d6343906ab05e528bb10ea3e76bf0fac 100644 (file)
 
 #define CRUSH_MAGIC 0x00010000ul   /* for detecting algorithm revisions */
 
-
 #define CRUSH_MAX_DEPTH 10  /* max crush hierarchy depth */
-#define CRUSH_MAX_SET   10  /* max size of a mapping result */
 
 
+#define CRUSH_ITEM_UNDEF  0x7ffffffe  /* undefined result (internal use only) */
+#define CRUSH_ITEM_NONE   0x7fffffff  /* no result */
+
 /*
  * CRUSH uses user-defined "rules" to describe how inputs should be
  * mapped to devices.  A rule consists of sequence of steps to perform
@@ -43,8 +44,13 @@ enum {
                                      /* arg2 = type */
        CRUSH_RULE_CHOOSE_INDEP = 3,  /* same */
        CRUSH_RULE_EMIT = 4,          /* no args */
-       CRUSH_RULE_CHOOSE_LEAF_FIRSTN = 6,
-       CRUSH_RULE_CHOOSE_LEAF_INDEP = 7,
+       CRUSH_RULE_CHOOSELEAF_FIRSTN = 6,
+       CRUSH_RULE_CHOOSELEAF_INDEP = 7,
+
+       CRUSH_RULE_SET_CHOOSE_TRIES = 8, /* override choose_total_tries */
+       CRUSH_RULE_SET_CHOOSELEAF_TRIES = 9, /* override chooseleaf_descend_once */
+       CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES = 10,
+       CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES = 11,
 };
 
 /*
@@ -162,7 +168,10 @@ struct crush_map {
        __u32 choose_local_fallback_tries;
        /* choose attempts before giving up */ 
        __u32 choose_total_tries;
-       /* attempt chooseleaf inner descent once; on failure retry outer descent */
+       /* attempt chooseleaf inner descent once for firstn mode; on
+        * reject retry outer descent.  Note that this does *not*
+        * apply to a collision: in that case we will retry as we used
+        * to. */
        __u32 chooseleaf_descend_once;
 };
 
@@ -174,6 +183,7 @@ extern void crush_destroy_bucket_list(struct crush_bucket_list *b);
 extern void crush_destroy_bucket_tree(struct crush_bucket_tree *b);
 extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b);
 extern void crush_destroy_bucket(struct crush_bucket *b);
+extern void crush_destroy_rule(struct crush_rule *r);
 extern void crush_destroy(struct crush_map *map);
 
 static inline int crush_calc_tree_node(int i)
index 5772dee3ecbf236c13b9fdc3e31446d6da495e31..eab367446eea7fa683cb4fd15e74ad3822bb35c8 100644 (file)
@@ -14,6 +14,7 @@ extern int crush_find_rule(const struct crush_map *map, int ruleset, int type, i
 extern int crush_do_rule(const struct crush_map *map,
                         int ruleno,
                         int x, int *result, int result_max,
-                        const __u32 *weights);
+                        const __u32 *weights, int weight_max,
+                        int *scratch);
 
 #endif
index 085197bd88120e945235e3d843360ce99364a274..70e8e21c0a303a3db8b7a59ff3b6f511cf225c46 100644 (file)
@@ -59,29 +59,36 @@ struct files_struct {
        struct file __rcu * fd_array[NR_OPEN_DEFAULT];
 };
 
-#define rcu_dereference_check_fdtable(files, fdtfd) \
-       (rcu_dereference_check((fdtfd), \
-                              lockdep_is_held(&(files)->file_lock) || \
-                              atomic_read(&(files)->count) == 1 || \
-                              rcu_my_thread_group_empty()))
-
-#define files_fdtable(files) \
-               (rcu_dereference_check_fdtable((files), (files)->fdt))
-
 struct file_operations;
 struct vfsmount;
 struct dentry;
 
 extern void __init files_defer_init(void);
 
-static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
+#define rcu_dereference_check_fdtable(files, fdtfd) \
+       rcu_dereference_check((fdtfd), lockdep_is_held(&(files)->file_lock))
+
+#define files_fdtable(files) \
+       rcu_dereference_check_fdtable((files), (files)->fdt)
+
+/*
+ * The caller must ensure that fd table isn't shared or hold rcu or file lock
+ */
+static inline struct file *__fcheck_files(struct files_struct *files, unsigned int fd)
 {
-       struct file * file = NULL;
-       struct fdtable *fdt = files_fdtable(files);
+       struct fdtable *fdt = rcu_dereference_raw(files->fdt);
 
        if (fd < fdt->max_fds)
-               file = rcu_dereference_check_fdtable(files, fdt->fd[fd]);
-       return file;
+               return rcu_dereference_raw(fdt->fd[fd]);
+       return NULL;
+}
+
+static inline struct file *fcheck_files(struct files_struct *files, unsigned int fd)
+{
+       rcu_lockdep_assert(rcu_read_lock_held() ||
+                          lockdep_is_held(&files->file_lock),
+                          "suspicious rcu_dereference_check() usage");
+       return __fcheck_files(files, fd);
 }
 
 /*
index 121f11f001c06f1cdcdeb6533234d76626a2915b..09f553c59813a2b2f88991ab0ab854880e07e574 100644 (file)
@@ -1580,6 +1580,7 @@ struct inode_operations {
                           struct file *, unsigned open_flag,
                           umode_t create_mode, int *opened);
        int (*tmpfile) (struct inode *, struct dentry *, umode_t);
+       int (*set_acl)(struct inode *, struct posix_acl *, int);
 } ____cacheline_aligned;
 
 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
index 7d8d5e608594c911c2eacc78dbb094c5384fd4af..3d286ff49ab0c82309ec3499bf27cc77f75f3670 100644 (file)
@@ -322,10 +322,10 @@ extern int fsnotify_fasync(int fd, struct file *file, int on);
 extern void fsnotify_destroy_event(struct fsnotify_group *group,
                                   struct fsnotify_event *event);
 /* attach the event to the group notification queue */
-extern struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group,
-                                                       struct fsnotify_event *event,
-                                                       struct fsnotify_event *(*merge)(struct list_head *,
-                                                                                       struct fsnotify_event *));
+extern int fsnotify_add_notify_event(struct fsnotify_group *group,
+                                    struct fsnotify_event *event,
+                                    int (*merge)(struct list_head *,
+                                                 struct fsnotify_event *));
 /* true if the group notification queue is empty */
 extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
 /* return, but do not dequeue the first event on the notification queue */
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
deleted file mode 100644 (file)
index b6d6575..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef LINUX_GENERIC_ACL_H
-#define LINUX_GENERIC_ACL_H
-
-#include <linux/xattr.h>
-
-struct inode;
-
-extern const struct xattr_handler generic_acl_access_handler;
-extern const struct xattr_handler generic_acl_default_handler;
-
-int generic_acl_init(struct inode *, struct inode *);
-int generic_acl_chmod(struct inode *);
-
-#endif /* LINUX_GENERIC_ACL_H */
index db43b58a3355c7b97d3acb0902fede4a0883790b..0053adde0ed9a37111ffd273c17f6d19956a6a77 100644 (file)
@@ -360,7 +360,7 @@ enum
 /* map softirq index to softirq name. update 'softirq_to_name' in
  * kernel/softirq.c when adding a new softirq.
  */
-extern char *softirq_to_name[NR_SOFTIRQS];
+extern const char * const softirq_to_name[NR_SOFTIRQS];
 
 /* softirq mask and active fields moved to irq_cpustat_t in
  * asm/hardirq.h to get better cache usage.  KAO
index 8d861b2651f7b0586edfa0be89adac92d9592746..9d84942ae2e577835a338b8a352f9c93eabe148b 100644 (file)
@@ -11,7 +11,7 @@
 struct kern_ipc_perm
 {
        spinlock_t      lock;
-       int             deleted;
+       bool            deleted;
        int             id;
        key_t           key;
        kuid_t          uid;
index f6c82de125413e8b6076ab91d68f64771641bfd1..e7831d20373776f5c3dc80c5a04147e8aa611c85 100644 (file)
@@ -21,7 +21,6 @@ struct user_namespace;
 struct ipc_ids {
        int in_use;
        unsigned short seq;
-       unsigned short seq_max;
        struct rw_semaphore rwsem;
        struct idr ipcs_idr;
        int next_id;
index 6156686bf108f38b91fcfb09766f73012dac20ea..ac39d910e70bda7c209d783dc6f01464a836e08a 100644 (file)
@@ -110,9 +110,6 @@ struct mc13xxx_led_platform_data {
        int id;
        const char *name;
        const char *default_trigger;
-
-/* Three or two bits current selection depending on the led */
-       char max_current;
 };
 
 #define MAX_LED_CONTROL_REGS   6
@@ -121,7 +118,7 @@ struct mc13xxx_leds_platform_data {
        struct mc13xxx_led_platform_data *led;
        int num_leds;
 
-/* LED Control 0 */
+/* MC13783 LED Control 0 */
 #define MC13783_LED_C0_ENABLE          (1 << 0)
 #define MC13783_LED_C0_TRIODE_MD       (1 << 7)
 #define MC13783_LED_C0_TRIODE_AD       (1 << 8)
@@ -129,21 +126,43 @@ struct mc13xxx_leds_platform_data {
 #define MC13783_LED_C0_BOOST           (1 << 10)
 #define MC13783_LED_C0_ABMODE(x)       (((x) & 0x7) << 11)
 #define MC13783_LED_C0_ABREF(x)                (((x) & 0x3) << 14)
-/* LED Control 1 */
+/* MC13783 LED Control 1 */
 #define MC13783_LED_C1_TC1HALF         (1 << 18)
 #define MC13783_LED_C1_SLEWLIM         (1 << 23)
-/* LED Control 2 */
+/* MC13783 LED Control 2 */
+#define MC13783_LED_C2_CURRENT_MD(x)   (((x) & 0x7) << 0)
+#define MC13783_LED_C2_CURRENT_AD(x)   (((x) & 0x7) << 3)
+#define MC13783_LED_C2_CURRENT_KP(x)   (((x) & 0x7) << 6)
 #define MC13783_LED_C2_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C2_SLEWLIM         (1 << 23)
-/* LED Control 3 */
+/* MC13783 LED Control 3 */
+#define MC13783_LED_C3_CURRENT_R1(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C3_CURRENT_G1(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C3_CURRENT_B1(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C3_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C3_TRIODE_TC1      (1 << 23)
-/* LED Control 4 */
+/* MC13783 LED Control 4 */
+#define MC13783_LED_C4_CURRENT_R2(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C4_CURRENT_G2(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C4_CURRENT_B2(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C4_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C4_TRIODE_TC2      (1 << 23)
-/* LED Control 5 */
+/* MC13783 LED Control 5 */
+#define MC13783_LED_C5_CURRENT_R3(x)   (((x) & 0x3) << 0)
+#define MC13783_LED_C5_CURRENT_G3(x)   (((x) & 0x3) << 2)
+#define MC13783_LED_C5_CURRENT_B3(x)   (((x) & 0x3) << 4)
 #define MC13783_LED_C5_PERIOD(x)       (((x) & 0x3) << 21)
 #define MC13783_LED_C5_TRIODE_TC3      (1 << 23)
+/* MC13892 LED Control 0 */
+#define MC13892_LED_C0_CURRENT_MD(x)   (((x) & 0x7) << 9)
+#define MC13892_LED_C0_CURRENT_AD(x)   (((x) & 0x7) << 21)
+/* MC13892 LED Control 1 */
+#define MC13892_LED_C1_CURRENT_KP(x)   (((x) & 0x7) << 9)
+/* MC13892 LED Control 2 */
+#define MC13892_LED_C2_CURRENT_R(x)    (((x) & 0x7) << 9)
+#define MC13892_LED_C2_CURRENT_G(x)    (((x) & 0x7) << 21)
+/* MC13892 LED Control 3 */
+#define MC13892_LED_C3_CURRENT_B(x)    (((x) & 0x7) << 9)
        u32 led_control[MAX_LED_CONTROL_REGS];
 };
 
index d9992fc128ca6e8e5ea1f485958191e7e335ea7e..f28f46eade6a642873246fea247f3f5455a18acb 100644 (file)
@@ -1895,7 +1895,7 @@ static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
 }
 #endif
 
-#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE
+#ifdef CONFIG_NUMA_BALANCING
 unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long start, unsigned long end);
 #endif
index e21f9d44307f0004baf0146b4d02a20de6a96466..f3f302f9c1975a67ea1c01a828403950fac8a061 100644 (file)
@@ -9,7 +9,7 @@ struct msg_msg {
        struct list_head m_list;
        long m_type;
        size_t m_ts;            /* message text size */
-       struct msg_msgsegnext;
+       struct msg_msgseg *next;
        void *security;
        /* the actual message follows immediately */
 };
index 68891313875d756a4151aa54847214277e62ba79..628a6a21ddf035063c07051c95b25b24686fb246 100644 (file)
@@ -3,6 +3,6 @@
 
 #include <linux/mtd/mtd.h>
 int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
-                       unsigned long size, char *name);
+                       unsigned long size, const char *name);
 
 #endif /* __MTD_MTDRAM_H__ */
index 9e6c8f9f306e016923a0c32d3ae0e2d9f0ce0d1f..32f8612469d8d2d2c5a659f9326551bcbbd8806b 100644 (file)
@@ -219,6 +219,9 @@ struct nand_chip;
 /* ONFI feature address */
 #define ONFI_FEATURE_ADDR_TIMING_MODE  0x1
 
+/* Vendor-specific feature address (Micron) */
+#define ONFI_FEATURE_ADDR_READ_RETRY   0x89
+
 /* ONFI subfeature parameters length */
 #define ONFI_SUBFEATURE_PARAM_LEN      4
 
@@ -279,16 +282,17 @@ struct nand_onfi_params {
        __le16 io_pin_capacitance_typ;
        __le16 input_pin_capacitance_typ;
        u8 input_pin_capacitance_max;
-       u8 driver_strenght_support;
+       u8 driver_strength_support;
        __le16 t_int_r;
        __le16 t_ald;
        u8 reserved4[7];
 
        /* vendor */
-       u8 reserved5[90];
+       __le16 vendor_revision;
+       u8 vendor[88];
 
        __le16 crc;
-} __attribute__((packed));
+} __packed;
 
 #define ONFI_CRC_BASE  0x4F4E
 
@@ -326,6 +330,26 @@ struct onfi_ext_param_page {
         */
 } __packed;
 
+struct nand_onfi_vendor_micron {
+       u8 two_plane_read;
+       u8 read_cache;
+       u8 read_unique_id;
+       u8 dq_imped;
+       u8 dq_imped_num_settings;
+       u8 dq_imped_feat_addr;
+       u8 rb_pulldown_strength;
+       u8 rb_pulldown_strength_feat_addr;
+       u8 rb_pulldown_strength_num_settings;
+       u8 otp_mode;
+       u8 otp_page_start;
+       u8 otp_data_prot_addr;
+       u8 otp_num_pages;
+       u8 otp_feat_addr;
+       u8 read_retry_options;
+       u8 reserved[72];
+       u8 param_revision;
+} __packed;
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -432,6 +456,8 @@ struct nand_buffers {
  *                     flash device.
  * @read_byte:         [REPLACEABLE] read one byte from the chip
  * @read_word:         [REPLACEABLE] read one word from the chip
+ * @write_byte:                [REPLACEABLE] write a single byte to the chip on the
+ *                     low 8 I/O lines
  * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
  * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
  * @select_chip:       [REPLACEABLE] select chip nr
@@ -451,6 +477,8 @@ struct nand_buffers {
  *                     commands to the chip.
  * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on
  *                     ready.
+ * @setup_read_retry:  [FLASHSPECIFIC] flash (vendor) specific function for
+ *                     setting the read-retry mode. Mostly needed for MLC NAND.
  * @ecc:               [BOARDSPECIFIC] ECC control structure
  * @buffers:           buffer structure for read/write
  * @hwcontrol:         platform-specific hardware control structure
@@ -497,6 +525,7 @@ struct nand_buffers {
  *                     non 0 if ONFI supported.
  * @onfi_params:       [INTERN] holds the ONFI page parameter when ONFI is
  *                     supported, 0 otherwise.
+ * @read_retries:      [INTERN] the number of read retry modes supported
  * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
  * @bbt:               [INTERN] bad block table pointer
@@ -521,6 +550,7 @@ struct nand_chip {
 
        uint8_t (*read_byte)(struct mtd_info *mtd);
        u16 (*read_word)(struct mtd_info *mtd);
+       void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
        void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
        void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
        void (*select_chip)(struct mtd_info *mtd, int chip);
@@ -544,6 +574,7 @@ struct nand_chip {
                        int feature_addr, uint8_t *subfeature_para);
        int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
                        int feature_addr, uint8_t *subfeature_para);
+       int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
 
        int chip_delay;
        unsigned int options;
@@ -568,6 +599,8 @@ struct nand_chip {
        int onfi_version;
        struct nand_onfi_params onfi_params;
 
+       int read_retries;
+
        flstate_t state;
 
        uint8_t *oob_poi;
@@ -600,6 +633,8 @@ struct nand_chip {
 #define NAND_MFR_AMD           0x01
 #define NAND_MFR_MACRONIX      0xc2
 #define NAND_MFR_EON           0x92
+#define NAND_MFR_SANDISK       0x45
+#define NAND_MFR_INTEL         0x89
 
 /* The maximum expected count of bytes in the NAND ID sequence */
 #define NAND_MAX_ID_LEN 8
index 1f8d24bdafdac2bc28789c777315068311368765..6a35e6de5da174fc7b9f82f67be421f4d74a1cc3 100644 (file)
@@ -37,7 +37,7 @@
  */
 
 struct mtd_partition {
-       char *name;                     /* identifier string */
+       const char *name;               /* identifier string */
        uint64_t size;                  /* partition size */
        uint64_t offset;                /* offset within the master MTD space */
        uint32_t mask_flags;            /* master MTD flags to mask out for this partition */
@@ -76,11 +76,11 @@ struct mtd_part_parser {
                        struct mtd_part_parser_data *);
 };
 
-extern int register_mtd_parser(struct mtd_part_parser *parser);
-extern int deregister_mtd_parser(struct mtd_part_parser *parser);
+extern void register_mtd_parser(struct mtd_part_parser *parser);
+extern void deregister_mtd_parser(struct mtd_part_parser *parser);
 
 int mtd_is_partition(const struct mtd_info *mtd);
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length);
 int mtd_del_partition(struct mtd_info *master, int partno);
 uint64_t mtd_get_device_size(const struct mtd_info *mtd);
index 48997374eaf04eac0d52b8bf8d60c61c35944df3..2b00625952a7c618c34c30bc7f145a231194ed89 100644 (file)
@@ -154,10 +154,6 @@ struct nfs_inode {
        struct rb_root          access_cache;
        struct list_head        access_cache_entry_lru;
        struct list_head        access_cache_inode_lru;
-#ifdef CONFIG_NFS_V3_ACL
-       struct posix_acl        *acl_access;
-       struct posix_acl        *acl_default;
-#endif
 
        /*
         * This is the cookie verifier used for NFSv3 readdir
@@ -564,23 +560,17 @@ extern int  nfs_readpage_async(struct nfs_open_context *, struct inode *,
  * linux/fs/nfs3proc.c
  */
 #ifdef CONFIG_NFS_V3_ACL
-extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
-extern int nfs3_proc_setacl(struct inode *inode, int type,
-                           struct posix_acl *acl);
-extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               umode_t mode);
-extern void nfs3_forget_cached_acls(struct inode *inode);
+extern struct posix_acl *nfs3_get_acl(struct inode *inode, int type);
+extern int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type);
+extern int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+               struct posix_acl *dfacl);
+extern const struct xattr_handler *nfs3_xattr_handlers[];
 #else
-static inline int nfs3_proc_set_default_acl(struct inode *dir,
-                                           struct inode *inode,
-                                           umode_t mode)
+static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+               struct posix_acl *dfacl)
 {
        return 0;
 }
-
-static inline void nfs3_forget_cached_acls(struct inode *inode)
-{
-}
 #endif /* CONFIG_NFS_V3_ACL */
 
 /*
index 5dc635f8d79e09a4a6976c3e536cbfb506b16689..520681b6820817b6f08cb304503bf75b8f8f564f 100644 (file)
@@ -44,11 +44,12 @@ enum utf16_endian {
 };
 
 /* nls_base.c */
-extern int register_nls(struct nls_table *);
+extern int __register_nls(struct nls_table *, struct module *);
 extern int unregister_nls(struct nls_table *);
 extern struct nls_table *load_nls(char *);
 extern void unload_nls(struct nls_table *);
 extern struct nls_table *load_nls_default(void);
+#define register_nls(nls) __register_nls((nls), THIS_MODULE)
 
 extern int utf8_to_utf32(const u8 *s, int len, unicode_t *pu);
 extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen);
index 0beaee9dac1f1480a51c36ade2004d8b3a69cbce..2b77058a73351dec2842e779d35d04dafaf4c5e1 100644 (file)
@@ -116,6 +116,7 @@ extern const void *of_flat_dt_match_machine(const void *default_match,
 extern void unflatten_device_tree(void);
 extern void unflatten_and_copy_device_tree(void);
 extern void early_init_devtree(void *);
+extern void early_get_first_memblock_info(void *, phys_addr_t *);
 #else /* CONFIG_OF_FLATTREE */
 static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
 static inline void unflatten_device_tree(void) {}
index 6f10e938ff7e74d4db19b991a55193f5073946e7..cb32d9c1e8dc83502e39143a8c25913bab3193d5 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef __LINUX_OF_MTD_H
-#define __LINUX_OF_NET_H
+#define __LINUX_OF_MTD_H
 
 #ifdef CONFIG_OF_MTD
 
index 24b536ebdf13de364c5c5bf0f0106d654eb94d31..d2be19a51acde32102710cdf0db536fe4d364f01 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
- *
  * Platform data structure for netxbig LED driver
  *
  * This file is licensed under the terms of the GNU General Public
@@ -8,8 +6,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __MACH_LEDS_NETXBIG_H
-#define __MACH_LEDS_NETXBIG_H
+#ifndef __LEDS_KIRKWOOD_NETXBIG_H
+#define __LEDS_KIRKWOOD_NETXBIG_H
 
 struct netxbig_gpio_ext {
        unsigned        *addr;
@@ -52,4 +50,4 @@ struct netxbig_led_platform_data {
        int                     num_leds;
 };
 
-#endif /* __MACH_LEDS_NETXBIG_H */
+#endif /* __LEDS_KIRKWOOD_NETXBIG_H */
index e21272e5f66847112a7805ed90730e0eca612b42..6a9fed57f34620c20a931f317150e5a381058e8f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/mach-kirkwood/include/mach/leds-ns2.h
- *
  * Platform data structure for Network Space v2 LED driver
  *
  * This file is licensed under the terms of the GNU General Public
@@ -8,8 +6,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __MACH_LEDS_NS2_H
-#define __MACH_LEDS_NS2_H
+#ifndef __LEDS_KIRKWOOD_NS2_H
+#define __LEDS_KIRKWOOD_NS2_H
 
 struct ns2_led {
        const char      *name;
@@ -23,4 +21,4 @@ struct ns2_led_platform_data {
        struct ns2_led  *leds;
 };
 
-#endif /* __MACH_LEDS_NS2_H */
+#endif /* __LEDS_KIRKWOOD_NS2_H */
index 4da5bfa2147f245ab980c3a1514647ef40eecf4b..3e9dd6676b9799aba4999d422a624f9a3a991b44 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/nand.h
- *
  * Copyright (C) 2006 Micron Technology Inc.
  *
  * This program is free software; you can redistribute it and/or modify
index ffb801998e5dfa10c450f99b2dbb943e8f7a05d4..a941471249299c842a7cfea12de9a4091d2e44e2 100644 (file)
@@ -55,6 +55,9 @@ struct pxa3xx_nand_platform_data {
        /* indicate how many chip selects will be used */
        int     num_cs;
 
+       /* use an flash-based bad block table */
+       bool    flash_bbt;
+
        const struct mtd_partition              *parts[NUM_CHIP_SELECT];
        unsigned int                            nr_parts[NUM_CHIP_SELECT];
 
index e9a9fb188f972555172349a8e0250ac237c7db5d..56ff0e6f5ad1dae5bfe9d774a71cb85a32856afa 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/arm/plat-omap/include/mach/onenand.h
- *
  * Copyright (C) 2006 Nokia Corporation
  * Author: Juha Yrjola
  *
index 9f3c180834d141a269f7c4ec84c8021532029c9c..a7ce77c7c1a8e5d5d7009e9122c1684fa3b70d95 100644 (file)
@@ -1,13 +1,11 @@
 /*
- * arch/arm/plat-orion/include/plat/orion_nand.h
- *
  * This file is licensed under the terms of the GNU General Public
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __PLAT_ORION_NAND_H
-#define __PLAT_ORION_NAND_H
+#ifndef __MTD_ORION_NAND_H
+#define __MTD_ORION_NAND_H
 
 /*
  * Device bus NAND private data
index 54334393ab926ada9935fa5aba6e1a3756b27a88..a947ab8b441ad968f0953e6ce15d03270325e55b 100644 (file)
@@ -7,20 +7,6 @@
 
 struct clk;
 
-/**
- * enum si5351_variant - SiLabs Si5351 chip variant
- * @SI5351_VARIANT_A: Si5351A (8 output clocks, XTAL input)
- * @SI5351_VARIANT_A3: Si5351A MSOP10 (3 output clocks, XTAL input)
- * @SI5351_VARIANT_B: Si5351B (8 output clocks, XTAL/VXCO input)
- * @SI5351_VARIANT_C: Si5351C (8 output clocks, XTAL/CLKIN input)
- */
-enum si5351_variant {
-       SI5351_VARIANT_A = 1,
-       SI5351_VARIANT_A3 = 2,
-       SI5351_VARIANT_B = 3,
-       SI5351_VARIANT_C = 4,
-};
-
 /**
  * enum si5351_pll_src - Si5351 pll clock source
  * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config
@@ -115,14 +101,12 @@ struct si5351_clkout_config {
 
 /**
  * struct si5351_platform_data - Platform data for the Si5351 clock driver
- * @variant: Si5351 chip variant
  * @clk_xtal: xtal input clock
  * @clk_clkin: clkin input clock
  * @pll_src: array of pll source clock setting
  * @clkout: array of clkout configuration
  */
 struct si5351_platform_data {
-       enum si5351_variant variant;
        struct clk *clk_xtal;
        struct clk *clk_clkin;
        enum si5351_pll_src pll_src[2];
index 833099bf8090a24f5be28f6b074c918d5d677119..3e96a6a7610338ff8ddd825a21ddc9bc5fe52e8b 100644 (file)
@@ -85,12 +85,20 @@ extern int posix_acl_valid(const struct posix_acl *);
 extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
 extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
 extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);
-extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
-extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
+extern int __posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
+extern int __posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
 
 extern struct posix_acl *get_posix_acl(struct inode *, int);
 extern int set_posix_acl(struct inode *, int, struct posix_acl *);
 
+#ifdef CONFIG_FS_POSIX_ACL
+extern int posix_acl_chmod(struct inode *, umode_t);
+extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
+               struct posix_acl **);
+
+extern int simple_set_acl(struct inode *, struct posix_acl *, int);
+extern int simple_acl_create(struct inode *, struct inode *);
+
 struct posix_acl **acl_by_type(struct inode *inode, int type);
 struct posix_acl *get_cached_acl(struct inode *inode, int type);
 struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type);
@@ -100,10 +108,37 @@ void forget_all_cached_acls(struct inode *inode);
 
 static inline void cache_no_acl(struct inode *inode)
 {
-#ifdef CONFIG_FS_POSIX_ACL
        inode->i_acl = NULL;
        inode->i_default_acl = NULL;
-#endif
 }
+#else
+static inline int posix_acl_chmod(struct inode *inode, umode_t mode)
+{
+       return 0;
+}
+
+#define simple_set_acl         NULL
+
+static inline int simple_acl_create(struct inode *dir, struct inode *inode)
+{
+       return 0;
+}
+static inline void cache_no_acl(struct inode *inode)
+{
+}
+
+static inline int posix_acl_create(struct inode *inode, umode_t *mode,
+               struct posix_acl **default_acl, struct posix_acl **acl)
+{
+       *default_acl = *acl = NULL;
+       return 0;
+}
+
+static inline void forget_all_cached_acls(struct inode *inode)
+{
+}
+#endif /* CONFIG_FS_POSIX_ACL */
+
+struct posix_acl *get_acl(struct inode *inode, int type);
 
 #endif  /* __LINUX_POSIX_ACL_H */
index ad93ad0f1db0b0afe072d587a6fd1507f2e35d84..6f14ee2958220b03afcb8c41a8fc2cdcad9ea940 100644 (file)
@@ -69,4 +69,7 @@ struct posix_acl *posix_acl_from_xattr(struct user_namespace *user_ns,
 int posix_acl_to_xattr(struct user_namespace *user_ns,
                       const struct posix_acl *acl, void *buffer, size_t size);
 
+extern const struct xattr_handler posix_acl_access_xattr_handler;
+extern const struct xattr_handler posix_acl_default_xattr_handler;
+
 #endif /* _POSIX_ACL_XATTR_H */
index 3e355c688618e66391d535de3e183bf9c9ec8cba..72bf3a01a4ee67ac8908212c3de3897d383a2161 100644 (file)
@@ -449,8 +449,6 @@ static inline int rcu_read_lock_sched_held(void)
 
 #ifdef CONFIG_PROVE_RCU
 
-int rcu_my_thread_group_empty(void);
-
 /**
  * rcu_lockdep_assert - emit lockdep splat if specified condition not met
  * @c: condition to check
index 429c1995d756634f82906af0ad532d5423ec7622..1e2cd2e6b5407956ab9a70f815a5a521da5ffea2 100644 (file)
@@ -9,7 +9,7 @@
 struct shmid_kernel /* private to the kernel */
 {      
        struct kern_ipc_perm    shm_perm;
-       struct file *           shm_file;
+       struct file             *shm_file;
        unsigned long           shm_nattch;
        unsigned long           shm_segsz;
        time_t                  shm_atim;
index 74575cbf2d6f579c317fec5f1f16e9d3793fab03..0e43906d2fda6dc68cffc6343594178465d6e461 100644 (file)
@@ -24,7 +24,8 @@
  * Passed to the actors
  */
 struct splice_desc {
-       unsigned int len, total_len;    /* current and remaining length */
+       size_t total_len;               /* remaining length */
+       unsigned int len;               /* current length */
        unsigned int flags;             /* splice flags */
        /*
         * actor() private data
index a353e0300b54b97a63cf4b87baf28cacf91428b8..7f490bef9e99f9838294bbb674e3014a7128185b 100644 (file)
@@ -84,7 +84,8 @@ enum {
 
 extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
                                      const unsigned char *dir_name);
-extern void rpc_pipefs_init_net(struct net *net);
+extern int rpc_pipefs_init_net(struct net *net);
+extern void rpc_pipefs_exit_net(struct net *net);
 extern struct super_block *rpc_get_sb_net(const struct net *net);
 extern void rpc_put_sb_net(const struct net *net);
 
@@ -130,5 +131,7 @@ extern int rpc_unlink(struct dentry *);
 extern int register_rpc_pipefs(void);
 extern void unregister_rpc_pipefs(void);
 
+extern bool gssd_running(struct net *net);
+
 #endif
 #endif
index e4b948080d20e7a537c7a83da17b8b5b7fec0008..a67b384157689ec9fda2abfec0173122fc98a4a8 100644 (file)
@@ -142,8 +142,6 @@ static inline unsigned long zone_page_state_snapshot(struct zone *zone,
        return x;
 }
 
-extern unsigned long global_reclaimable_pages(void);
-
 #ifdef CONFIG_NUMA
 /*
  * Determine the per node value of a stat item. This function
index 9696a5e2c437f3e33dc8f4d2bd50f8ff8bff6a53..6bdf8c61d221f7267914974958f96f2cc2156460 100644 (file)
@@ -685,7 +685,7 @@ do {                                                                        \
            else                                                                \
              {                                                                 \
                r = 0;                                                          \
-               if (X##_s)                                                      \
+               if (!X##_s)                                                     \
                  r = ~r;                                                       \
              }                                                                 \
            FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
@@ -743,12 +743,17 @@ do {                                                                      \
          }                                                                     \
        else                                                                    \
          {                                                                     \
+           int _lz0, _lz1;                                                     \
            if (X##_e <= -_FP_WORKBITS - 1)                                     \
              _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                           \
            else                                                                \
              _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,               \
                                _FP_WFRACBITS_##fs);                            \
+           _FP_FRAC_CLZ_##wc(_lz0, X);                                         \
            _FP_ROUND(wc, X);                                                   \
+           _FP_FRAC_CLZ_##wc(_lz1, X);                                         \
+           if (_lz1 < _lz0)                                                    \
+             X##_e++; /* For overflow detection.  */                           \
            _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                                 \
            _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                                \
          }                                                                     \
@@ -762,7 +767,7 @@ do {                                                                        \
            if (!rsigned)                                                       \
              {                                                                 \
                r = 0;                                                          \
-               if (X##_s)                                                      \
+               if (!X##_s)                                                     \
                  r = ~r;                                                       \
              }                                                                 \
            else if (rsigned != 2)                                              \
index a5f9b960dfc8f0ca329c1fc510956f379e817fdd..6ca3265a4dcacaff704e32a329f546a421c2971e 100644 (file)
@@ -102,6 +102,7 @@ struct ore_striping_info {
        unsigned unit_off;
        unsigned cur_pg;
        unsigned cur_comp;
+       unsigned maxdevUnits;
 };
 
 struct ore_io_state;
index d51d16c7afd86d64b02092f0a8e4969b4ab5eaa2..ddc179b7a1052aa6c3fb9df408e3b5ad9e50d792 100644 (file)
@@ -301,6 +301,7 @@ DECLARE_EVENT_CLASS(xs_socket_event_done,
 
 DEFINE_RPC_SOCKET_EVENT(rpc_socket_state_change);
 DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_connect);
+DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_error);
 DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_reset_connection);
 DEFINE_RPC_SOCKET_EVENT(rpc_socket_close);
 DEFINE_RPC_SOCKET_EVENT(rpc_socket_shutdown);
index 7c098ac9068a582af317596908390ad74011040e..a8227022e3a02210afaab0cc628729f80ca07af8 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/minix_fs.h>
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
-#include <linux/cramfs_fs.h>
+#include <uapi/linux/cramfs_fs.h>
 #include <linux/initrd.h>
 #include <linux/string.h>
 #include <linux/slab.h>
index 3f1f4e4b61f7618452a8c1a93e298bb409c2e054..2fd9cef70ee8aa86261d8e2439b1c2a50f130925 100644 (file)
@@ -92,8 +92,6 @@ static int kernel_init(void *);
 
 extern void init_IRQ(void);
 extern void fork_init(unsigned long);
-extern void mca_init(void);
-extern void sbus_init(void);
 extern void radix_tree_init(void);
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
index 892f6585dd6014a7b1fb70cabd8f7ce0d2f9a4ad..f486b0096a67f32fe453cca13b40ad6268a76d45 100644 (file)
@@ -197,7 +197,7 @@ static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
 static inline int get_compat_semid64_ds(struct semid64_ds *s64,
                                        struct compat_semid64_ds __user *up64)
 {
-       if (!access_ok (VERIFY_READ, up64, sizeof(*up64)))
+       if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
                return -EFAULT;
        return __get_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
 }
@@ -205,7 +205,7 @@ static inline int get_compat_semid64_ds(struct semid64_ds *s64,
 static inline int get_compat_semid_ds(struct semid64_ds *s,
                                      struct compat_semid_ds __user *up)
 {
-       if (!access_ok (VERIFY_READ, up, sizeof(*up)))
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)))
                return -EFAULT;
        return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
 }
@@ -215,7 +215,7 @@ static inline int put_compat_semid64_ds(struct semid64_ds *s64,
 {
        int err;
 
-       if (!access_ok (VERIFY_WRITE, up64, sizeof(*up64)))
+       if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
                return -EFAULT;
        err  = __put_compat_ipc64_perm(&s64->sem_perm, &up64->sem_perm);
        err |= __put_user(s64->sem_otime, &up64->sem_otime);
@@ -229,7 +229,7 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
 {
        int err;
 
-       if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
                return -EFAULT;
        err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
        err |= __put_user(s->sem_otime, &up->sem_otime);
@@ -288,11 +288,11 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
                break;
 
        case IPC_SET:
-               if (version == IPC_64) {
+               if (version == IPC_64)
                        err = get_compat_semid64_ds(&s64, compat_ptr(pad));
-               } else {
+               else
                        err = get_compat_semid_ds(&s64, compat_ptr(pad));
-               }
+
                up64 = compat_alloc_user_space(sizeof(s64));
                if (copy_to_user(up64, &s64, sizeof(s64)))
                        err = -EFAULT;
@@ -376,12 +376,12 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
                        struct compat_ipc_kludge ipck;
                        if (!uptr)
                                return -EINVAL;
-                       if (copy_from_user (&ipck, uptr, sizeof(ipck)))
+                       if (copy_from_user(&ipck, uptr, sizeof(ipck)))
                                return -EFAULT;
                        uptr = compat_ptr(ipck.msgp);
                        fifth = ipck.msgtyp;
                }
-               return do_msgrcv(first, uptr, second, fifth, third,
+               return do_msgrcv(first, uptr, second, (s32)fifth, third,
                                 compat_do_msg_fill);
        }
        case MSGGET:
@@ -515,11 +515,11 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
                break;
 
        case IPC_SET:
-               if (version == IPC_64) {
+               if (version == IPC_64)
                        err = get_compat_msqid64(&m64, uptr);
-               } else {
+               else
                        err = get_compat_msqid(&m64, uptr);
-               }
+
                if (err)
                        break;
                p = compat_alloc_user_space(sizeof(m64));
@@ -702,11 +702,11 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
 
 
        case IPC_SET:
-               if (version == IPC_64) {
+               if (version == IPC_64)
                        err = get_compat_shmid64_ds(&s64, uptr);
-               } else {
+               else
                        err = get_compat_shmid_ds(&s64, uptr);
-               }
+
                if (err)
                        break;
                p = compat_alloc_user_space(sizeof(s64));
index 380ea4fe08e7151c71c64a39eac8a9e92a2ea7ee..63d7c6de335bd3b4878f8f2cf65d1d9e3f7e9474 100644 (file)
@@ -64,7 +64,7 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name,
        return sys_mq_open(u_name, oflag, mode, p);
 }
 
-static int compat_prepare_timeout(struct timespec __user * *p,
+static int compat_prepare_timeout(struct timespec __user **p,
                                  const struct compat_timespec __user *u)
 {
        struct timespec ts;
index b0e99deb6d05330482c8ec98f1a511f07f9fa5f1..17028648cfeb05fc4b76470ca343cd069a11bb02 100644 (file)
@@ -164,21 +164,21 @@ static struct ctl_table ipc_kern_table[] = {
        {
                .procname       = "shmmax",
                .data           = &init_ipc_ns.shm_ctlmax,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
+               .maxlen         = sizeof(init_ipc_ns.shm_ctlmax),
                .mode           = 0644,
                .proc_handler   = proc_ipc_doulongvec_minmax,
        },
        {
                .procname       = "shmall",
                .data           = &init_ipc_ns.shm_ctlall,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
+               .maxlen         = sizeof(init_ipc_ns.shm_ctlall),
                .mode           = 0644,
                .proc_handler   = proc_ipc_doulongvec_minmax,
        },
        {
                .procname       = "shmmni",
                .data           = &init_ipc_ns.shm_ctlmni,
-               .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
+               .maxlen         = sizeof(init_ipc_ns.shm_ctlmni),
                .mode           = 0644,
                .proc_handler   = proc_ipc_dointvec,
        },
@@ -194,7 +194,7 @@ static struct ctl_table ipc_kern_table[] = {
        {
                .procname       = "msgmax",
                .data           = &init_ipc_ns.msg_ctlmax,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
+               .maxlen         = sizeof(init_ipc_ns.msg_ctlmax),
                .mode           = 0644,
                .proc_handler   = proc_ipc_dointvec_minmax,
                .extra1         = &zero,
@@ -203,7 +203,7 @@ static struct ctl_table ipc_kern_table[] = {
        {
                .procname       = "msgmni",
                .data           = &init_ipc_ns.msg_ctlmni,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
+               .maxlen         = sizeof(init_ipc_ns.msg_ctlmni),
                .mode           = 0644,
                .proc_handler   = proc_ipc_callback_dointvec_minmax,
                .extra1         = &zero,
@@ -212,7 +212,7 @@ static struct ctl_table ipc_kern_table[] = {
        {
                .procname       =  "msgmnb",
                .data           = &init_ipc_ns.msg_ctlmnb,
-               .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
+               .maxlen         = sizeof(init_ipc_ns.msg_ctlmnb),
                .mode           = 0644,
                .proc_handler   = proc_ipc_dointvec_minmax,
                .extra1         = &zero,
@@ -221,7 +221,7 @@ static struct ctl_table ipc_kern_table[] = {
        {
                .procname       = "sem",
                .data           = &init_ipc_ns.sem_ctls,
-               .maxlen         = 4*sizeof (int),
+               .maxlen         = 4*sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_ipc_dointvec,
        },
index 95827ce2f3c78e76adfdef64278a227402356587..ccf1f9fd263acdfae7dc56a87bceddd3170f69d9 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Spinlocks:               Mohamed Abbas           (abbas.mohamed@intel.com)
  * Lockless receive & send, fd based notify:
- *                         Manfred Spraul          (manfred@colorfullife.com)
+ *                         Manfred Spraul          (manfred@colorfullife.com)
  *
  * Audit:                   George Wilson           (ltcgcw@us.ibm.com)
  *
@@ -73,7 +73,7 @@ struct mqueue_inode_info {
        struct mq_attr attr;
 
        struct sigevent notify;
-       struct pidnotify_owner;
+       struct pid *notify_owner;
        struct user_namespace *notify_user_ns;
        struct user_struct *user;       /* user who created, for accounting */
        struct sock *notify_sock;
@@ -92,7 +92,7 @@ static void remove_notification(struct mqueue_inode_info *info);
 
 static struct kmem_cache *mqueue_inode_cachep;
 
-static struct ctl_table_header * mq_sysctl_table;
+static struct ctl_table_header *mq_sysctl_table;
 
 static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode)
 {
@@ -466,13 +466,13 @@ out_unlock:
 
 static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = dentry->d_inode;
 
        dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
        dir->i_size -= DIRENT_SIZE;
-       drop_nlink(inode);
-       dput(dentry);
-       return 0;
+       drop_nlink(inode);
+       dput(dentry);
+       return 0;
 }
 
 /*
@@ -622,7 +622,7 @@ static struct ext_wait_queue *wq_get_first_waiter(
 
 static inline void set_cookie(struct sk_buff *skb, char code)
 {
-       ((char*)skb->data)[NOTIFY_COOKIE_LEN-1] = code;
+       ((char *)skb->data)[NOTIFY_COOKIE_LEN-1] = code;
 }
 
 /*
@@ -1303,11 +1303,11 @@ retry:
 out_fput:
        fdput(f);
 out:
-       if (sock) {
+       if (sock)
                netlink_detachskb(sock, nc);
-       } else if (nc) {
+       else if (nc)
                dev_kfree_skb(nc);
-       }
+
        return ret;
 }
 
index 558aa91186b6ced1a27b1e05b65c5ee129e0a175..245db1140ad66a2be47744f02ef0d80deea5006f 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -253,8 +253,14 @@ static void expunge_all(struct msg_queue *msq, int res)
        struct msg_receiver *msr, *t;
 
        list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
-               msr->r_msg = NULL;
+               msr->r_msg = NULL; /* initialize expunge ordering */
                wake_up_process(msr->r_tsk);
+               /*
+                * Ensure that the wakeup is visible before setting r_msg as
+                * the receiving end depends on it: either spinning on a nil,
+                * or dealing with -EAGAIN cases. See lockless receive part 1
+                * and 2 in do_msgrcv().
+                */
                smp_mb();
                msr->r_msg = ERR_PTR(res);
        }
@@ -318,7 +324,7 @@ SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
 static inline unsigned long
 copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                return copy_to_user(buf, in, sizeof(*in));
        case IPC_OLD:
@@ -363,7 +369,7 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
 static inline unsigned long
 copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
@@ -375,9 +381,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
                if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
                        return -EFAULT;
 
-               out->msg_perm.uid       = tbuf_old.msg_perm.uid;
-               out->msg_perm.gid       = tbuf_old.msg_perm.gid;
-               out->msg_perm.mode      = tbuf_old.msg_perm.mode;
+               out->msg_perm.uid       = tbuf_old.msg_perm.uid;
+               out->msg_perm.gid       = tbuf_old.msg_perm.gid;
+               out->msg_perm.mode      = tbuf_old.msg_perm.mode;
 
                if (tbuf_old.msg_qbytes == 0)
                        out->msg_qbytes = tbuf_old.msg_lqbytes;
@@ -606,13 +612,13 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
 
 static int testmsg(struct msg_msg *msg, long type, int mode)
 {
-       switch(mode)
+       switch (mode)
        {
                case SEARCH_ANY:
                case SEARCH_NUMBER:
                        return 1;
                case SEARCH_LESSEQUAL:
-                       if (msg->m_type <=type)
+                       if (msg->m_type <= type)
                                return 1;
                        break;
                case SEARCH_EQUAL:
@@ -638,15 +644,22 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
 
                        list_del(&msr->r_list);
                        if (msr->r_maxsize < msg->m_ts) {
+                               /* initialize pipelined send ordering */
                                msr->r_msg = NULL;
                                wake_up_process(msr->r_tsk);
-                               smp_mb();
+                               smp_mb(); /* see barrier comment below */
                                msr->r_msg = ERR_PTR(-E2BIG);
                        } else {
                                msr->r_msg = NULL;
                                msq->q_lrpid = task_pid_vnr(msr->r_tsk);
                                msq->q_rtime = get_seconds();
                                wake_up_process(msr->r_tsk);
+                               /*
+                                * Ensure that the wakeup is visible before
+                                * setting r_msg, as the receiving end depends
+                                * on it. See lockless receive part 1 and 2 in
+                                * do_msgrcv().
+                                */
                                smp_mb();
                                msr->r_msg = msg;
 
@@ -654,6 +667,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
                        }
                }
        }
+
        return 0;
 }
 
@@ -696,7 +710,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
                        goto out_unlock0;
 
                /* raced with RMID? */
-               if (msq->q_perm.deleted) {
+               if (!ipc_valid_object(&msq->q_perm)) {
                        err = -EIDRM;
                        goto out_unlock0;
                }
@@ -716,6 +730,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
                        goto out_unlock0;
                }
 
+               /* enqueue the sender and prepare to block */
                ss_add(msq, &s);
 
                if (!ipc_rcu_getref(msq)) {
@@ -731,7 +746,8 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
                ipc_lock_object(&msq->q_perm);
 
                ipc_rcu_putref(msq, ipc_rcu_free);
-               if (msq->q_perm.deleted) {
+               /* raced with RMID? */
+               if (!ipc_valid_object(&msq->q_perm)) {
                        err = -EIDRM;
                        goto out_unlock0;
                }
@@ -909,7 +925,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
                ipc_lock_object(&msq->q_perm);
 
                /* raced with RMID? */
-               if (msq->q_perm.deleted) {
+               if (!ipc_valid_object(&msq->q_perm)) {
                        msg = ERR_PTR(-EIDRM);
                        goto out_unlock0;
                }
@@ -983,7 +999,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
                 * wake_up_process(). There is a race with exit(), see
                 * ipc/mqueue.c for the details.
                 */
-               msg = (struct msg_msg*)msr_d.r_msg;
+               msg = (struct msg_msg *)msr_d.r_msg;
                while (msg == NULL) {
                        cpu_relax();
                        msg = (struct msg_msg *)msr_d.r_msg;
@@ -1004,7 +1020,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
                /* Lockless receive, part 4:
                 * Repeat test after acquiring the spinlock.
                 */
-               msg = (struct msg_msg*)msr_d.r_msg;
+               msg = (struct msg_msg *)msr_d.r_msg;
                if (msg != ERR_PTR(-EAGAIN))
                        goto out_unlock0;
 
index db9d241af133d770cb0a95a22cacf257f79b1215..bee5554173120780374e6b42228d13c786ceb315 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -188,7 +188,7 @@ void sem_exit_ns(struct ipc_namespace *ns)
 }
 #endif
 
-void __init sem_init (void)
+void __init sem_init(void)
 {
        sem_init_ns(&init_ipc_ns);
        ipc_init_proc_interface("sysvipc/sem",
@@ -225,7 +225,7 @@ static void unmerge_queues(struct sem_array *sma)
 }
 
 /**
- * merge_queues - Merge single semop queues into global queue
+ * merge_queues - merge single semop queues into global queue
  * @sma: semaphore array
  *
  * This function merges all per-semaphore queues into the global queue.
@@ -394,7 +394,7 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns,
        /* ipc_rmid() may have already freed the ID while sem_lock
         * was spinning: verify that the structure is still valid
         */
-       if (!ipcp->deleted)
+       if (ipc_valid_object(ipcp))
                return container_of(ipcp, struct sem_array, sem_perm);
 
        sem_unlock(sma, *locknum);
@@ -445,11 +445,11 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  *     * call wake_up_process
  *     * set queue.status to the final value.
  * - the previously blocked thread checks queue.status:
- *     * if it's IN_WAKEUP, then it must wait until the value changes
- *     * if it's not -EINTR, then the operation was completed by
- *       update_queue. semtimedop can return queue.status without
- *       performing any operation on the sem array.
- *     * otherwise it must acquire the spinlock and check what's up.
+ *     * if it's IN_WAKEUP, then it must wait until the value changes
+ *     * if it's not -EINTR, then the operation was completed by
+ *       update_queue. semtimedop can return queue.status without
+ *       performing any operation on the sem array.
+ *     * otherwise it must acquire the spinlock and check what's up.
  *
  * The two-stage algorithm is necessary to protect against the following
  * races:
@@ -474,7 +474,6 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  *
  * Called with sem_ids.rwsem held (as a writer)
  */
-
 static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 {
        int id;
@@ -491,12 +490,12 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        if (ns->used_sems + nsems > ns->sc_semmns)
                return -ENOSPC;
 
-       size = sizeof (*sma) + nsems * sizeof (struct sem);
+       size = sizeof(*sma) + nsems * sizeof(struct sem);
        sma = ipc_rcu_alloc(size);
-       if (!sma) {
+       if (!sma)
                return -ENOMEM;
-       }
-       memset (sma, 0, size);
+
+       memset(sma, 0, size);
 
        sma->sem_perm.mode = (semflg & S_IRWXUGO);
        sma->sem_perm.key = key;
@@ -584,10 +583,11 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
        return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
 }
 
-/** perform_atomic_semop - Perform (if possible) a semaphore operation
+/**
+ * perform_atomic_semop - Perform (if possible) a semaphore operation
  * @sma: semaphore array
  * @sops: array with operations that should be checked
- * @nsems: number of sops
+ * @nsops: number of operations
  * @un: undo array
  * @pid: pid that did the change
  *
@@ -595,19 +595,18 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
  * Returns 1 if the operation is impossible, the caller must sleep.
  * Negative values are error codes.
  */
-
 static int perform_atomic_semop(struct sem_array *sma, struct sembuf *sops,
                             int nsops, struct sem_undo *un, int pid)
 {
        int result, sem_op;
        struct sembuf *sop;
-       struct sem * curr;
+       struct sem *curr;
 
        for (sop = sops; sop < sops + nsops; sop++) {
                curr = sma->sem_base + sop->sem_num;
                sem_op = sop->sem_op;
                result = curr->semval;
-  
+
                if (!sem_op && result)
                        goto would_block;
 
@@ -616,25 +615,24 @@ static int perform_atomic_semop(struct sem_array *sma, struct sembuf *sops,
                        goto would_block;
                if (result > SEMVMX)
                        goto out_of_range;
+
                if (sop->sem_flg & SEM_UNDO) {
                        int undo = un->semadj[sop->sem_num] - sem_op;
-                       /*
-                        *      Exceeding the undo range is an error.
-                        */
+                       /* Exceeding the undo range is an error. */
                        if (undo < (-SEMAEM - 1) || undo > SEMAEM)
                                goto out_of_range;
+                       un->semadj[sop->sem_num] = undo;
                }
+
                curr->semval = result;
        }
 
        sop--;
        while (sop >= sops) {
                sma->sem_base[sop->sem_num].sempid = pid;
-               if (sop->sem_flg & SEM_UNDO)
-                       un->semadj[sop->sem_num] -= sop->sem_op;
                sop--;
        }
-       
+
        return 0;
 
 out_of_range:
@@ -650,7 +648,10 @@ would_block:
 undo:
        sop--;
        while (sop >= sops) {
-               sma->sem_base[sop->sem_num].semval -= sop->sem_op;
+               sem_op = sop->sem_op;
+               sma->sem_base[sop->sem_num].semval -= sem_op;
+               if (sop->sem_flg & SEM_UNDO)
+                       un->semadj[sop->sem_num] += sem_op;
                sop--;
        }
 
@@ -680,7 +681,7 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
 }
 
 /**
- * wake_up_sem_queue_do(pt) - do the actual wake-up
+ * wake_up_sem_queue_do - do the actual wake-up
  * @pt: list of tasks to be woken up
  *
  * Do the actual wake-up.
@@ -746,7 +747,7 @@ static int check_restart(struct sem_array *sma, struct sem_queue *q)
 }
 
 /**
- * wake_const_ops(sma, semnum, pt) - Wake up non-alter tasks
+ * wake_const_ops - wake up non-alter tasks
  * @sma: semaphore array.
  * @semnum: semaphore that was modified.
  * @pt: list head for the tasks that must be woken up.
@@ -796,15 +797,14 @@ static int wake_const_ops(struct sem_array *sma, int semnum,
 }
 
 /**
- * do_smart_wakeup_zero(sma, sops, nsops, pt) - wakeup all wait for zero tasks
+ * do_smart_wakeup_zero - wakeup all wait for zero tasks
  * @sma: semaphore array
  * @sops: operations that were performed
  * @nsops: number of operations
  * @pt: list head of the tasks that must be woken up.
  *
- * do_smart_wakeup_zero() checks all required queue for wait-for-zero
- * operations, based on the actual changes that were performed on the
- * semaphore array.
+ * Checks all required queue for wait-for-zero operations, based
+ * on the actual changes that were performed on the semaphore array.
  * The function returns 1 if at least one operation was completed successfully.
  */
 static int do_smart_wakeup_zero(struct sem_array *sma, struct sembuf *sops,
@@ -848,7 +848,7 @@ static int do_smart_wakeup_zero(struct sem_array *sma, struct sembuf *sops,
 
 
 /**
- * update_queue(sma, semnum): Look for tasks that can be completed.
+ * update_queue - look for tasks that can be completed.
  * @sma: semaphore array.
  * @semnum: semaphore that was modified.
  * @pt: list head for the tasks that must be woken up.
@@ -918,7 +918,7 @@ again:
 }
 
 /**
- * set_semotime(sma, sops) - set sem_otime
+ * set_semotime - set sem_otime
  * @sma: semaphore array
  * @sops: operations that modified the array, may be NULL
  *
@@ -936,7 +936,7 @@ static void set_semotime(struct sem_array *sma, struct sembuf *sops)
 }
 
 /**
- * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
+ * do_smart_update - optimized update_queue
  * @sma: semaphore array
  * @sops: operations that were performed
  * @nsops: number of operations
@@ -998,21 +998,21 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
  * The counts we return here are a rough approximation, but still
  * warrant that semncnt+semzcnt>0 if the task is on the pending queue.
  */
-static int count_semncnt (struct sem_array * sma, ushort semnum)
+static int count_semncnt(struct sem_array *sma, ushort semnum)
 {
        int semncnt;
-       struct sem_queue * q;
+       struct sem_queue *q;
 
        semncnt = 0;
        list_for_each_entry(q, &sma->sem_base[semnum].pending_alter, list) {
-               struct sembuf * sops = q->sops;
+               struct sembuf *sops = q->sops;
                BUG_ON(sops->sem_num != semnum);
                if ((sops->sem_op < 0) && !(sops->sem_flg & IPC_NOWAIT))
                        semncnt++;
        }
 
        list_for_each_entry(q, &sma->pending_alter, list) {
-               struct sembuf * sops = q->sops;
+               struct sembuf *sops = q->sops;
                int nsops = q->nsops;
                int i;
                for (i = 0; i < nsops; i++)
@@ -1024,21 +1024,21 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
        return semncnt;
 }
 
-static int count_semzcnt (struct sem_array * sma, ushort semnum)
+static int count_semzcnt(struct sem_array *sma, ushort semnum)
 {
        int semzcnt;
-       struct sem_queue * q;
+       struct sem_queue *q;
 
        semzcnt = 0;
        list_for_each_entry(q, &sma->sem_base[semnum].pending_const, list) {
-               struct sembuf * sops = q->sops;
+               struct sembuf *sops = q->sops;
                BUG_ON(sops->sem_num != semnum);
                if ((sops->sem_op == 0) && !(sops->sem_flg & IPC_NOWAIT))
                        semzcnt++;
        }
 
        list_for_each_entry(q, &sma->pending_const, list) {
-               struct sembuf * sops = q->sops;
+               struct sembuf *sops = q->sops;
                int nsops = q->nsops;
                int i;
                for (i = 0; i < nsops; i++)
@@ -1108,7 +1108,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 
 static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                return copy_to_user(buf, in, sizeof(*in));
        case IPC_OLD:
@@ -1151,7 +1151,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
        int err;
        struct sem_array *sma;
 
-       switch(cmd) {
+       switch (cmd) {
        case IPC_INFO:
        case SEM_INFO:
        {
@@ -1162,7 +1162,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
                if (err)
                        return err;
                
-               memset(&seminfo,0,sizeof(seminfo));
+               memset(&seminfo, 0, sizeof(seminfo));
                seminfo.semmni = ns->sc_semmni;
                seminfo.semmns = ns->sc_semmns;
                seminfo.semmsl = ns->sc_semmsl;
@@ -1183,7 +1183,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
                up_read(&sem_ids(ns).rwsem);
                if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 
                        return -EFAULT;
-               return (max_id < 0) ? 0: max_id;
+               return (max_id < 0) ? 0 : max_id;
        }
        case IPC_STAT:
        case SEM_STAT:
@@ -1239,7 +1239,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 {
        struct sem_undo *un;
        struct sem_array *sma;
-       struct semcurr;
+       struct sem *curr;
        int err;
        struct list_head tasks;
        int val;
@@ -1282,7 +1282,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 
        sem_lock(sma, NULL, -1);
 
-       if (sma->sem_perm.deleted) {
+       if (!ipc_valid_object(&sma->sem_perm)) {
                sem_unlock(sma, -1);
                rcu_read_unlock();
                return -EIDRM;
@@ -1309,10 +1309,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int cmd, void __user *p)
 {
        struct sem_array *sma;
-       struct semcurr;
+       struct sem *curr;
        int err, nsems;
        ushort fast_sem_io[SEMMSL_FAST];
-       ushortsem_io = fast_sem_io;
+       ushort *sem_io = fast_sem_io;
        struct list_head tasks;
 
        INIT_LIST_HEAD(&tasks);
@@ -1342,11 +1342,11 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int i;
 
                sem_lock(sma, NULL, -1);
-               if (sma->sem_perm.deleted) {
+               if (!ipc_valid_object(&sma->sem_perm)) {
                        err = -EIDRM;
                        goto out_unlock;
                }
-               if(nsems > SEMMSL_FAST) {
+               if (nsems > SEMMSL_FAST) {
                        if (!ipc_rcu_getref(sma)) {
                                err = -EIDRM;
                                goto out_unlock;
@@ -1354,14 +1354,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                        sem_unlock(sma, -1);
                        rcu_read_unlock();
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
-                       if(sem_io == NULL) {
+                       if (sem_io == NULL) {
                                ipc_rcu_putref(sma, ipc_rcu_free);
                                return -ENOMEM;
                        }
 
                        rcu_read_lock();
                        sem_lock_and_putref(sma);
-                       if (sma->sem_perm.deleted) {
+                       if (!ipc_valid_object(&sma->sem_perm)) {
                                err = -EIDRM;
                                goto out_unlock;
                        }
@@ -1371,7 +1371,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                sem_unlock(sma, -1);
                rcu_read_unlock();
                err = 0;
-               if(copy_to_user(array, sem_io, nsems*sizeof(ushort)))
+               if (copy_to_user(array, sem_io, nsems*sizeof(ushort)))
                        err = -EFAULT;
                goto out_free;
        }
@@ -1386,15 +1386,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                }
                rcu_read_unlock();
 
-               if(nsems > SEMMSL_FAST) {
+               if (nsems > SEMMSL_FAST) {
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
-                       if(sem_io == NULL) {
+                       if (sem_io == NULL) {
                                ipc_rcu_putref(sma, ipc_rcu_free);
                                return -ENOMEM;
                        }
                }
 
-               if (copy_from_user (sem_io, p, nsems*sizeof(ushort))) {
+               if (copy_from_user(sem_io, p, nsems*sizeof(ushort))) {
                        ipc_rcu_putref(sma, ipc_rcu_free);
                        err = -EFAULT;
                        goto out_free;
@@ -1409,7 +1409,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                }
                rcu_read_lock();
                sem_lock_and_putref(sma);
-               if (sma->sem_perm.deleted) {
+               if (!ipc_valid_object(&sma->sem_perm)) {
                        err = -EIDRM;
                        goto out_unlock;
                }
@@ -1435,7 +1435,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                goto out_rcu_wakeup;
 
        sem_lock(sma, NULL, -1);
-       if (sma->sem_perm.deleted) {
+       if (!ipc_valid_object(&sma->sem_perm)) {
                err = -EIDRM;
                goto out_unlock;
        }
@@ -1449,10 +1449,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                err = curr->sempid;
                goto out_unlock;
        case GETNCNT:
-               err = count_semncnt(sma,semnum);
+               err = count_semncnt(sma, semnum);
                goto out_unlock;
        case GETZCNT:
-               err = count_semzcnt(sma,semnum);
+               err = count_semzcnt(sma, semnum);
                goto out_unlock;
        }
 
@@ -1462,7 +1462,7 @@ out_rcu_wakeup:
        rcu_read_unlock();
        wake_up_sem_queue_do(&tasks);
 out_free:
-       if(sem_io != fast_sem_io)
+       if (sem_io != fast_sem_io)
                ipc_free(sem_io, sizeof(ushort)*nsems);
        return err;
 }
@@ -1470,7 +1470,7 @@ out_free:
 static inline unsigned long
 copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
@@ -1479,7 +1479,7 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
            {
                struct semid_ds tbuf_old;
 
-               if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+               if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
                        return -EFAULT;
 
                out->sem_perm.uid       = tbuf_old.sem_perm.uid;
@@ -1506,7 +1506,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
        struct semid64_ds semid64;
        struct kern_ipc_perm *ipcp;
 
-       if(cmd == IPC_SET) {
+       if (cmd == IPC_SET) {
                if (copy_semid_from_user(&semid64, p, version))
                        return -EFAULT;
        }
@@ -1566,7 +1566,7 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
        version = ipc_parse_version(&cmd);
        ns = current->nsproxy->ipc_ns;
 
-       switch(cmd) {
+       switch (cmd) {
        case IPC_INFO:
        case SEM_INFO:
        case IPC_STAT:
@@ -1634,7 +1634,7 @@ static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
 {
        struct sem_undo *un;
 
-       assert_spin_locked(&ulp->lock);
+       assert_spin_locked(&ulp->lock);
 
        un = __lookup_undo(ulp, semid);
        if (un) {
@@ -1645,7 +1645,7 @@ static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
 }
 
 /**
- * find_alloc_undo - Lookup (and if not present create) undo array
+ * find_alloc_undo - lookup (and if not present create) undo array
  * @ns: namespace
  * @semid: semaphore array id
  *
@@ -1670,7 +1670,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
        spin_lock(&ulp->lock);
        un = lookup_undo(ulp, semid);
        spin_unlock(&ulp->lock);
-       if (likely(un!=NULL))
+       if (likely(un != NULL))
                goto out;
 
        /* no undo structure around - allocate one. */
@@ -1699,7 +1699,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
        /* step 3: Acquire the lock on semaphore array */
        rcu_read_lock();
        sem_lock_and_putref(sma);
-       if (sma->sem_perm.deleted) {
+       if (!ipc_valid_object(&sma->sem_perm)) {
                sem_unlock(sma, -1);
                rcu_read_unlock();
                kfree(new);
@@ -1735,7 +1735,7 @@ out:
 
 
 /**
- * get_queue_result - Retrieve the result code from sem_queue
+ * get_queue_result - retrieve the result code from sem_queue
  * @q: Pointer to queue structure
  *
  * Retrieve the return code from the pending queue. If IN_WAKEUP is found in
@@ -1765,7 +1765,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
        int error = -EINVAL;
        struct sem_array *sma;
        struct sembuf fast_sops[SEMOPM_FAST];
-       struct sembufsops = fast_sops, *sop;
+       struct sembuf *sops = fast_sops, *sop;
        struct sem_undo *un;
        int undos = 0, alter = 0, max, locknum;
        struct sem_queue queue;
@@ -1779,13 +1779,13 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
                return -EINVAL;
        if (nsops > ns->sc_semopm)
                return -E2BIG;
-       if(nsops > SEMOPM_FAST) {
-               sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
-               if(sops==NULL)
+       if (nsops > SEMOPM_FAST) {
+               sops = kmalloc(sizeof(*sops)*nsops, GFP_KERNEL);
+               if (sops == NULL)
                        return -ENOMEM;
        }
-       if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
-               error=-EFAULT;
+       if (copy_from_user(sops, tsops, nsops * sizeof(*tsops))) {
+               error =  -EFAULT;
                goto out_free;
        }
        if (timeout) {
@@ -1846,7 +1846,15 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
        error = -EIDRM;
        locknum = sem_lock(sma, sops, nsops);
-       if (sma->sem_perm.deleted)
+       /*
+        * We eventually might perform the following check in a lockless
+        * fashion, considering ipc_valid_object() locking constraints.
+        * If nsops == 1 and there is no contention for sem_perm.lock, then
+        * only a per-semaphore lock is held and it's OK to proceed with the
+        * check below. More details on the fine grained locking scheme
+        * entangled here and why it's RMID race safe on comments at sem_lock()
+        */
+       if (!ipc_valid_object(&sma->sem_perm))
                goto out_unlock_free;
        /*
         * semid identifiers are not unique - find_alloc_undo may have
@@ -1959,10 +1967,8 @@ sleep_again:
         * If queue.status != -EINTR we are woken up by another process.
         * Leave without unlink_queue(), but with sem_unlock().
         */
-
-       if (error != -EINTR) {
+       if (error != -EINTR)
                goto out_unlock_free;
-       }
 
        /*
         * If an interrupt occurred we have to clean up the queue
@@ -1984,7 +1990,7 @@ out_rcu_wakeup:
        rcu_read_unlock();
        wake_up_sem_queue_do(&tasks);
 out_free:
-       if(sops != fast_sops)
+       if (sops != fast_sops)
                kfree(sops);
        return error;
 }
@@ -2068,7 +2074,7 @@ void exit_sem(struct task_struct *tsk)
 
                sem_lock(sma, NULL, -1);
                /* exit_sem raced with IPC_RMID, nothing to do */
-               if (sma->sem_perm.deleted) {
+               if (!ipc_valid_object(&sma->sem_perm)) {
                        sem_unlock(sma, -1);
                        rcu_read_unlock();
                        continue;
@@ -2093,7 +2099,7 @@ void exit_sem(struct task_struct *tsk)
 
                /* perform adjustments registered in un */
                for (i = 0; i < sma->sem_nsems; i++) {
-                       struct sem * semaphore = &sma->sem_base[i];
+                       struct sem *semaphore = &sma->sem_base[i];
                        if (un->semadj[i]) {
                                semaphore->semval += un->semadj[i];
                                /*
@@ -2107,7 +2113,7 @@ void exit_sem(struct task_struct *tsk)
                                 * Linux caps the semaphore value, both at 0
                                 * and at SEMVMX.
                                 *
-                                *      Manfred <manfred@colorfullife.com>
+                                *      Manfred <manfred@colorfullife.com>
                                 */
                                if (semaphore->semval < 0)
                                        semaphore->semval = 0;
index 7a51443a51d6421bd2a02a66ec18db98f6796dd3..76459616a7fafe7581d713a245c63e861a4cf631 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -67,7 +67,7 @@ static const struct vm_operations_struct shm_vm_ops;
 static int newseg(struct ipc_namespace *, struct ipc_params *);
 static void shm_open(struct vm_area_struct *vma);
 static void shm_close(struct vm_area_struct *vma);
-static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
+static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
@@ -91,7 +91,7 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
        struct shmid_kernel *shp;
        shp = container_of(ipcp, struct shmid_kernel, shm_perm);
 
-       if (shp->shm_nattch){
+       if (shp->shm_nattch) {
                shp->shm_perm.mode |= SHM_DEST;
                /* Do not find it any more */
                shp->shm_perm.key = IPC_PRIVATE;
@@ -116,7 +116,7 @@ static int __init ipc_ns_init(void)
 
 pure_initcall(ipc_ns_init);
 
-void __init shm_init (void)
+void __init shm_init(void)
 {
        ipc_init_proc_interface("sysvipc/shm",
 #if BITS_PER_LONG <= 32
@@ -248,7 +248,7 @@ static bool shm_may_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
  */
 static void shm_close(struct vm_area_struct *vma)
 {
-       struct file * file = vma->vm_file;
+       struct file *file = vma->vm_file;
        struct shm_file_data *sfd = shm_file_data(file);
        struct shmid_kernel *shp;
        struct ipc_namespace *ns = sfd->ns;
@@ -379,7 +379,7 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
 }
 #endif
 
-static int shm_mmap(struct file * file, struct vm_area_struct * vma)
+static int shm_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct shm_file_data *sfd = shm_file_data(file);
        int ret;
@@ -477,7 +477,6 @@ static const struct vm_operations_struct shm_vm_ops = {
  *
  * Called with shm_ids.rwsem held as a writer.
  */
-
 static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 {
        key_t key = params->key;
@@ -486,7 +485,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        int error;
        struct shmid_kernel *shp;
        size_t numpages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       struct file * file;
+       struct file *file;
        char name[13];
        int id;
        vm_flags_t acctflag = 0;
@@ -512,7 +511,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
                return error;
        }
 
-       sprintf (name, "SYSV%08x", key);
+       sprintf(name, "SYSV%08x", key);
        if (shmflg & SHM_HUGETLB) {
                struct hstate *hs;
                size_t hugesize;
@@ -533,7 +532,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        } else {
                /*
                 * Do not allow no accounting for OVERCOMMIT_NEVER, even
-                * if it's asked for.
+                * if it's asked for.
                 */
                if  ((shmflg & SHM_NORESERVE) &&
                                sysctl_overcommit_memory != OVERCOMMIT_NEVER)
@@ -628,7 +627,7 @@ SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg)
 
 static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                return copy_to_user(buf, in, sizeof(*in));
        case IPC_OLD:
@@ -655,7 +654,7 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_
 static inline unsigned long
 copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
@@ -680,14 +679,14 @@ copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
 
 static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminfo64 *in, int version)
 {
-       switch(version) {
+       switch (version) {
        case IPC_64:
                return copy_to_user(buf, in, sizeof(*in));
        case IPC_OLD:
            {
                struct shminfo out;
 
-               if(in->shmmax > INT_MAX)
+               if (in->shmmax > INT_MAX)
                        out.shmmax = INT_MAX;
                else
                        out.shmmax = (int)in->shmmax;
@@ -846,14 +845,14 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
                shminfo.shmall = ns->shm_ctlall;
 
                shminfo.shmmin = SHMMIN;
-               if(copy_shminfo_to_user (buf, &shminfo, version))
+               if (copy_shminfo_to_user(buf, &shminfo, version))
                        return -EFAULT;
 
                down_read(&shm_ids(ns).rwsem);
                err = ipc_get_maxid(&shm_ids(ns));
                up_read(&shm_ids(ns).rwsem);
 
-               if(err<0)
+               if (err < 0)
                        err = 0;
                goto out;
        }
@@ -864,7 +863,7 @@ static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
                memset(&shm_info, 0, sizeof(shm_info));
                down_read(&shm_ids(ns).rwsem);
                shm_info.used_ids = shm_ids(ns).in_use;
-               shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
+               shm_get_stat(ns, &shm_info.shm_rss, &shm_info.shm_swp);
                shm_info.shm_tot = ns->shm_tot;
                shm_info.swap_attempts = 0;
                shm_info.swap_successes = 0;
@@ -975,6 +974,13 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
                        goto out_unlock1;
 
                ipc_lock_object(&shp->shm_perm);
+
+               /* check if shm_destroy() is tearing down shp */
+               if (!ipc_valid_object(&shp->shm_perm)) {
+                       err = -EIDRM;
+                       goto out_unlock0;
+               }
+
                if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
                        kuid_t euid = current_euid();
                        if (!uid_eq(euid, shp->shm_perm.uid) &&
@@ -989,13 +995,6 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
                }
 
                shm_file = shp->shm_file;
-
-               /* check if shm_destroy() is tearing down shp */
-               if (shm_file == NULL) {
-                       err = -EIDRM;
-                       goto out_unlock0;
-               }
-
                if (is_file_hugepages(shm_file))
                        goto out_unlock0;
 
@@ -1047,7 +1046,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
        struct shmid_kernel *shp;
        unsigned long addr;
        unsigned long size;
-       struct file * file;
+       struct file *file;
        int    err;
        unsigned long flags;
        unsigned long prot;
@@ -1116,7 +1115,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
        ipc_lock_object(&shp->shm_perm);
 
        /* check if shm_destroy() is tearing down shp */
-       if (shp->shm_file == NULL) {
+       if (!ipc_valid_object(&shp->shm_perm)) {
                ipc_unlock_object(&shp->shm_perm);
                err = -EIDRM;
                goto out_unlock;
index 3ae17a4ace5b9ba242fd1aa42543d64145e5cb7f..e1b4c6db8aa042d2a896426391b10af913ac7b4f 100644 (file)
@@ -110,15 +110,15 @@ static struct notifier_block ipc_memory_nb = {
 };
 
 /**
- *     ipc_init        -       initialise IPC subsystem
+ * ipc_init - initialise ipc subsystem
  *
- *     The various system5 IPC resources (semaphores, messages and shared
- *     memory) are initialised
- *     A callback routine is registered into the memory hotplug notifier
- *     chain: since msgmni scales to lowmem this callback routine will be
- *     called upon successful memory add / remove to recompute msmgni.
+ * The various sysv ipc resources (semaphores, messages and shared
+ * memory) are initialised.
+ *
+ * A callback routine is registered into the memory hotplug notifier
+ * chain: since msgmni scales to lowmem this callback routine will be
+ * called upon successful memory add / remove to recompute msmgni.
  */
 static int __init ipc_init(void)
 {
        sem_init();
@@ -131,39 +131,29 @@ static int __init ipc_init(void)
 __initcall(ipc_init);
 
 /**
- *     ipc_init_ids            -       initialise IPC identifiers
- *     @ids: Identifier set
+ * ipc_init_ids        - initialise ipc identifiers
+ * @ids: ipc identifier set
  *
- *     Set up the sequence range to use for the ipc identifier range (limited
- *     below IPCMNI) then initialise the ids idr.
+ * Set up the sequence range to use for the ipc identifier range (limited
+ * below IPCMNI) then initialise the ids idr.
  */
 void ipc_init_ids(struct ipc_ids *ids)
 {
-       init_rwsem(&ids->rwsem);
-
        ids->in_use = 0;
        ids->seq = 0;
        ids->next_id = -1;
-       {
-               int seq_limit = INT_MAX/SEQ_MULTIPLIER;
-               if (seq_limit > USHRT_MAX)
-                       ids->seq_max = USHRT_MAX;
-                else
-                       ids->seq_max = seq_limit;
-       }
-
+       init_rwsem(&ids->rwsem);
        idr_init(&ids->ipcs_idr);
 }
 
 #ifdef CONFIG_PROC_FS
 static const struct file_operations sysvipc_proc_fops;
 /**
- *     ipc_init_proc_interface -  Create a proc interface for sysipc types using a seq_file interface.
- *     @path: Path in procfs
- *     @header: Banner to be printed at the beginning of the file.
- *     @ids: ipc id table to iterate.
- *     @show: show routine.
+ * ipc_init_proc_interface -  create a proc interface for sysipc types using a seq_file interface.
+ * @path: Path in procfs
+ * @header: Banner to be printed at the beginning of the file.
+ * @ids: ipc id table to iterate.
+ * @show: show routine.
  */
 void __init ipc_init_proc_interface(const char *path, const char *header,
                int ids, int (*show)(struct seq_file *, void *))
@@ -184,23 +174,21 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
                               NULL,           /* parent dir */
                               &sysvipc_proc_fops,
                               iface);
-       if (!pde) {
+       if (!pde)
                kfree(iface);
-       }
 }
 #endif
 
 /**
- *     ipc_findkey     -       find a key in an ipc identifier set     
- *     @ids: Identifier set
- *     @key: The key to find
+ * ipc_findkey - find a key in an ipc identifier set
+ * @ids: ipc identifier set
+ * @key: key to find
  *     
- *     Requires ipc_ids.rwsem locked.
- *     Returns the LOCKED pointer to the ipc structure if found or NULL
- *     if not.
- *     If key is found ipc points to the owning ipc structure
+ * Returns the locked pointer to the ipc structure if found or NULL
+ * otherwise. If key is found ipc points to the owning ipc structure
+ *
+ * Called with ipc_ids.rwsem held.
  */
 static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
 {
        struct kern_ipc_perm *ipc;
@@ -227,12 +215,11 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
 }
 
 /**
- *     ipc_get_maxid   -       get the last assigned id
- *     @ids: IPC identifier set
+ * ipc_get_maxid - get the last assigned id
+ * @ids: ipc identifier set
  *
- *     Called with ipc_ids.rwsem held.
+ * Called with ipc_ids.rwsem held.
  */
-
 int ipc_get_maxid(struct ipc_ids *ids)
 {
        struct kern_ipc_perm *ipc;
@@ -258,19 +245,19 @@ int ipc_get_maxid(struct ipc_ids *ids)
 }
 
 /**
- *     ipc_addid       -       add an IPC identifier
- *     @ids: IPC identifier set
- *     @new: new IPC permission set
- *     @size: limit for the number of used ids
+ * ipc_addid - add an ipc identifier
+ * @ids: ipc identifier set
+ * @new: new ipc permission set
+ * @size: limit for the number of used ids
  *
- *     Add an entry 'new' to the IPC ids idr. The permissions object is
- *     initialised and the first free entry is set up and the id assigned
- *     is returned. The 'new' entry is returned in a locked state on success.
- *     On failure the entry is not locked and a negative err-code is returned.
+ * Add an entry 'new' to the ipc ids idr. The permissions object is
+ * initialised and the first free entry is set up and the id assigned
+ * is returned. The 'new' entry is returned in a locked state on success.
+ * On failure the entry is not locked and a negative err-code is returned.
  *
- *     Called with writer ipc_ids.rwsem held.
+ * Called with writer ipc_ids.rwsem held.
  */
-int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
+int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
 {
        kuid_t euid;
        kgid_t egid;
@@ -286,7 +273,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        idr_preload(GFP_KERNEL);
 
        spin_lock_init(&new->lock);
-       new->deleted = 0;
+       new->deleted = false;
        rcu_read_lock();
        spin_lock(&new->lock);
 
@@ -308,7 +295,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 
        if (next_id < 0) {
                new->seq = ids->seq++;
-               if (ids->seq > ids->seq_max)
+               if (ids->seq > IPCID_SEQ_MAX)
                        ids->seq = 0;
        } else {
                new->seq = ipcid_to_seqx(next_id);
@@ -320,14 +307,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 }
 
 /**
- *     ipcget_new      -       create a new ipc object
- *     @ns: namespace
- *     @ids: IPC identifer set
- *     @ops: the actual creation routine to call
- *     @params: its parameters
- *
- *     This routine is called by sys_msgget, sys_semget() and sys_shmget()
- *     when the key is IPC_PRIVATE.
+ * ipcget_new -        create a new ipc object
+ * @ns: ipc namespace
+ * @ids: ipc identifer set
+ * @ops: the actual creation routine to call
+ * @params: its parameters
+ *
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is IPC_PRIVATE.
  */
 static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
                struct ipc_ops *ops, struct ipc_params *params)
@@ -341,19 +328,19 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
 }
 
 /**
- *     ipc_check_perms -       check security and permissions for an IPC
- *     @ns: IPC namespace
- *     @ipcp: ipc permission set
- *     @ops: the actual security routine to call
- *     @params: its parameters
+ * ipc_check_perms - check security and permissions for an ipc object
+ * @ns: ipc namespace
+ * @ipcp: ipc permission set
+ * @ops: the actual security routine to call
+ * @params: its parameters
  *
- *     This routine is called by sys_msgget(), sys_semget() and sys_shmget()
- *      when the key is not IPC_PRIVATE and that key already exists in the
- *      ids IDR.
+ * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE and that key already exists in the
+ * ds IDR.
  *
- *     On success, the IPC id is returned.
+ * On success, the ipc id is returned.
  *
- *     It is called with ipc_ids.rwsem and ipcp->lock held.
+ * It is called with ipc_ids.rwsem and ipcp->lock held.
  */
 static int ipc_check_perms(struct ipc_namespace *ns,
                           struct kern_ipc_perm *ipcp,
@@ -374,18 +361,18 @@ static int ipc_check_perms(struct ipc_namespace *ns,
 }
 
 /**
- *     ipcget_public   -       get an ipc object or create a new one
- *     @ns: namespace
- *     @ids: IPC identifer set
- *     @ops: the actual creation routine to call
- *     @params: its parameters
- *
- *     This routine is called by sys_msgget, sys_semget() and sys_shmget()
- *     when the key is not IPC_PRIVATE.
- *     It adds a new entry if the key is not found and does some permission
- *      / security checkings if the key is found.
- *
- *     On success, the ipc id is returned.
+ * ipcget_public - get an ipc object or create a new one
+ * @ns: ipc namespace
+ * @ids: ipc identifer set
+ * @ops: the actual creation routine to call
+ * @params: its parameters
+ *
+ * This routine is called by sys_msgget, sys_semget() and sys_shmget()
+ * when the key is not IPC_PRIVATE.
+ * It adds a new entry if the key is not found and does some permission
+ * / security checkings if the key is found.
+ *
+ * On success, the ipc id is returned.
  */
 static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
                struct ipc_ops *ops, struct ipc_params *params)
@@ -431,39 +418,33 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
 
 
 /**
- *     ipc_rmid        -       remove an IPC identifier
- *     @ids: IPC identifier set
- *     @ipcp: ipc perm structure containing the identifier to remove
+ * ipc_rmid - remove an ipc identifier
+ * @ids: ipc identifier set
+ * @ipcp: ipc perm structure containing the identifier to remove
  *
- *     ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
- *     before this function is called, and remain locked on the exit.
+ * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
+ * before this function is called, and remain locked on the exit.
  */
 void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
 {
        int lid = ipcid_to_idx(ipcp->id);
 
        idr_remove(&ids->ipcs_idr, lid);
-
        ids->in_use--;
-
-       ipcp->deleted = 1;
-
-       return;
+       ipcp->deleted = true;
 }
 
 /**
- *     ipc_alloc       -       allocate ipc space
- *     @size: size desired
+ * ipc_alloc - allocate ipc space
+ * @size: size desired
  *
- *     Allocate memory from the appropriate pools and return a pointer to it.
- *     NULL is returned if the allocation fails
+ * Allocate memory from the appropriate pools and return a pointer to it.
+ * NULL is returned if the allocation fails
  */
 void *ipc_alloc(int size)
 {
        void *out;
-       if(size > PAGE_SIZE)
+       if (size > PAGE_SIZE)
                out = vmalloc(size);
        else
                out = kmalloc(size, GFP_KERNEL);
@@ -471,28 +452,27 @@ void *ipc_alloc(int size)
 }
 
 /**
- *     ipc_free        -       free ipc space
- *     @ptr: pointer returned by ipc_alloc
- *     @size: size of block
+ * ipc_free - free ipc space
+ * @ptr: pointer returned by ipc_alloc
+ * @size: size of block
  *
- *     Free a block created with ipc_alloc(). The caller must know the size
- *     used in the allocation call.
+ * Free a block created with ipc_alloc(). The caller must know the size
+ * used in the allocation call.
  */
-
-void ipc_free(void* ptr, int size)
+void ipc_free(void *ptr, int size)
 {
-       if(size > PAGE_SIZE)
+       if (size > PAGE_SIZE)
                vfree(ptr);
        else
                kfree(ptr);
 }
 
 /**
- *     ipc_rcu_alloc   -       allocate ipc and rcu space 
- *     @size: size desired
+ * ipc_rcu_alloc - allocate ipc and rcu space
+ * @size: size desired
  *
- *     Allocate memory for the rcu header structure +  the object.
- *     Returns the pointer to the object or NULL upon failure.
+ * Allocate memory for the rcu header structure +  the object.
+ * Returns the pointer to the object or NULL upon failure.
  */
 void *ipc_rcu_alloc(int size)
 {
@@ -534,17 +514,16 @@ void ipc_rcu_free(struct rcu_head *head)
 }
 
 /**
- *     ipcperms        -       check IPC permissions
- *     @ns: IPC namespace
- *     @ipcp: IPC permission set
- *     @flag: desired permission set.
+ * ipcperms - check ipc permissions
+ * @ns: ipc namespace
+ * @ipcp: ipc permission set
+ * @flag: desired permission set
  *
- *     Check user, group, other permissions for access
- *     to ipc resources. return 0 if allowed
+ * Check user, group, other permissions for access
+ * to ipc resources. return 0 if allowed
  *
- *     @flag will most probably be 0 or S_...UGO from <linux/stat.h>
+ * @flag will most probably be 0 or S_...UGO from <linux/stat.h>
  */
 int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
 {
        kuid_t euid = current_euid();
@@ -572,16 +551,14 @@ int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
  */
 
 /**
- *     kernel_to_ipc64_perm    -       convert kernel ipc permissions to user
- *     @in: kernel permissions
- *     @out: new style IPC permissions
+ * kernel_to_ipc64_perm        - convert kernel ipc permissions to user
+ * @in: kernel permissions
+ * @out: new style ipc permissions
  *
- *     Turn the kernel object @in into a set of permissions descriptions
- *     for returning to userspace (@out).
+ * Turn the kernel object @in into a set of permissions descriptions
+ * for returning to userspace (@out).
  */
-
-void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
+void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out)
 {
        out->key        = in->key;
        out->uid        = from_kuid_munged(current_user_ns(), in->uid);
@@ -593,15 +570,14 @@ void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
 }
 
 /**
- *     ipc64_perm_to_ipc_perm  -       convert new ipc permissions to old
- *     @in: new style IPC permissions
- *     @out: old style IPC permissions
+ * ipc64_perm_to_ipc_perm - convert new ipc permissions to old
+ * @in: new style ipc permissions
+ * @out: old style ipc permissions
  *
- *     Turn the new style permissions object @in into a compatibility
- *     object and store it into the @out pointer.
+ * Turn the new style permissions object @in into a compatibility
+ * object and store it into the @out pointer.
  */
-void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
+void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out)
 {
        out->key        = in->key;
        SET_UID(out->uid, in->uid);
@@ -635,8 +611,8 @@ struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id)
 }
 
 /**
- * ipc_lock - Lock an ipc structure without rwsem held
- * @ids: IPC identifier set
+ * ipc_lock - lock an ipc structure without rwsem held
+ * @ids: ipc identifier set
  * @id: ipc id to look for
  *
  * Look for an id in the ipc ids idr and lock the associated ipc object.
@@ -657,7 +633,7 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
        /* ipc_rmid() may have already freed the ID while ipc_lock
         * was spinning: here verify that the structure is still valid
         */
-       if (!out->deleted)
+       if (ipc_valid_object(out))
                return out;
 
        spin_unlock(&out->lock);
@@ -693,11 +669,11 @@ out:
 
 /**
  * ipcget - Common sys_*get() code
- * @ns : namsepace
- * @ids : IPC identifier set
- * @ops : operations to be called on ipc object creation, permission checks
- *        and further checks
- * @params : the parameters needed by the previous operations.
+ * @ns: namsepace
+ * @ids: ipc identifier set
+ * @ops: operations to be called on ipc object creation, permission checks
+ *       and further checks
+ * @params: the parameters needed by the previous operations.
  *
  * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
  */
@@ -711,7 +687,7 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
 }
 
 /**
- * ipc_update_perm - update the permissions of an IPC.
+ * ipc_update_perm - update the permissions of an ipc object
  * @in:  the permission given as input.
  * @out: the permission of the ipc to set.
  */
@@ -732,7 +708,7 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
 
 /**
  * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd
- * @ns:  the ipc namespace
+ * @ns:  ipc namespace
  * @ids:  the table of ids where to look for the ipc
  * @id:   the id of the ipc to retrieve
  * @cmd:  the cmd to check
@@ -779,15 +755,14 @@ err:
 
 
 /**
- *     ipc_parse_version       -       IPC call version
- *     @cmd: pointer to command
+ * ipc_parse_version - ipc call version
+ * @cmd: pointer to command
  *
- *     Return IPC_64 for new style IPC and IPC_OLD for old style IPC. 
- *     The @cmd value is turned from an encoding command and version into
- *     just the command code.
+ * Return IPC_64 for new style IPC and IPC_OLD for old style IPC.
+ * The @cmd value is turned from an encoding command and version into
+ * just the command code.
  */
-int ipc_parse_version (int *cmd)
+int ipc_parse_version(int *cmd)
 {
        if (*cmd & IPC_64) {
                *cmd ^= IPC_64;
@@ -824,7 +799,7 @@ static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
        if (total >= ids->in_use)
                return NULL;
 
-       for ( ; pos < IPCMNI; pos++) {
+       for (; pos < IPCMNI; pos++) {
                ipc = idr_find(&ids->ipcs_idr, pos);
                if (ipc != NULL) {
                        *new_pos = pos + 1;
@@ -927,8 +902,10 @@ static int sysvipc_proc_open(struct inode *inode, struct file *file)
                goto out;
 
        ret = seq_open(file, &sysvipc_proc_seqops);
-       if (ret)
-               goto out_kfree;
+       if (ret) {
+               kfree(iter);
+               goto out;
+       }
 
        seq = file->private_data;
        seq->private = iter;
@@ -937,9 +914,6 @@ static int sysvipc_proc_open(struct inode *inode, struct file *file)
        iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
 out:
        return ret;
-out_kfree:
-       kfree(iter);
-       goto out;
 }
 
 static int sysvipc_proc_release(struct inode *inode, struct file *file)
index 59d78aa949874aff138845ce13fb55c764205f9d..9c47d6f6c7b4b6c63b05b8a7c246ea3efcdeb0dc 100644 (file)
@@ -15,9 +15,9 @@
 
 #define SEQ_MULTIPLIER (IPCMNI)
 
-void sem_init (void);
-void msg_init (void);
-void shm_init (void);
+void sem_init(void);
+void msg_init(void);
+void shm_init(void);
 
 struct ipc_namespace;
 
@@ -100,6 +100,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 
 #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
 #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
+#define IPCID_SEQ_MAX min_t(int, INT_MAX/SEQ_MULTIPLIER, USHRT_MAX)
 
 /* must be called with ids->rwsem acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
@@ -116,8 +117,8 @@ int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);
 /* for rare, potentially huge allocations.
  * both function can sleep
  */
-voidipc_alloc(int size);
-void ipc_free(voidptr, int size);
+void *ipc_alloc(int size);
+void ipc_free(void *ptr, int size);
 
 /*
  * For allocation that need to be freed by RCU.
@@ -125,7 +126,7 @@ void ipc_free(void* ptr, int size);
  * getref increases the refcount, the putref call that reduces the recount
  * to 0 schedules the rcu destruction. Caller must guarantee locking.
  */
-voidipc_rcu_alloc(int size);
+void *ipc_rcu_alloc(int size);
 int ipc_rcu_getref(void *ptr);
 void ipc_rcu_putref(void *ptr, void (*func)(struct rcu_head *head));
 void ipc_rcu_free(struct rcu_head *head);
@@ -144,7 +145,7 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
   /* On IA-64, we always use the "64-bit version" of the IPC structures.  */ 
 # define ipc_parse_version(cmd)        IPC_64
 #else
-int ipc_parse_version (int *cmd);
+int ipc_parse_version(int *cmd);
 #endif
 
 extern void free_msg(struct msg_msg *msg);
@@ -185,6 +186,19 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm)
        rcu_read_unlock();
 }
 
+/*
+ * ipc_valid_object() - helper to sort out IPC_RMID races for codepaths
+ * where the respective ipc_ids.rwsem is not being held down.
+ * Checks whether the ipc object is still around or if it's gone already, as
+ * ipc_rmid() may have already freed the ID while the ipc lock was spinning.
+ * Needs to be called with kern_ipc_perm.lock held -- exception made for one
+ * checkpoint case at sys_semtimedop() as noted in code commentary.
+ */
+static inline bool ipc_valid_object(struct kern_ipc_perm *perm)
+{
+       return !perm->deleted;
+}
+
 struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
                        struct ipc_ops *ops, struct ipc_params *params);
index ac738781d35686601e793a6901f7d677086357c0..60bafbed06abd7a7b2defd0c031ca18b7287a37e 100644 (file)
@@ -1537,7 +1537,7 @@ void vmcoreinfo_append_str(const char *fmt, ...)
        size_t r;
 
        va_start(args, fmt);
-       r = vsnprintf(buf, sizeof(buf), fmt, args);
+       r = vscnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
 
        r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
index 802365ccd591826a60e08009a3927c9bed8c69bf..c54609faf233ba21a49835d32a9132eb56853f14 100644 (file)
@@ -200,17 +200,6 @@ void wait_rcu_gp(call_rcu_func_t crf)
 }
 EXPORT_SYMBOL_GPL(wait_rcu_gp);
 
-#ifdef CONFIG_PROVE_RCU
-/*
- * wrapper function to avoid #include problems.
- */
-int rcu_my_thread_group_empty(void)
-{
-       return thread_group_empty(current);
-}
-EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty);
-#endif /* #ifdef CONFIG_PROVE_RCU */
-
 #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
 static inline void debug_init_rcu_head(struct rcu_head *head)
 {
index 8a1e6e104892daff68dded8f7ff2af9d72f3dd1e..850967068aaf3ff0711587d1624ac353216c4e2e 100644 (file)
@@ -8,6 +8,8 @@
  *     Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/export.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
@@ -54,7 +56,7 @@ static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp
 
 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
-char *softirq_to_name[NR_SOFTIRQS] = {
+const char * const softirq_to_name[NR_SOFTIRQS] = {
        "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
        "TASKLET", "SCHED", "HRTIMER", "RCU"
 };
@@ -136,7 +138,6 @@ void _local_bh_enable(void)
        WARN_ON_ONCE(in_irq());
        __local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
 }
-
 EXPORT_SYMBOL(_local_bh_enable);
 
 void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
@@ -153,7 +154,7 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
        /*
         * Keep preemption disabled until we are done with
         * softirq processing:
-        */
+        */
        preempt_count_sub(cnt - 1);
 
        if (unlikely(!in_interrupt() && local_softirq_pending())) {
@@ -229,6 +230,7 @@ asmlinkage void __do_softirq(void)
        struct softirq_action *h;
        bool in_hardirq;
        __u32 pending;
+       int softirq_bit;
        int cpu;
 
        /*
@@ -253,30 +255,30 @@ restart:
 
        h = softirq_vec;
 
-       do {
-               if (pending & 1) {
-                       unsigned int vec_nr = h - softirq_vec;
-                       int prev_count = preempt_count();
-
-                       kstat_incr_softirqs_this_cpu(vec_nr);
-
-                       trace_softirq_entry(vec_nr);
-                       h->action(h);
-                       trace_softirq_exit(vec_nr);
-                       if (unlikely(prev_count != preempt_count())) {
-                               printk(KERN_ERR "huh, entered softirq %u %s %p"
-                                      "with preempt_count %08x,"
-                                      " exited with %08x?\n", vec_nr,
-                                      softirq_to_name[vec_nr], h->action,
-                                      prev_count, preempt_count());
-                               preempt_count_set(prev_count);
-                       }
+       while ((softirq_bit = ffs(pending))) {
+               unsigned int vec_nr;
+               int prev_count;
 
-                       rcu_bh_qs(cpu);
+               h += softirq_bit - 1;
+
+               vec_nr = h - softirq_vec;
+               prev_count = preempt_count();
+
+               kstat_incr_softirqs_this_cpu(vec_nr);
+
+               trace_softirq_entry(vec_nr);
+               h->action(h);
+               trace_softirq_exit(vec_nr);
+               if (unlikely(prev_count != preempt_count())) {
+                       pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",
+                              vec_nr, softirq_to_name[vec_nr], h->action,
+                              prev_count, preempt_count());
+                       preempt_count_set(prev_count);
                }
+               rcu_bh_qs(cpu);
                h++;
-               pending >>= 1;
-       } while (pending);
+               pending >>= softirq_bit;
+       }
 
        local_irq_disable();
 
@@ -433,8 +435,7 @@ void open_softirq(int nr, void (*action)(struct softirq_action *))
 /*
  * Tasklets
  */
-struct tasklet_head
-{
+struct tasklet_head {
        struct tasklet_struct *head;
        struct tasklet_struct **tail;
 };
@@ -453,7 +454,6 @@ void __tasklet_schedule(struct tasklet_struct *t)
        raise_softirq_irqoff(TASKLET_SOFTIRQ);
        local_irq_restore(flags);
 }
-
 EXPORT_SYMBOL(__tasklet_schedule);
 
 void __tasklet_hi_schedule(struct tasklet_struct *t)
@@ -467,7 +467,6 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
        raise_softirq_irqoff(HI_SOFTIRQ);
        local_irq_restore(flags);
 }
-
 EXPORT_SYMBOL(__tasklet_hi_schedule);
 
 void __tasklet_hi_schedule_first(struct tasklet_struct *t)
@@ -478,7 +477,6 @@ void __tasklet_hi_schedule_first(struct tasklet_struct *t)
        __this_cpu_write(tasklet_hi_vec.head, t);
        __raise_softirq_irqoff(HI_SOFTIRQ);
 }
-
 EXPORT_SYMBOL(__tasklet_hi_schedule_first);
 
 static void tasklet_action(struct softirq_action *a)
@@ -498,7 +496,8 @@ static void tasklet_action(struct softirq_action *a)
 
                if (tasklet_trylock(t)) {
                        if (!atomic_read(&t->count)) {
-                               if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+                               if (!test_and_clear_bit(TASKLET_STATE_SCHED,
+                                                       &t->state))
                                        BUG();
                                t->func(t->data);
                                tasklet_unlock(t);
@@ -533,7 +532,8 @@ static void tasklet_hi_action(struct softirq_action *a)
 
                if (tasklet_trylock(t)) {
                        if (!atomic_read(&t->count)) {
-                               if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+                               if (!test_and_clear_bit(TASKLET_STATE_SCHED,
+                                                       &t->state))
                                        BUG();
                                t->func(t->data);
                                tasklet_unlock(t);
@@ -551,7 +551,6 @@ static void tasklet_hi_action(struct softirq_action *a)
        }
 }
 
-
 void tasklet_init(struct tasklet_struct *t,
                  void (*func)(unsigned long), unsigned long data)
 {
@@ -561,13 +560,12 @@ void tasklet_init(struct tasklet_struct *t,
        t->func = func;
        t->data = data;
 }
-
 EXPORT_SYMBOL(tasklet_init);
 
 void tasklet_kill(struct tasklet_struct *t)
 {
        if (in_interrupt())
-               printk("Attempt to kill tasklet from interrupt\n");
+               pr_notice("Attempt to kill tasklet from interrupt\n");
 
        while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
                do {
@@ -577,7 +575,6 @@ void tasklet_kill(struct tasklet_struct *t)
        tasklet_unlock_wait(t);
        clear_bit(TASKLET_STATE_SCHED, &t->state);
 }
-
 EXPORT_SYMBOL(tasklet_kill);
 
 /*
@@ -727,9 +724,8 @@ static void takeover_tasklets(unsigned int cpu)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int cpu_callback(struct notifier_block *nfb,
-                                 unsigned long action,
-                                 void *hcpu)
+static int cpu_callback(struct notifier_block *nfb, unsigned long action,
+                       void *hcpu)
 {
        switch (action) {
 #ifdef CONFIG_HOTPLUG_CPU
index 20c755e018cad3fdc59cb767eac7f604120793be..815c878f409bd94e08777d1b9f83b1553f4a2e24 100644 (file)
@@ -455,6 +455,9 @@ int __trace_puts(unsigned long ip, const char *str, int size)
        unsigned long irq_flags;
        int alloc;
 
+       if (unlikely(tracing_selftest_running || tracing_disabled))
+               return 0;
+
        alloc = sizeof(*entry) + size + 2; /* possible \n added */
 
        local_save_flags(irq_flags);
@@ -495,6 +498,9 @@ int __trace_bputs(unsigned long ip, const char *str)
        unsigned long irq_flags;
        int size = sizeof(struct bputs_entry);
 
+       if (unlikely(tracing_selftest_running || tracing_disabled))
+               return 0;
+
        local_save_flags(irq_flags);
        buffer = global_trace.trace_buffer.buffer;
        event = trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size,
@@ -3519,60 +3525,103 @@ static const char readme_msg[] =
        "  instances\t\t- Make sub-buffers with: mkdir instances/foo\n"
        "\t\t\t  Remove sub-buffer with rmdir\n"
        "  trace_options\t\t- Set format or modify how tracing happens\n"
-       "\t\t\t  Disable an option by adding a suffix 'no' to the option name\n"
+       "\t\t\t  Disable an option by adding a suffix 'no' to the\n"
+       "\t\t\t  option name\n"
 #ifdef CONFIG_DYNAMIC_FTRACE
        "\n  available_filter_functions - list of functions that can be filtered on\n"
-       "  set_ftrace_filter\t- echo function name in here to only trace these functions\n"
-       "            accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
-       "            modules: Can select a group via module\n"
-       "             Format: :mod:<module-name>\n"
-       "             example: echo :mod:ext3 > set_ftrace_filter\n"
-       "            triggers: a command to perform when function is hit\n"
-       "              Format: <function>:<trigger>[:count]\n"
-       "             trigger: traceon, traceoff\n"
-       "                      enable_event:<system>:<event>\n"
-       "                      disable_event:<system>:<event>\n"
+       "  set_ftrace_filter\t- echo function name in here to only trace these\n"
+       "\t\t\t  functions\n"
+       "\t     accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
+       "\t     modules: Can select a group via module\n"
+       "\t      Format: :mod:<module-name>\n"
+       "\t     example: echo :mod:ext3 > set_ftrace_filter\n"
+       "\t    triggers: a command to perform when function is hit\n"
+       "\t      Format: <function>:<trigger>[:count]\n"
+       "\t     trigger: traceon, traceoff\n"
+       "\t\t      enable_event:<system>:<event>\n"
+       "\t\t      disable_event:<system>:<event>\n"
 #ifdef CONFIG_STACKTRACE
-       "                      stacktrace\n"
+       "\t\t      stacktrace\n"
 #endif
 #ifdef CONFIG_TRACER_SNAPSHOT
-       "                      snapshot\n"
+       "\t\t      snapshot\n"
 #endif
-       "             example: echo do_fault:traceoff > set_ftrace_filter\n"
-       "                      echo do_trap:traceoff:3 > set_ftrace_filter\n"
-       "             The first one will disable tracing every time do_fault is hit\n"
-       "             The second will disable tracing at most 3 times when do_trap is hit\n"
-       "               The first time do trap is hit and it disables tracing, the counter\n"
-       "               will decrement to 2. If tracing is already disabled, the counter\n"
-       "               will not decrement. It only decrements when the trigger did work\n"
-       "             To remove trigger without count:\n"
-       "               echo '!<function>:<trigger> > set_ftrace_filter\n"
-       "             To remove trigger with a count:\n"
-       "               echo '!<function>:<trigger>:0 > set_ftrace_filter\n"
+       "\t     example: echo do_fault:traceoff > set_ftrace_filter\n"
+       "\t              echo do_trap:traceoff:3 > set_ftrace_filter\n"
+       "\t     The first one will disable tracing every time do_fault is hit\n"
+       "\t     The second will disable tracing at most 3 times when do_trap is hit\n"
+       "\t       The first time do trap is hit and it disables tracing, the\n"
+       "\t       counter will decrement to 2. If tracing is already disabled,\n"
+       "\t       the counter will not decrement. It only decrements when the\n"
+       "\t       trigger did work\n"
+       "\t     To remove trigger without count:\n"
+       "\t       echo '!<function>:<trigger> > set_ftrace_filter\n"
+       "\t     To remove trigger with a count:\n"
+       "\t       echo '!<function>:<trigger>:0 > set_ftrace_filter\n"
        "  set_ftrace_notrace\t- echo function name in here to never trace.\n"
-       "            accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
-       "            modules: Can select a group via module command :mod:\n"
-       "            Does not accept triggers\n"
+       "\t    accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
+       "\t    modules: Can select a group via module command :mod:\n"
+       "\t    Does not accept triggers\n"
 #endif /* CONFIG_DYNAMIC_FTRACE */
 #ifdef CONFIG_FUNCTION_TRACER
-       "  set_ftrace_pid\t- Write pid(s) to only function trace those pids (function)\n"
+       "  set_ftrace_pid\t- Write pid(s) to only function trace those pids\n"
+       "\t\t    (function)\n"
 #endif
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        "  set_graph_function\t- Trace the nested calls of a function (function_graph)\n"
        "  max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n"
 #endif
 #ifdef CONFIG_TRACER_SNAPSHOT
-       "\n  snapshot\t\t- Like 'trace' but shows the content of the static snapshot buffer\n"
-       "\t\t\t  Read the contents for more information\n"
+       "\n  snapshot\t\t- Like 'trace' but shows the content of the static\n"
+       "\t\t\t  snapshot buffer. Read the contents for more\n"
+       "\t\t\t  information\n"
 #endif
 #ifdef CONFIG_STACK_TRACER
        "  stack_trace\t\t- Shows the max stack trace when active\n"
        "  stack_max_size\t- Shows current max stack size that was traced\n"
-       "\t\t\t  Write into this file to reset the max size (trigger a new trace)\n"
+       "\t\t\t  Write into this file to reset the max size (trigger a\n"
+       "\t\t\t  new trace)\n"
 #ifdef CONFIG_DYNAMIC_FTRACE
-       "  stack_trace_filter\t- Like set_ftrace_filter but limits what stack_trace traces\n"
+       "  stack_trace_filter\t- Like set_ftrace_filter but limits what stack_trace\n"
+       "\t\t\t  traces\n"
 #endif
 #endif /* CONFIG_STACK_TRACER */
+       "  events/\t\t- Directory containing all trace event subsystems:\n"
+       "      enable\t\t- Write 0/1 to enable/disable tracing of all events\n"
+       "  events/<system>/\t- Directory containing all trace events for <system>:\n"
+       "      enable\t\t- Write 0/1 to enable/disable tracing of all <system>\n"
+       "\t\t\t  events\n"
+       "      filter\t\t- If set, only events passing filter are traced\n"
+       "  events/<system>/<event>/\t- Directory containing control files for\n"
+       "\t\t\t  <event>:\n"
+       "      enable\t\t- Write 0/1 to enable/disable tracing of <event>\n"
+       "      filter\t\t- If set, only events passing filter are traced\n"
+       "      trigger\t\t- If set, a command to perform when event is hit\n"
+       "\t    Format: <trigger>[:count][if <filter>]\n"
+       "\t   trigger: traceon, traceoff\n"
+       "\t            enable_event:<system>:<event>\n"
+       "\t            disable_event:<system>:<event>\n"
+#ifdef CONFIG_STACKTRACE
+       "\t\t    stacktrace\n"
+#endif
+#ifdef CONFIG_TRACER_SNAPSHOT
+       "\t\t    snapshot\n"
+#endif
+       "\t   example: echo traceoff > events/block/block_unplug/trigger\n"
+       "\t            echo traceoff:3 > events/block/block_unplug/trigger\n"
+       "\t            echo 'enable_event:kmem:kmalloc:3 if nr_rq > 1' > \\\n"
+       "\t                  events/block/block_unplug/trigger\n"
+       "\t   The first disables tracing every time block_unplug is hit.\n"
+       "\t   The second disables tracing the first 3 times block_unplug is hit.\n"
+       "\t   The third enables the kmalloc event the first 3 times block_unplug\n"
+       "\t     is hit and has value of greater than 1 for the 'nr_rq' event field.\n"
+       "\t   Like function triggers, the counter is only decremented if it\n"
+       "\t    enabled or disabled tracing.\n"
+       "\t   To remove a trigger without a count:\n"
+       "\t     echo '!<trigger> > <system>/<event>/trigger\n"
+       "\t   To remove a trigger with a count:\n"
+       "\t     echo '!<trigger>:0 > <system>/<event>/trigger\n"
+       "\t   Filters can be ignored when removing a trigger.\n"
 ;
 
 static ssize_t
index e0e2eebf7ab38502fc2c2f72f5076271cdb30edb..dbf94a7d25a8a1c7be60d62f29680e69e1261f1b 100644 (file)
@@ -1556,17 +1556,6 @@ config PROVIDE_OHCI1394_DMA_INIT
 
          See Documentation/debugging-via-ohci1394.txt for more information.
 
-config FIREWIRE_OHCI_REMOTE_DMA
-       bool "Remote debugging over FireWire with firewire-ohci"
-       depends on FIREWIRE_OHCI
-       help
-         This option lets you use the FireWire bus for remote debugging
-         with help of the firewire-ohci driver. It enables unfiltered
-         remote DMA in firewire-ohci.
-         See Documentation/debugging-via-ohci1394.txt for more information.
-
-         If unsure, say N.
-
 config BUILD_DOCSRC
        bool "Build targets in Documentation/ tree"
        depends on HEADERS_CHECK
index c38083871f11dbaf3f7252674b937fe5e161380a..2defd1308b045c46389a6232391999914573deb6 100644 (file)
@@ -463,7 +463,7 @@ static int active_pfn_set_overlap(unsigned long pfn, int overlap)
        int i;
 
        if (overlap > ACTIVE_PFN_MAX_OVERLAP || overlap < 0)
-               return 0;
+               return overlap;
 
        for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
                if (overlap & 1 << i)
@@ -486,7 +486,7 @@ static void active_pfn_inc_overlap(unsigned long pfn)
         * debug_dma_assert_idle() as the pfn may be marked idle
         * prematurely.
         */
-       WARN_ONCE(overlap == 0,
+       WARN_ONCE(overlap > ACTIVE_PFN_MAX_OVERLAP,
                  "DMA-API: exceeded %d overlapping mappings of pfn %lx\n",
                  ACTIVE_PFN_MAX_OVERLAP, pfn);
 }
@@ -517,7 +517,11 @@ static void active_pfn_remove(struct dma_debug_entry *entry)
        unsigned long flags;
 
        spin_lock_irqsave(&radix_lock, flags);
-       if (active_pfn_dec_overlap(entry->pfn) == 0)
+       /* since we are counting overlaps the final put of the
+        * entry->pfn will occur when the overlap count is 0.
+        * active_pfn_dec_overlap() returns -1 in that case
+        */
+       if (active_pfn_dec_overlap(entry->pfn) < 0)
                radix_tree_delete(&dma_active_pfn, entry->pfn);
        spin_unlock_irqrestore(&radix_lock, flags);
 }
index 600ac57e27777f429b77279d93cb9a483f1fbd15..7288e38e17575952664af1df3a69ba488812c8e3 100644 (file)
@@ -268,14 +268,12 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
  */
 static inline int parse_lineno(const char *str, unsigned int *val)
 {
-       char *end = NULL;
        BUG_ON(str == NULL);
        if (*str == '\0') {
                *val = 0;
                return 0;
        }
-       *val = simple_strtoul(str, &end, 10);
-       if (end == NULL || end == str || *end != '\0') {
+       if (kstrtouint(str, 10, val) < 0) {
                pr_err("bad line-number: %s\n", str);
                return -EINVAL;
        }
@@ -348,14 +346,14 @@ static int ddebug_parse_query(char *words[], int nwords,
                        }
                        if (last)
                                *last++ = '\0';
-                       if (parse_lineno(first, &query->first_lineno) < 0) {
-                               pr_err("line-number is <0\n");
+                       if (parse_lineno(first, &query->first_lineno) < 0)
                                return -EINVAL;
-                       }
                        if (last) {
                                /* range <first>-<last> */
-                               if (parse_lineno(last, &query->last_lineno)
-                                   < query->first_lineno) {
+                               if (parse_lineno(last, &query->last_lineno) < 0)
+                                       return -EINVAL;
+
+                               if (query->last_lineno < query->first_lineno) {
                                        pr_err("last-line:%d < 1st-line:%d\n",
                                                query->last_lineno,
                                                query->first_lineno);
index dda31168844f42c9c6fe2f9c9d25526e30884529..bdb9a456bcbb50471310b9f636df72c6bc377ddd 100644 (file)
@@ -316,7 +316,7 @@ EXPORT_SYMBOL(gen_pool_alloc);
  * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
  * @pool: pool to allocate from
  * @size: number of bytes to allocate from the pool
- * @dma: dma-view physical address
+ * @dma: dma-view physical address return value.  Use NULL if unneeded.
  *
  * Allocate the requested number of bytes from the specified pool.
  * Uses the pool allocation function (with first-fit algorithm by default).
@@ -334,7 +334,8 @@ void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
        if (!vaddr)
                return NULL;
 
-       *dma = gen_pool_virt_to_phys(pool, vaddr);
+       if (dma)
+               *dma = gen_pool_virt_to_phys(pool, vaddr);
 
        return (void *)vaddr;
 }
index 615f3de4b5ce2e3248a101f1adc174a03d65b6fb..b604b831f4d182c4cbc43ddcb23e7f98d3d8d177 100644 (file)
@@ -172,7 +172,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
        /*
         * Get the overflow emergency buffer
         */
-       v_overflow_buffer = memblock_virt_alloc_nopanic(
+       v_overflow_buffer = memblock_virt_alloc_low_nopanic(
                                                PAGE_ALIGN(io_tlb_overflow),
                                                PAGE_SIZE);
        if (!v_overflow_buffer)
@@ -220,7 +220,7 @@ swiotlb_init(int verbose)
        bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
        /* Get IO TLB memory from the low pages */
-       vstart = memblock_virt_alloc_nopanic(PAGE_ALIGN(bytes), PAGE_SIZE);
+       vstart = memblock_virt_alloc_low_nopanic(PAGE_ALIGN(bytes), PAGE_SIZE);
        if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
                return;
 
@@ -510,7 +510,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
 
 not_found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
-       dev_warn(hwdev, "swiotlb buffer is full\n");
+       if (printk_ratelimit())
+               dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size);
        return SWIOTLB_MAP_ERROR;
 found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
index 7a7f3e0db7384515b6e266029ef930e5c775ec0d..d56d3c145b9f26d3210ec8ad17430be6c46af2a9 100644 (file)
@@ -1428,30 +1428,28 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                if (!count)
                        goto out; /* skip atime */
                size = i_size_read(inode);
-               if (pos < size) {
-                       retval = filemap_write_and_wait_range(mapping, pos,
+               retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + iov_length(iov, nr_segs) - 1);
-                       if (!retval) {
-                               retval = mapping->a_ops->direct_IO(READ, iocb,
-                                                       iov, pos, nr_segs);
-                       }
-                       if (retval > 0) {
-                               *ppos = pos + retval;
-                               count -= retval;
-                       }
+               if (!retval) {
+                       retval = mapping->a_ops->direct_IO(READ, iocb,
+                                                          iov, pos, nr_segs);
+               }
+               if (retval > 0) {
+                       *ppos = pos + retval;
+                       count -= retval;
+               }
 
-                       /*
-                        * Btrfs can have a short DIO read if we encounter
-                        * compressed extents, so if there was an error, or if
-                        * we've already read everything we wanted to, or if
-                        * there was a short read because we hit EOF, go ahead
-                        * and return.  Otherwise fallthrough to buffered io for
-                        * the rest of the read.
-                        */
-                       if (retval < 0 || !count || *ppos >= size) {
-                               file_accessed(filp);
-                               goto out;
-                       }
+               /*
+                * Btrfs can have a short DIO read if we encounter
+                * compressed extents, so if there was an error, or if
+                * we've already read everything we wanted to, or if
+                * there was a short read because we hit EOF, go ahead
+                * and return.  Otherwise fallthrough to buffered io for
+                * the rest of the read.
+                */
+               if (retval < 0 || !count || *ppos >= size) {
+                       file_accessed(filp);
+                       goto out;
                }
        }
 
index 65c98eb5483c24946321bbca51dd0ebc02da0a00..82166bf974e14262ecfb064ea7c173d006d3ab98 100644 (file)
@@ -1508,19 +1508,15 @@ int move_huge_pmd(struct vm_area_struct *vma, struct vm_area_struct *new_vma,
                        spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
                pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
                VM_BUG_ON(!pmd_none(*new_pmd));
-               set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
-               if (new_ptl != old_ptl) {
-                       pgtable_t pgtable;
 
-                       /*
-                        * Move preallocated PTE page table if new_pmd is on
-                        * different PMD page table.
-                        */
+               if (pmd_move_must_withdraw(new_ptl, old_ptl)) {
+                       pgtable_t pgtable;
                        pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
                        pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
-
-                       spin_unlock(new_ptl);
                }
+               set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
+               if (new_ptl != old_ptl)
+                       spin_unlock(new_ptl);
                spin_unlock(old_ptl);
        }
 out:
index 612c14f5e0f570159fcf775991e88615fca26606..29e1e761f9ebe3fee42eea1b0e77589122a23d24 100644 (file)
@@ -83,7 +83,6 @@ extern unsigned long highest_memmap_pfn;
  */
 extern int isolate_lru_page(struct page *page);
 extern void putback_lru_page(struct page *page);
-extern unsigned long zone_reclaimable_pages(struct zone *zone);
 extern bool zone_reclaimable(struct zone *zone);
 
 /*
index 9c0aeef194404a93a0e64f94a25c337ff301749e..39a31e7f004505991e37219bdb1e17f571efb933 100644 (file)
@@ -984,9 +984,6 @@ static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
        if (!align)
                align = SMP_CACHE_BYTES;
 
-       /* align @size to avoid excessive fragmentation on reserved array */
-       size = round_up(size, align);
-
        found = memblock_find_in_range_node(size, align, 0, max_addr, nid);
        if (found && !memblock_reserve(found, size))
                return found;
@@ -1080,8 +1077,8 @@ static void * __init memblock_virt_alloc_internal(
        if (!align)
                align = SMP_CACHE_BYTES;
 
-       /* align @size to avoid excessive fragmentation on reserved array */
-       size = round_up(size, align);
+       if (max_addr > memblock.current_limit)
+               max_addr = memblock.current_limit;
 
 again:
        alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
index 463b7fbf0d1d0ffd3e422948f62b9605dd8f3f65..873de7e542bc91993e6922a6b5ada5d4759a6da6 100644 (file)
@@ -613,7 +613,7 @@ static inline int queue_pages_pgd_range(struct vm_area_struct *vma,
        return 0;
 }
 
-#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE
+#ifdef CONFIG_NUMA_BALANCING
 /*
  * This is used to mark a range of virtual addresses to be inaccessible.
  * These are later cleared by a NUMA hinting fault. Depending on these
@@ -627,7 +627,6 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long addr, unsigned long end)
 {
        int nr_updated;
-       BUILD_BUG_ON(_PAGE_NUMA != _PAGE_PROTNONE);
 
        nr_updated = change_protection(vma, addr, end, vma->vm_page_prot, 0, 1);
        if (nr_updated)
@@ -641,7 +640,7 @@ static unsigned long change_prot_numa(struct vm_area_struct *vma,
 {
        return 0;
 }
-#endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
+#endif /* CONFIG_NUMA_BALANCING */
 
 /*
  * Walk through page tables and collect pages to be migrated.
@@ -2655,7 +2654,7 @@ void mpol_free_shared_policy(struct shared_policy *p)
 }
 
 #ifdef CONFIG_NUMA_BALANCING
-static bool __initdata numabalancing_override;
+static int __initdata numabalancing_override;
 
 static void __init check_numabalancing_enable(void)
 {
@@ -2664,9 +2663,15 @@ static void __init check_numabalancing_enable(void)
        if (IS_ENABLED(CONFIG_NUMA_BALANCING_DEFAULT_ENABLED))
                numabalancing_default = true;
 
+       /* Parsed by setup_numabalancing. override == 1 enables, -1 disables */
+       if (numabalancing_override)
+               set_numabalancing_state(numabalancing_override == 1);
+
        if (nr_node_ids > 1 && !numabalancing_override) {
-               printk(KERN_INFO "Enabling automatic NUMA balancing. "
-                       "Configure with numa_balancing= or the kernel.numa_balancing sysctl");
+               pr_info("%s automatic NUMA balancing. "
+                       "Configure with numa_balancing= or the "
+                       "kernel.numa_balancing sysctl",
+                       numabalancing_default ? "Enabling" : "Disabling");
                set_numabalancing_state(numabalancing_default);
        }
 }
@@ -2676,18 +2681,17 @@ static int __init setup_numabalancing(char *str)
        int ret = 0;
        if (!str)
                goto out;
-       numabalancing_override = true;
 
        if (!strcmp(str, "enable")) {
-               set_numabalancing_state(true);
+               numabalancing_override = 1;
                ret = 1;
        } else if (!strcmp(str, "disable")) {
-               set_numabalancing_state(false);
+               numabalancing_override = -1;
                ret = 1;
        }
 out:
        if (!ret)
-               printk(KERN_WARNING "Unable to parse numa_balancing=\n");
+               pr_warn("Unable to parse numa_balancing=\n");
 
        return ret;
 }
index 734704f6f29b33dc8256463fcb9de1c23621d057..482a33d89134fd83e15d5f6863dae57f5cb05aac 100644 (file)
@@ -1548,8 +1548,6 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
                                          __GFP_NOMEMALLOC | __GFP_NORETRY |
                                          __GFP_NOWARN) &
                                         ~GFP_IOFS, 0);
-       if (newpage)
-               page_cpupid_xchg_last(newpage, page_cpupid_last(page));
 
        return newpage;
 }
index 857a6434e3a58a85467df765ebeab08b8be6f88a..4074caf9936bf399a14fa488b40ac0b5cdb16bdd 100644 (file)
@@ -202,4 +202,4 @@ static int __init mm_sysfs_init(void)
 
        return 0;
 }
-pure_initcall(mm_sysfs_init);
+postcore_initcall(mm_sysfs_init);
index 63807583d8e89f1c96f8b05bcf5fe422ed200c26..2d30e2cfe8047606064f117fbaca4675540e00dd 100644 (file)
@@ -191,6 +191,26 @@ static unsigned long writeout_period_time = 0;
  * global dirtyable memory first.
  */
 
+/**
+ * zone_dirtyable_memory - number of dirtyable pages in a zone
+ * @zone: the zone
+ *
+ * Returns the zone's number of pages potentially available for dirty
+ * page cache.  This is the base value for the per-zone dirty limits.
+ */
+static unsigned long zone_dirtyable_memory(struct zone *zone)
+{
+       unsigned long nr_pages;
+
+       nr_pages = zone_page_state(zone, NR_FREE_PAGES);
+       nr_pages -= min(nr_pages, zone->dirty_balance_reserve);
+
+       nr_pages += zone_page_state(zone, NR_INACTIVE_FILE);
+       nr_pages += zone_page_state(zone, NR_ACTIVE_FILE);
+
+       return nr_pages;
+}
+
 static unsigned long highmem_dirtyable_memory(unsigned long total)
 {
 #ifdef CONFIG_HIGHMEM
@@ -198,11 +218,9 @@ static unsigned long highmem_dirtyable_memory(unsigned long total)
        unsigned long x = 0;
 
        for_each_node_state(node, N_HIGH_MEMORY) {
-               struct zone *z =
-                       &NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
+               struct zone *z = &NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
 
-               x += zone_page_state(z, NR_FREE_PAGES) +
-                    zone_reclaimable_pages(z) - z->dirty_balance_reserve;
+               x += zone_dirtyable_memory(z);
        }
        /*
         * Unreclaimable memory (kernel memory or anonymous memory
@@ -238,9 +256,12 @@ static unsigned long global_dirtyable_memory(void)
 {
        unsigned long x;
 
-       x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages();
+       x = global_page_state(NR_FREE_PAGES);
        x -= min(x, dirty_balance_reserve);
 
+       x += global_page_state(NR_INACTIVE_FILE);
+       x += global_page_state(NR_ACTIVE_FILE);
+
        if (!vm_highmem_is_dirtyable)
                x -= highmem_dirtyable_memory(x);
 
@@ -288,32 +309,6 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty)
        trace_global_dirty_state(background, dirty);
 }
 
-/**
- * zone_dirtyable_memory - number of dirtyable pages in a zone
- * @zone: the zone
- *
- * Returns the zone's number of pages potentially available for dirty
- * page cache.  This is the base value for the per-zone dirty limits.
- */
-static unsigned long zone_dirtyable_memory(struct zone *zone)
-{
-       /*
-        * The effective global number of dirtyable pages may exclude
-        * highmem as a big-picture measure to keep the ratio between
-        * dirty memory and lowmem reasonable.
-        *
-        * But this function is purely about the individual zone and a
-        * highmem zone can hold its share of dirty pages, so we don't
-        * care about vm_highmem_is_dirtyable here.
-        */
-       unsigned long nr_pages = zone_page_state(zone, NR_FREE_PAGES) +
-               zone_reclaimable_pages(zone);
-
-       /* don't allow this to underflow */
-       nr_pages -= min(nr_pages, zone->dirty_balance_reserve);
-       return nr_pages;
-}
-
 /**
  * zone_dirty_limit - maximum number of dirty pages allowed in a zone
  * @zone: the zone
index 7cdbb44aa90bd99bef05f43ee27cc13b2121ed7a..0de2360d65f3f4f4cce4e0ae94f02d78a51a2429 100644 (file)
@@ -211,8 +211,6 @@ out:
 int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
                pgoff_t offset, unsigned long nr_to_read)
 {
-       int ret = 0;
-
        if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages))
                return -EINVAL;
 
@@ -226,15 +224,13 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
                        this_chunk = nr_to_read;
                err = __do_page_cache_readahead(mapping, filp,
                                                offset, this_chunk, 0);
-               if (err < 0) {
-                       ret = err;
-                       break;
-               }
-               ret += err;
+               if (err < 0)
+                       return err;
+
                offset += this_chunk;
                nr_to_read -= this_chunk;
        }
-       return ret;
+       return 0;
 }
 
 /*
@@ -576,8 +572,7 @@ do_readahead(struct address_space *mapping, struct file *filp,
        if (!mapping || !mapping->a_ops)
                return -EINVAL;
 
-       force_page_cache_readahead(mapping, filp, index, nr);
-       return 0;
+       return force_page_cache_readahead(mapping, filp, index, nr);
 }
 
 SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)
index 8156f95ec0cfc638d93e8f6175e107384c83d7dd..1f18c9d0d93ea270ab01054b2febbdd6a7eb6f56 100644 (file)
@@ -45,7 +45,7 @@ static struct vfsmount *shm_mnt;
 #include <linux/xattr.h>
 #include <linux/exportfs.h>
 #include <linux/posix_acl.h>
-#include <linux/generic_acl.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/mman.h>
 #include <linux/string.h>
 #include <linux/slab.h>
@@ -620,10 +620,8 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        setattr_copy(inode, attr);
-#ifdef CONFIG_TMPFS_POSIX_ACL
        if (attr->ia_valid & ATTR_MODE)
-               error = generic_acl_chmod(inode);
-#endif
+               error = posix_acl_chmod(inode, inode->i_mode);
        return error;
 }
 
@@ -1937,22 +1935,14 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 
        inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
        if (inode) {
-#ifdef CONFIG_TMPFS_POSIX_ACL
-               error = generic_acl_init(inode, dir);
-               if (error) {
-                       iput(inode);
-                       return error;
-               }
-#endif
+               error = simple_acl_create(dir, inode);
+               if (error)
+                       goto out_iput;
                error = security_inode_init_security(inode, dir,
                                                     &dentry->d_name,
                                                     shmem_initxattrs, NULL);
-               if (error) {
-                       if (error != -EOPNOTSUPP) {
-                               iput(inode);
-                               return error;
-                       }
-               }
+               if (error && error != -EOPNOTSUPP)
+                       goto out_iput;
 
                error = 0;
                dir->i_size += BOGO_DIRENT_SIZE;
@@ -1961,6 +1951,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
                dget(dentry); /* Extra count - pin the dentry in core */
        }
        return error;
+out_iput:
+       iput(inode);
+       return error;
 }
 
 static int
@@ -1974,24 +1967,17 @@ shmem_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
                error = security_inode_init_security(inode, dir,
                                                     NULL,
                                                     shmem_initxattrs, NULL);
-               if (error) {
-                       if (error != -EOPNOTSUPP) {
-                               iput(inode);
-                               return error;
-                       }
-               }
-#ifdef CONFIG_TMPFS_POSIX_ACL
-               error = generic_acl_init(inode, dir);
-               if (error) {
-                       iput(inode);
-                       return error;
-               }
-#else
-               error = 0;
-#endif
+               if (error && error != -EOPNOTSUPP)
+                       goto out_iput;
+               error = simple_acl_create(dir, inode);
+               if (error)
+                       goto out_iput;
                d_tmpfile(dentry, inode);
        }
        return error;
+out_iput:
+       iput(inode);
+       return error;
 }
 
 static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@ -2223,8 +2209,8 @@ static int shmem_initxattrs(struct inode *inode,
 
 static const struct xattr_handler *shmem_xattr_handlers[] = {
 #ifdef CONFIG_TMPFS_POSIX_ACL
-       &generic_acl_access_handler,
-       &generic_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL
 };
@@ -2740,6 +2726,7 @@ static const struct inode_operations shmem_inode_operations = {
        .getxattr       = shmem_getxattr,
        .listxattr      = shmem_listxattr,
        .removexattr    = shmem_removexattr,
+       .set_acl        = simple_set_acl,
 #endif
 };
 
@@ -2764,6 +2751,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
+       .set_acl        = simple_set_acl,
 #endif
 };
 
@@ -2776,6 +2764,7 @@ static const struct inode_operations shmem_special_inode_operations = {
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
+       .set_acl        = simple_set_acl,
 #endif
 };
 
index 8e40321da091b66f24f983b266acb344ce41d56c..1ec3c619ba04b955f0d64f32ae3d432d113488f6 100644 (file)
@@ -233,14 +233,17 @@ out_unlock:
        mutex_unlock(&slab_mutex);
        put_online_cpus();
 
-       /*
-        * There is no point in flooding logs with warnings or especially
-        * crashing the system if we fail to create a cache for a memcg. In
-        * this case we will be accounting the memcg allocation to the root
-        * cgroup until we succeed to create its own cache, but it isn't that
-        * critical.
-        */
-       if (err && !memcg) {
+       if (err) {
+               /*
+                * There is no point in flooding logs with warnings or
+                * especially crashing the system if we fail to create a cache
+                * for a memcg. In this case we will be accounting the memcg
+                * allocation to the root cgroup until we succeed to create its
+                * own cache, but it isn't that critical.
+                */
+               if (!memcg)
+                       return NULL;
+
                if (flags & SLAB_PANIC)
                        panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n",
                                name, err);
index 34bb8c65a2d8d7e9973fa501fafbe10cf571b8f3..545a170ebf9f66cf0e3716c9cd6f4cb7eef0eda6 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1559,7 +1559,7 @@ static inline void *acquire_slab(struct kmem_cache *s,
                new.freelist = freelist;
        }
 
-       VM_BUG_ON_PAGE(new.frozen, &new);
+       VM_BUG_ON(new.frozen);
        new.frozen = 1;
 
        if (!__cmpxchg_double_slab(s, page,
@@ -1812,7 +1812,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page,
                        set_freepointer(s, freelist, prior);
                        new.counters = counters;
                        new.inuse--;
-                       VM_BUG_ON_PAGE(!new.frozen, &new);
+                       VM_BUG_ON(!new.frozen);
 
                } while (!__cmpxchg_double_slab(s, page,
                        prior, counters,
@@ -1840,7 +1840,7 @@ redo:
 
        old.freelist = page->freelist;
        old.counters = page->counters;
-       VM_BUG_ON_PAGE(!old.frozen, &old);
+       VM_BUG_ON(!old.frozen);
 
        /* Determine target state of the slab */
        new.counters = old.counters;
@@ -1952,7 +1952,7 @@ static void unfreeze_partials(struct kmem_cache *s,
 
                        old.freelist = page->freelist;
                        old.counters = page->counters;
-                       VM_BUG_ON_PAGE(!old.frozen, &old);
+                       VM_BUG_ON(!old.frozen);
 
                        new.counters = old.counters;
                        new.freelist = old.freelist;
@@ -2225,7 +2225,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
                counters = page->counters;
 
                new.counters = counters;
-               VM_BUG_ON_PAGE(!new.frozen, &new);
+               VM_BUG_ON(!new.frozen);
 
                new.inuse = page->objects;
                new.frozen = freelist != NULL;
@@ -2319,7 +2319,7 @@ load_freelist:
         * page is pointing to the page from which the objects are obtained.
         * That page must be frozen for per cpu allocations to work.
         */
-       VM_BUG_ON_PAGE(!c->page->frozen, c->page);
+       VM_BUG_ON(!c->page->frozen);
        c->freelist = get_freepointer(s, freelist);
        c->tid = next_tid(c->tid);
        local_irq_restore(flags);
index e4f0db2a3eae5ea01f1a80e0d3b680a9c2fa7c08..0fdf96803c5b59623792a24e57015fb0e25098bb 100644 (file)
@@ -220,12 +220,12 @@ int is_vmalloc_or_module_addr(const void *x)
 }
 
 /*
- * Walk a vmap address to the physical pfn it maps to.
+ * Walk a vmap address to the struct page it maps.
  */
-unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
+struct page *vmalloc_to_page(const void *vmalloc_addr)
 {
        unsigned long addr = (unsigned long) vmalloc_addr;
-       unsigned long pfn = 0;
+       struct page *page = NULL;
        pgd_t *pgd = pgd_offset_k(addr);
 
        /*
@@ -244,23 +244,23 @@ unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
                                ptep = pte_offset_map(pmd, addr);
                                pte = *ptep;
                                if (pte_present(pte))
-                                       pfn = pte_pfn(pte);
+                                       page = pte_page(pte);
                                pte_unmap(ptep);
                        }
                }
        }
-       return pfn;
+       return page;
 }
-EXPORT_SYMBOL(vmalloc_to_pfn);
+EXPORT_SYMBOL(vmalloc_to_page);
 
 /*
- * Map a vmalloc()-space virtual address to the struct page.
+ * Map a vmalloc()-space virtual address to the physical page frame number.
  */
-struct page *vmalloc_to_page(const void *vmalloc_addr)
+unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
 {
-       return pfn_to_page(vmalloc_to_pfn(vmalloc_addr));
+       return page_to_pfn(vmalloc_to_page(vmalloc_addr));
 }
-EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_to_pfn);
 
 
 /*** Global kva allocator ***/
index 90c4075d8d75af6358ba6c789bc0747f53460a4d..a9c74b409681a460f2c2ef5f45b3f2283a81a4b8 100644 (file)
@@ -147,7 +147,7 @@ static bool global_reclaim(struct scan_control *sc)
 }
 #endif
 
-unsigned long zone_reclaimable_pages(struct zone *zone)
+static unsigned long zone_reclaimable_pages(struct zone *zone)
 {
        int nr;
 
@@ -3315,27 +3315,6 @@ void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx)
        wake_up_interruptible(&pgdat->kswapd_wait);
 }
 
-/*
- * The reclaimable count would be mostly accurate.
- * The less reclaimable pages may be
- * - mlocked pages, which will be moved to unevictable list when encountered
- * - mapped pages, which may require several travels to be reclaimed
- * - dirty pages, which is not "instantly" reclaimable
- */
-unsigned long global_reclaimable_pages(void)
-{
-       int nr;
-
-       nr = global_page_state(NR_ACTIVE_FILE) +
-            global_page_state(NR_INACTIVE_FILE);
-
-       if (get_nr_swap_pages() > 0)
-               nr += global_page_state(NR_ACTIVE_ANON) +
-                     global_page_state(NR_INACTIVE_ANON);
-
-       return nr;
-}
-
 #ifdef CONFIG_HIBERNATION
 /*
  * Try to free `nr_to_reclaim' of memory, system-wide, and return the number of
index bf3e6a13c215cd61cd7372e85ba19e7fc7974e9a..621b5f65407f739e7fb5f2f743b1421add43ddda 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/ceph/buffer.h>
 #include <linux/ceph/decode.h>
+#include <linux/ceph/libceph.h> /* for ceph_kv{malloc,free} */
 
 struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
 {
@@ -15,16 +16,10 @@ struct ceph_buffer *ceph_buffer_new(size_t len, gfp_t gfp)
        if (!b)
                return NULL;
 
-       b->vec.iov_base = kmalloc(len, gfp | __GFP_NOWARN);
-       if (b->vec.iov_base) {
-               b->is_vmalloc = false;
-       } else {
-               b->vec.iov_base = __vmalloc(len, gfp | __GFP_HIGHMEM, PAGE_KERNEL);
-               if (!b->vec.iov_base) {
-                       kfree(b);
-                       return NULL;
-               }
-               b->is_vmalloc = true;
+       b->vec.iov_base = ceph_kvmalloc(len, gfp);
+       if (!b->vec.iov_base) {
+               kfree(b);
+               return NULL;
        }
 
        kref_init(&b->kref);
@@ -40,12 +35,7 @@ void ceph_buffer_release(struct kref *kref)
        struct ceph_buffer *b = container_of(kref, struct ceph_buffer, kref);
 
        dout("buffer_release %p\n", b);
-       if (b->vec.iov_base) {
-               if (b->is_vmalloc)
-                       vfree(b->vec.iov_base);
-               else
-                       kfree(b->vec.iov_base);
-       }
+       ceph_kvfree(b->vec.iov_base);
        kfree(b);
 }
 EXPORT_SYMBOL(ceph_buffer_release);
index 34b11ee8124ee9b04a7026063b9159e6ce864be2..67d7721d237e1638c21bc62da98f7275a9991026 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/statfs.h>
 #include <linux/string.h>
+#include <linux/vmalloc.h>
 #include <linux/nsproxy.h>
 #include <net/net_namespace.h>
 
@@ -170,6 +171,25 @@ int ceph_compare_options(struct ceph_options *new_opt,
 }
 EXPORT_SYMBOL(ceph_compare_options);
 
+void *ceph_kvmalloc(size_t size, gfp_t flags)
+{
+       if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+               void *ptr = kmalloc(size, flags | __GFP_NOWARN);
+               if (ptr)
+                       return ptr;
+       }
+
+       return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
+}
+
+void ceph_kvfree(const void *ptr)
+{
+       if (is_vmalloc_addr(ptr))
+               vfree(ptr);
+       else
+               kfree(ptr);
+}
+
 
 static int parse_fsid(const char *str, struct ceph_fsid *fsid)
 {
@@ -461,8 +481,8 @@ EXPORT_SYMBOL(ceph_client_id);
  * create a fresh client instance
  */
 struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private,
-                                      unsigned int supported_features,
-                                      unsigned int required_features)
+                                      u64 supported_features,
+                                      u64 required_features)
 {
        struct ceph_client *client;
        struct ceph_entity_addr *myaddr = NULL;
index 089613234f032610c05f25a239c1d2053e768b45..16bc199d9a622e7ecb7957643b26e5c41977ff55 100644 (file)
@@ -116,11 +116,14 @@ void crush_destroy(struct crush_map *map)
        if (map->rules) {
                __u32 b;
                for (b = 0; b < map->max_rules; b++)
-                       kfree(map->rules[b]);
+                       crush_destroy_rule(map->rules[b]);
                kfree(map->rules);
        }
 
        kfree(map);
 }
 
-
+void crush_destroy_rule(struct crush_rule *rule)
+{
+       kfree(rule);
+}
index cbd06a91941c15f3e88b9dd6671694e2fe76dbe2..b703790b4e44788e109bb91ab61f272015000654 100644 (file)
@@ -189,7 +189,7 @@ static int terminal(int x)
 static int bucket_tree_choose(struct crush_bucket_tree *bucket,
                              int x, int r)
 {
-       int n, l;
+       int n;
        __u32 w;
        __u64 t;
 
@@ -197,6 +197,7 @@ static int bucket_tree_choose(struct crush_bucket_tree *bucket,
        n = bucket->num_nodes >> 1;
 
        while (!terminal(n)) {
+               int l;
                /* pick point in [0, w) */
                w = bucket->node_weights[n];
                t = (__u64)crush_hash32_4(bucket->h.hash, x, n, r,
@@ -264,8 +265,12 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
  * true if device is marked "out" (failed, fully offloaded)
  * of the cluster
  */
-static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x)
+static int is_out(const struct crush_map *map,
+                 const __u32 *weight, int weight_max,
+                 int item, int x)
 {
+       if (item >= weight_max)
+               return 1;
        if (weight[item] >= 0x10000)
                return 0;
        if (weight[item] == 0)
@@ -277,7 +282,7 @@ static int is_out(const struct crush_map *map, const __u32 *weight, int item, in
 }
 
 /**
- * crush_choose - choose numrep distinct items of given type
+ * crush_choose_firstn - choose numrep distinct items of given type
  * @map: the crush_map
  * @bucket: the bucket we are choose an item from
  * @x: crush input value
@@ -285,18 +290,24 @@ static int is_out(const struct crush_map *map, const __u32 *weight, int item, in
  * @type: the type of item to choose
  * @out: pointer to output vector
  * @outpos: our position in that vector
- * @firstn: true if choosing "first n" items, false if choosing "indep"
- * @recurse_to_leaf: true if we want one device under each item of given type
- * @descend_once: true if we should only try one descent before giving up
+ * @tries: number of attempts to make
+ * @recurse_tries: number of attempts to have recursive chooseleaf make
+ * @local_tries: localized retries
+ * @local_fallback_tries: localized fallback retries
+ * @recurse_to_leaf: true if we want one device under each item of given type (chooseleaf instead of choose)
  * @out2: second output vector for leaf items (if @recurse_to_leaf)
  */
-static int crush_choose(const struct crush_map *map,
-                       struct crush_bucket *bucket,
-                       const __u32 *weight,
-                       int x, int numrep, int type,
-                       int *out, int outpos,
-                       int firstn, int recurse_to_leaf,
-                       int descend_once, int *out2)
+static int crush_choose_firstn(const struct crush_map *map,
+                              struct crush_bucket *bucket,
+                              const __u32 *weight, int weight_max,
+                              int x, int numrep, int type,
+                              int *out, int outpos,
+                              unsigned int tries,
+                              unsigned int recurse_tries,
+                              unsigned int local_tries,
+                              unsigned int local_fallback_tries,
+                              int recurse_to_leaf,
+                              int *out2)
 {
        int rep;
        unsigned int ftotal, flocal;
@@ -325,35 +336,17 @@ static int crush_choose(const struct crush_map *map,
                                collide = 0;
                                retry_bucket = 0;
                                r = rep;
-                               if (in->alg == CRUSH_BUCKET_UNIFORM) {
-                                       /* be careful */
-                                       if (firstn || (__u32)numrep >= in->size)
-                                               /* r' = r + f_total */
-                                               r += ftotal;
-                                       else if (in->size % numrep == 0)
-                                               /* r'=r+(n+1)*f_local */
-                                               r += (numrep+1) *
-                                                       (flocal+ftotal);
-                                       else
-                                               /* r' = r + n*f_local */
-                                               r += numrep * (flocal+ftotal);
-                               } else {
-                                       if (firstn)
-                                               /* r' = r + f_total */
-                                               r += ftotal;
-                                       else
-                                               /* r' = r + n*f_local */
-                                               r += numrep * (flocal+ftotal);
-                               }
+                               /* r' = r + f_total */
+                               r += ftotal;
 
                                /* bucket choose */
                                if (in->size == 0) {
                                        reject = 1;
                                        goto reject;
                                }
-                               if (map->choose_local_fallback_tries > 0 &&
+                               if (local_fallback_tries > 0 &&
                                    flocal >= (in->size>>1) &&
-                                   flocal > map->choose_local_fallback_tries)
+                                   flocal > local_fallback_tries)
                                        item = bucket_perm_choose(in, x, r);
                                else
                                        item = crush_bucket_choose(in, x, r);
@@ -394,13 +387,15 @@ static int crush_choose(const struct crush_map *map,
                                reject = 0;
                                if (!collide && recurse_to_leaf) {
                                        if (item < 0) {
-                                               if (crush_choose(map,
+                                               if (crush_choose_firstn(map,
                                                         map->buckets[-1-item],
-                                                        weight,
+                                                        weight, weight_max,
                                                         x, outpos+1, 0,
                                                         out2, outpos,
-                                                        firstn, 0,
-                                                        map->chooseleaf_descend_once,
+                                                        recurse_tries, 0,
+                                                        local_tries,
+                                                        local_fallback_tries,
+                                                        0,
                                                         NULL) <= outpos)
                                                        /* didn't get leaf */
                                                        reject = 1;
@@ -414,6 +409,7 @@ static int crush_choose(const struct crush_map *map,
                                        /* out? */
                                        if (itemtype == 0)
                                                reject = is_out(map, weight,
+                                                               weight_max,
                                                                item, x);
                                        else
                                                reject = 0;
@@ -424,17 +420,14 @@ reject:
                                        ftotal++;
                                        flocal++;
 
-                                       if (reject && descend_once)
-                                               /* let outer call try again */
-                                               skip_rep = 1;
-                                       else if (collide && flocal <= map->choose_local_tries)
+                                       if (collide && flocal <= local_tries)
                                                /* retry locally a few times */
                                                retry_bucket = 1;
-                                       else if (map->choose_local_fallback_tries > 0 &&
-                                                flocal <= in->size + map->choose_local_fallback_tries)
+                                       else if (local_fallback_tries > 0 &&
+                                                flocal <= in->size + local_fallback_tries)
                                                /* exhaustive bucket search */
                                                retry_bucket = 1;
-                                       else if (ftotal <= map->choose_total_tries)
+                                       else if (ftotal <= tries)
                                                /* then retry descent */
                                                retry_descent = 1;
                                        else
@@ -463,6 +456,160 @@ reject:
 }
 
 
+/**
+ * crush_choose_indep: alternative breadth-first positionally stable mapping
+ *
+ */
+static void crush_choose_indep(const struct crush_map *map,
+                              struct crush_bucket *bucket,
+                              const __u32 *weight, int weight_max,
+                              int x, int left, int numrep, int type,
+                              int *out, int outpos,
+                              unsigned int tries,
+                              unsigned int recurse_tries,
+                              int recurse_to_leaf,
+                              int *out2,
+                              int parent_r)
+{
+       struct crush_bucket *in = bucket;
+       int endpos = outpos + left;
+       int rep;
+       unsigned int ftotal;
+       int r;
+       int i;
+       int item = 0;
+       int itemtype;
+       int collide;
+
+       dprintk("CHOOSE%s INDEP bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "",
+               bucket->id, x, outpos, numrep);
+
+       /* initially my result is undefined */
+       for (rep = outpos; rep < endpos; rep++) {
+               out[rep] = CRUSH_ITEM_UNDEF;
+               if (out2)
+                       out2[rep] = CRUSH_ITEM_UNDEF;
+       }
+
+       for (ftotal = 0; left > 0 && ftotal < tries; ftotal++) {
+               for (rep = outpos; rep < endpos; rep++) {
+                       if (out[rep] != CRUSH_ITEM_UNDEF)
+                               continue;
+
+                       in = bucket;  /* initial bucket */
+
+                       /* choose through intervening buckets */
+                       for (;;) {
+                               /* note: we base the choice on the position
+                                * even in the nested call.  that means that
+                                * if the first layer chooses the same bucket
+                                * in a different position, we will tend to
+                                * choose a different item in that bucket.
+                                * this will involve more devices in data
+                                * movement and tend to distribute the load.
+                                */
+                               r = rep + parent_r;
+
+                               /* be careful */
+                               if (in->alg == CRUSH_BUCKET_UNIFORM &&
+                                   in->size % numrep == 0)
+                                       /* r'=r+(n+1)*f_total */
+                                       r += (numrep+1) * ftotal;
+                               else
+                                       /* r' = r + n*f_total */
+                                       r += numrep * ftotal;
+
+                               /* bucket choose */
+                               if (in->size == 0) {
+                                       dprintk("   empty bucket\n");
+                                       break;
+                               }
+
+                               item = crush_bucket_choose(in, x, r);
+                               if (item >= map->max_devices) {
+                                       dprintk("   bad item %d\n", item);
+                                       out[rep] = CRUSH_ITEM_NONE;
+                                       if (out2)
+                                               out2[rep] = CRUSH_ITEM_NONE;
+                                       left--;
+                                       break;
+                               }
+
+                               /* desired type? */
+                               if (item < 0)
+                                       itemtype = map->buckets[-1-item]->type;
+                               else
+                                       itemtype = 0;
+                               dprintk("  item %d type %d\n", item, itemtype);
+
+                               /* keep going? */
+                               if (itemtype != type) {
+                                       if (item >= 0 ||
+                                           (-1-item) >= map->max_buckets) {
+                                               dprintk("   bad item type %d\n", type);
+                                               out[rep] = CRUSH_ITEM_NONE;
+                                               if (out2)
+                                                       out2[rep] =
+                                                               CRUSH_ITEM_NONE;
+                                               left--;
+                                               break;
+                                       }
+                                       in = map->buckets[-1-item];
+                                       continue;
+                               }
+
+                               /* collision? */
+                               collide = 0;
+                               for (i = outpos; i < endpos; i++) {
+                                       if (out[i] == item) {
+                                               collide = 1;
+                                               break;
+                                       }
+                               }
+                               if (collide)
+                                       break;
+
+                               if (recurse_to_leaf) {
+                                       if (item < 0) {
+                                               crush_choose_indep(map,
+                                                  map->buckets[-1-item],
+                                                  weight, weight_max,
+                                                  x, 1, numrep, 0,
+                                                  out2, rep,
+                                                  recurse_tries, 0,
+                                                  0, NULL, r);
+                                               if (out2[rep] == CRUSH_ITEM_NONE) {
+                                                       /* placed nothing; no leaf */
+                                                       break;
+                                               }
+                                       } else {
+                                               /* we already have a leaf! */
+                                               out2[rep] = item;
+                                       }
+                               }
+
+                               /* out? */
+                               if (itemtype == 0 &&
+                                   is_out(map, weight, weight_max, item, x))
+                                       break;
+
+                               /* yay! */
+                               out[rep] = item;
+                               left--;
+                               break;
+                       }
+               }
+       }
+       for (rep = outpos; rep < endpos; rep++) {
+               if (out[rep] == CRUSH_ITEM_UNDEF) {
+                       out[rep] = CRUSH_ITEM_NONE;
+               }
+               if (out2 && out2[rep] == CRUSH_ITEM_UNDEF) {
+                       out2[rep] = CRUSH_ITEM_NONE;
+               }
+       }
+}
+
 /**
  * crush_do_rule - calculate a mapping with the given input and rule
  * @map: the crush_map
@@ -470,15 +617,19 @@ reject:
  * @x: hash input
  * @result: pointer to result vector
  * @result_max: maximum result size
+ * @weight: weight vector (for map leaves)
+ * @weight_max: size of weight vector
+ * @scratch: scratch vector for private use; must be >= 3 * result_max
  */
 int crush_do_rule(const struct crush_map *map,
                  int ruleno, int x, int *result, int result_max,
-                 const __u32 *weight)
+                 const __u32 *weight, int weight_max,
+                 int *scratch)
 {
        int result_len;
-       int a[CRUSH_MAX_SET];
-       int b[CRUSH_MAX_SET];
-       int c[CRUSH_MAX_SET];
+       int *a = scratch;
+       int *b = scratch + result_max;
+       int *c = scratch + result_max*2;
        int recurse_to_leaf;
        int *w;
        int wsize = 0;
@@ -489,8 +640,10 @@ int crush_do_rule(const struct crush_map *map,
        __u32 step;
        int i, j;
        int numrep;
-       int firstn;
-       const int descend_once = 0;
+       int choose_tries = map->choose_total_tries;
+       int choose_local_tries = map->choose_local_tries;
+       int choose_local_fallback_tries = map->choose_local_fallback_tries;
+       int choose_leaf_tries = 0;
 
        if ((__u32)ruleno >= map->max_rules) {
                dprintk(" bad ruleno %d\n", ruleno);
@@ -503,29 +656,49 @@ int crush_do_rule(const struct crush_map *map,
        o = b;
 
        for (step = 0; step < rule->len; step++) {
+               int firstn = 0;
                struct crush_rule_step *curstep = &rule->steps[step];
 
-               firstn = 0;
                switch (curstep->op) {
                case CRUSH_RULE_TAKE:
                        w[0] = curstep->arg1;
                        wsize = 1;
                        break;
 
-               case CRUSH_RULE_CHOOSE_LEAF_FIRSTN:
+               case CRUSH_RULE_SET_CHOOSE_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSELEAF_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_leaf_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_local_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES:
+                       if (curstep->arg1 > 0)
+                               choose_local_fallback_tries = curstep->arg1;
+                       break;
+
+               case CRUSH_RULE_CHOOSELEAF_FIRSTN:
                case CRUSH_RULE_CHOOSE_FIRSTN:
                        firstn = 1;
                        /* fall through */
-               case CRUSH_RULE_CHOOSE_LEAF_INDEP:
+               case CRUSH_RULE_CHOOSELEAF_INDEP:
                case CRUSH_RULE_CHOOSE_INDEP:
                        if (wsize == 0)
                                break;
 
                        recurse_to_leaf =
                                curstep->op ==
-                                CRUSH_RULE_CHOOSE_LEAF_FIRSTN ||
+                                CRUSH_RULE_CHOOSELEAF_FIRSTN ||
                                curstep->op ==
-                               CRUSH_RULE_CHOOSE_LEAF_INDEP;
+                               CRUSH_RULE_CHOOSELEAF_INDEP;
 
                        /* reset output */
                        osize = 0;
@@ -543,22 +716,51 @@ int crush_do_rule(const struct crush_map *map,
                                                continue;
                                }
                                j = 0;
-                               osize += crush_choose(map,
-                                                     map->buckets[-1-w[i]],
-                                                     weight,
-                                                     x, numrep,
-                                                     curstep->arg2,
-                                                     o+osize, j,
-                                                     firstn,
-                                                     recurse_to_leaf,
-                                                     descend_once, c+osize);
+                               if (firstn) {
+                                       int recurse_tries;
+                                       if (choose_leaf_tries)
+                                               recurse_tries =
+                                                       choose_leaf_tries;
+                                       else if (map->chooseleaf_descend_once)
+                                               recurse_tries = 1;
+                                       else
+                                               recurse_tries = choose_tries;
+                                       osize += crush_choose_firstn(
+                                               map,
+                                               map->buckets[-1-w[i]],
+                                               weight, weight_max,
+                                               x, numrep,
+                                               curstep->arg2,
+                                               o+osize, j,
+                                               choose_tries,
+                                               recurse_tries,
+                                               choose_local_tries,
+                                               choose_local_fallback_tries,
+                                               recurse_to_leaf,
+                                               c+osize);
+                               } else {
+                                       crush_choose_indep(
+                                               map,
+                                               map->buckets[-1-w[i]],
+                                               weight, weight_max,
+                                               x, numrep, numrep,
+                                               curstep->arg2,
+                                               o+osize, j,
+                                               choose_tries,
+                                               choose_leaf_tries ?
+                                                  choose_leaf_tries : 1,
+                                               recurse_to_leaf,
+                                               c+osize,
+                                               0);
+                                       osize += numrep;
+                               }
                        }
 
                        if (recurse_to_leaf)
                                /* copy final _leaf_ values to output set */
                                memcpy(o, c, osize*sizeof(*o));
 
-                       /* swap t and w arrays */
+                       /* swap o and w arrays */
                        tmp = o;
                        o = w;
                        w = tmp;
index 83661cdc0766de24a458d06cdede00c3f3d6a4a2..258a382e75ed665a597d063a1234150e47d8f5f0 100644 (file)
@@ -132,7 +132,8 @@ static int osdc_show(struct seq_file *s, void *pp)
                           req->r_osd ? req->r_osd->o_osd : -1,
                           req->r_pgid.pool, req->r_pgid.seed);
 
-               seq_printf(s, "%.*s", req->r_oid_len, req->r_oid);
+               seq_printf(s, "%.*s", req->r_base_oid.name_len,
+                          req->r_base_oid.name);
 
                if (req->r_reassert_version.epoch)
                        seq_printf(s, "\t%u'%llu",
index 4a5df7b1cc9ff5652185e0248cf5a4df4006effd..2ed1304d22a7dfed5c8bc9f86d5f0f5cb1b91742 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dns_resolver.h>
 #include <net/tcp.h>
 
+#include <linux/ceph/ceph_features.h>
 #include <linux/ceph/libceph.h>
 #include <linux/ceph/messenger.h>
 #include <linux/ceph/decode.h>
@@ -1865,7 +1866,9 @@ int ceph_parse_ips(const char *c, const char *end,
                                port = (port * 10) + (*p - '0');
                                p++;
                        }
-                       if (port > 65535 || port == 0)
+                       if (port == 0)
+                               port = CEPH_MON_PORT;
+                       else if (port > 65535)
                                goto bad;
                } else {
                        port = CEPH_MON_PORT;
@@ -1945,7 +1948,8 @@ static int process_connect(struct ceph_connection *con)
 {
        u64 sup_feat = con->msgr->supported_features;
        u64 req_feat = con->msgr->required_features;
-       u64 server_feat = le64_to_cpu(con->in_reply.features);
+       u64 server_feat = ceph_sanitize_features(
+                               le64_to_cpu(con->in_reply.features));
        int ret;
 
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
@@ -2853,8 +2857,8 @@ static void con_fault(struct ceph_connection *con)
  */
 void ceph_messenger_init(struct ceph_messenger *msgr,
                        struct ceph_entity_addr *myaddr,
-                       u32 supported_features,
-                       u32 required_features,
+                       u64 supported_features,
+                       u64 required_features,
                        bool nocrc)
 {
        msgr->supported_features = supported_features;
@@ -3126,15 +3130,8 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
        INIT_LIST_HEAD(&m->data);
 
        /* front */
-       m->front_max = front_len;
        if (front_len) {
-               if (front_len > PAGE_CACHE_SIZE) {
-                       m->front.iov_base = __vmalloc(front_len, flags,
-                                                     PAGE_KERNEL);
-                       m->front_is_vmalloc = true;
-               } else {
-                       m->front.iov_base = kmalloc(front_len, flags);
-               }
+               m->front.iov_base = ceph_kvmalloc(front_len, flags);
                if (m->front.iov_base == NULL) {
                        dout("ceph_msg_new can't allocate %d bytes\n",
                             front_len);
@@ -3143,7 +3140,7 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
        } else {
                m->front.iov_base = NULL;
        }
-       m->front.iov_len = front_len;
+       m->front_alloc_len = m->front.iov_len = front_len;
 
        dout("ceph_msg_new %p front %d\n", m, front_len);
        return m;
@@ -3256,10 +3253,7 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
 void ceph_msg_kfree(struct ceph_msg *m)
 {
        dout("msg_kfree %p\n", m);
-       if (m->front_is_vmalloc)
-               vfree(m->front.iov_base);
-       else
-               kfree(m->front.iov_base);
+       ceph_kvfree(m->front.iov_base);
        kmem_cache_free(ceph_msg_cache, m);
 }
 
@@ -3301,8 +3295,8 @@ EXPORT_SYMBOL(ceph_msg_last_put);
 
 void ceph_msg_dump(struct ceph_msg *msg)
 {
-       pr_debug("msg_dump %p (front_max %d length %zd)\n", msg,
-                msg->front_max, msg->data_length);
+       pr_debug("msg_dump %p (front_alloc_len %d length %zd)\n", msg,
+                msg->front_alloc_len, msg->data_length);
        print_hex_dump(KERN_DEBUG, "header: ",
                       DUMP_PREFIX_OFFSET, 16, 1,
                       &msg->hdr, sizeof(msg->hdr), true);
index 1fe25cd29d0eceb66bb4924ee85e5a62b598c48a..2ac9ef35110b3e9ea07363d6f2d3c0eb2e4ee27b 100644 (file)
@@ -152,7 +152,7 @@ static int __open_session(struct ceph_mon_client *monc)
                /* initiatiate authentication handshake */
                ret = ceph_auth_build_hello(monc->auth,
                                            monc->m_auth->front.iov_base,
-                                           monc->m_auth->front_max);
+                                           monc->m_auth->front_alloc_len);
                __send_prepared_auth_request(monc, ret);
        } else {
                dout("open_session mon%d already open\n", monc->cur_mon);
@@ -196,7 +196,7 @@ static void __send_subscribe(struct ceph_mon_client *monc)
                int num;
 
                p = msg->front.iov_base;
-               end = p + msg->front_max;
+               end = p + msg->front_alloc_len;
 
                num = 1 + !!monc->want_next_osdmap + !!monc->want_mdsmap;
                ceph_encode_32(&p, num);
@@ -897,7 +897,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
        ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
                                     msg->front.iov_len,
                                     monc->m_auth->front.iov_base,
-                                    monc->m_auth->front_max);
+                                    monc->m_auth->front_alloc_len);
        if (ret < 0) {
                monc->client->auth_err = ret;
                wake_up_all(&monc->client->auth_wq);
@@ -939,7 +939,7 @@ static int __validate_auth(struct ceph_mon_client *monc)
                return 0;
 
        ret = ceph_build_auth(monc->auth, monc->m_auth->front.iov_base,
-                             monc->m_auth->front_max);
+                             monc->m_auth->front_alloc_len);
        if (ret <= 0)
                return ret; /* either an error, or no need to authenticate */
        __send_prepared_auth_request(monc, ret);
index 2b4b32aaa893b3117043e6a218fcde6c58f0aff4..010ff3bd58ade67373c0db7531a2ec8ea9bb1460 100644 (file)
@@ -338,7 +338,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
        msg_size = 4 + 4 + 8 + 8 + 4+8;
        msg_size += 2 + 4 + 8 + 4 + 4; /* oloc */
        msg_size += 1 + 8 + 4 + 4;     /* pg_t */
-       msg_size += 4 + MAX_OBJ_NAME_SIZE;
+       msg_size += 4 + CEPH_MAX_OID_NAME_LEN; /* oid */
        msg_size += 2 + num_ops*sizeof(struct ceph_osd_op);
        msg_size += 8;  /* snapid */
        msg_size += 8;  /* snap_seq */
@@ -368,6 +368,9 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
        INIT_LIST_HEAD(&req->r_req_lru_item);
        INIT_LIST_HEAD(&req->r_osd_item);
 
+       req->r_base_oloc.pool = -1;
+       req->r_target_oloc.pool = -1;
+
        /* create reply message */
        if (use_mempool)
                msg = ceph_msgpool_get(&osdc->msgpool_op_reply, 0);
@@ -761,11 +764,11 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
        if (num_ops > 1)
                osd_req_op_init(req, 1, CEPH_OSD_OP_STARTSYNC);
 
-       req->r_file_layout = *layout;  /* keep a copy */
+       req->r_base_oloc.pool = ceph_file_layout_pg_pool(*layout);
 
-       snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx",
-               vino.ino, objnum);
-       req->r_oid_len = strlen(req->r_oid);
+       snprintf(req->r_base_oid.name, sizeof(req->r_base_oid.name),
+                "%llx.%08llx", vino.ino, objnum);
+       req->r_base_oid.name_len = strlen(req->r_base_oid.name);
 
        return req;
 }
@@ -1044,8 +1047,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
                        !ceph_con_opened(&osd->o_con)) {
                struct ceph_osd_request *req;
 
-               dout(" osd addr hasn't changed and connection never opened,"
-                    " letting msgr retry");
+               dout("osd addr hasn't changed and connection never opened, "
+                    "letting msgr retry\n");
                /* touch each r_stamp for handle_timeout()'s benfit */
                list_for_each_entry(req, &osd->o_requests, r_osd_item)
                        req->r_stamp = jiffies;
@@ -1231,6 +1234,61 @@ void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc,
 }
 EXPORT_SYMBOL(ceph_osdc_set_request_linger);
 
+/*
+ * Returns whether a request should be blocked from being sent
+ * based on the current osdmap and osd_client settings.
+ *
+ * Caller should hold map_sem for read.
+ */
+static bool __req_should_be_paused(struct ceph_osd_client *osdc,
+                                  struct ceph_osd_request *req)
+{
+       bool pauserd = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD);
+       bool pausewr = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR) ||
+               ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL);
+       return (req->r_flags & CEPH_OSD_FLAG_READ && pauserd) ||
+               (req->r_flags & CEPH_OSD_FLAG_WRITE && pausewr);
+}
+
+/*
+ * Calculate mapping of a request to a PG.  Takes tiering into account.
+ */
+static int __calc_request_pg(struct ceph_osdmap *osdmap,
+                            struct ceph_osd_request *req,
+                            struct ceph_pg *pg_out)
+{
+       bool need_check_tiering;
+
+       need_check_tiering = false;
+       if (req->r_target_oloc.pool == -1) {
+               req->r_target_oloc = req->r_base_oloc; /* struct */
+               need_check_tiering = true;
+       }
+       if (req->r_target_oid.name_len == 0) {
+               ceph_oid_copy(&req->r_target_oid, &req->r_base_oid);
+               need_check_tiering = true;
+       }
+
+       if (need_check_tiering &&
+           (req->r_flags & CEPH_OSD_FLAG_IGNORE_OVERLAY) == 0) {
+               struct ceph_pg_pool_info *pi;
+
+               pi = ceph_pg_pool_by_id(osdmap, req->r_target_oloc.pool);
+               if (pi) {
+                       if ((req->r_flags & CEPH_OSD_FLAG_READ) &&
+                           pi->read_tier >= 0)
+                               req->r_target_oloc.pool = pi->read_tier;
+                       if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
+                           pi->write_tier >= 0)
+                               req->r_target_oloc.pool = pi->write_tier;
+               }
+               /* !pi is caught in ceph_oloc_oid_to_pg() */
+       }
+
+       return ceph_oloc_oid_to_pg(osdmap, &req->r_target_oloc,
+                                  &req->r_target_oid, pg_out);
+}
+
 /*
  * Pick an osd (the first 'up' osd in the pg), allocate the osd struct
  * (as needed), and set the request r_osd appropriately.  If there is
@@ -1248,10 +1306,11 @@ static int __map_request(struct ceph_osd_client *osdc,
        int acting[CEPH_PG_MAX_SIZE];
        int o = -1, num = 0;
        int err;
+       bool was_paused;
 
        dout("map_request %p tid %lld\n", req, req->r_tid);
-       err = ceph_calc_ceph_pg(&pgid, req->r_oid, osdc->osdmap,
-                               ceph_file_layout_pg_pool(req->r_file_layout));
+
+       err = __calc_request_pg(osdc->osdmap, req, &pgid);
        if (err) {
                list_move(&req->r_req_lru_item, &osdc->req_notarget);
                return err;
@@ -1264,12 +1323,18 @@ static int __map_request(struct ceph_osd_client *osdc,
                num = err;
        }
 
+       was_paused = req->r_paused;
+       req->r_paused = __req_should_be_paused(osdc, req);
+       if (was_paused && !req->r_paused)
+               force_resend = 1;
+
        if ((!force_resend &&
             req->r_osd && req->r_osd->o_osd == o &&
             req->r_sent >= req->r_osd->o_incarnation &&
             req->r_num_pg_osds == num &&
             memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) ||
-           (req->r_osd == NULL && o == -1))
+           (req->r_osd == NULL && o == -1) ||
+           req->r_paused)
                return 0;  /* no change */
 
        dout("map_request tid %llu pgid %lld.%x osd%d (was osd%d)\n",
@@ -1331,7 +1396,7 @@ static void __send_request(struct ceph_osd_client *osdc,
        /* fill in message content that changes each time we send it */
        put_unaligned_le32(osdc->osdmap->epoch, req->r_request_osdmap_epoch);
        put_unaligned_le32(req->r_flags, req->r_request_flags);
-       put_unaligned_le64(req->r_pgid.pool, req->r_request_pool);
+       put_unaligned_le64(req->r_target_oloc.pool, req->r_request_pool);
        p = req->r_request_pgid;
        ceph_encode_64(&p, req->r_pgid.pool);
        ceph_encode_32(&p, req->r_pgid.seed);
@@ -1432,6 +1497,109 @@ static void handle_osds_timeout(struct work_struct *work)
                              round_jiffies_relative(delay));
 }
 
+static int ceph_oloc_decode(void **p, void *end,
+                           struct ceph_object_locator *oloc)
+{
+       u8 struct_v, struct_cv;
+       u32 len;
+       void *struct_end;
+       int ret = 0;
+
+       ceph_decode_need(p, end, 1 + 1 + 4, e_inval);
+       struct_v = ceph_decode_8(p);
+       struct_cv = ceph_decode_8(p);
+       if (struct_v < 3) {
+               pr_warn("got v %d < 3 cv %d of ceph_object_locator\n",
+                       struct_v, struct_cv);
+               goto e_inval;
+       }
+       if (struct_cv > 6) {
+               pr_warn("got v %d cv %d > 6 of ceph_object_locator\n",
+                       struct_v, struct_cv);
+               goto e_inval;
+       }
+       len = ceph_decode_32(p);
+       ceph_decode_need(p, end, len, e_inval);
+       struct_end = *p + len;
+
+       oloc->pool = ceph_decode_64(p);
+       *p += 4; /* skip preferred */
+
+       len = ceph_decode_32(p);
+       if (len > 0) {
+               pr_warn("ceph_object_locator::key is set\n");
+               goto e_inval;
+       }
+
+       if (struct_v >= 5) {
+               len = ceph_decode_32(p);
+               if (len > 0) {
+                       pr_warn("ceph_object_locator::nspace is set\n");
+                       goto e_inval;
+               }
+       }
+
+       if (struct_v >= 6) {
+               s64 hash = ceph_decode_64(p);
+               if (hash != -1) {
+                       pr_warn("ceph_object_locator::hash is set\n");
+                       goto e_inval;
+               }
+       }
+
+       /* skip the rest */
+       *p = struct_end;
+out:
+       return ret;
+
+e_inval:
+       ret = -EINVAL;
+       goto out;
+}
+
+static int ceph_redirect_decode(void **p, void *end,
+                               struct ceph_request_redirect *redir)
+{
+       u8 struct_v, struct_cv;
+       u32 len;
+       void *struct_end;
+       int ret;
+
+       ceph_decode_need(p, end, 1 + 1 + 4, e_inval);
+       struct_v = ceph_decode_8(p);
+       struct_cv = ceph_decode_8(p);
+       if (struct_cv > 1) {
+               pr_warn("got v %d cv %d > 1 of ceph_request_redirect\n",
+                       struct_v, struct_cv);
+               goto e_inval;
+       }
+       len = ceph_decode_32(p);
+       ceph_decode_need(p, end, len, e_inval);
+       struct_end = *p + len;
+
+       ret = ceph_oloc_decode(p, end, &redir->oloc);
+       if (ret)
+               goto out;
+
+       len = ceph_decode_32(p);
+       if (len > 0) {
+               pr_warn("ceph_request_redirect::object_name is set\n");
+               goto e_inval;
+       }
+
+       len = ceph_decode_32(p);
+       *p += len; /* skip osd_instructions */
+
+       /* skip the rest */
+       *p = struct_end;
+out:
+       return ret;
+
+e_inval:
+       ret = -EINVAL;
+       goto out;
+}
+
 static void complete_request(struct ceph_osd_request *req)
 {
        complete_all(&req->r_safe_completion);  /* fsync waiter */
@@ -1446,6 +1614,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
 {
        void *p, *end;
        struct ceph_osd_request *req;
+       struct ceph_request_redirect redir;
        u64 tid;
        int object_len;
        unsigned int numops;
@@ -1525,10 +1694,41 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
        for (i = 0; i < numops; i++)
                req->r_reply_op_result[i] = ceph_decode_32(&p);
 
-       already_completed = req->r_got_reply;
+       if (le16_to_cpu(msg->hdr.version) >= 6) {
+               p += 8 + 4; /* skip replay_version */
+               p += 8; /* skip user_version */
 
-       if (!req->r_got_reply) {
+               err = ceph_redirect_decode(&p, end, &redir);
+               if (err)
+                       goto bad_put;
+       } else {
+               redir.oloc.pool = -1;
+       }
+
+       if (redir.oloc.pool != -1) {
+               dout("redirect pool %lld\n", redir.oloc.pool);
+
+               __unregister_request(osdc, req);
+               mutex_unlock(&osdc->request_mutex);
+
+               req->r_target_oloc = redir.oloc; /* struct */
+
+               /*
+                * Start redirect requests with nofail=true.  If
+                * mapping fails, request will end up on the notarget
+                * list, waiting for the new osdmap (which can take
+                * a while), even though the original request mapped
+                * successfully.  In the future we might want to follow
+                * original request's nofail setting here.
+                */
+               err = ceph_osdc_start_request(osdc, req, true);
+               BUG_ON(err);
 
+               goto done;
+       }
+
+       already_completed = req->r_got_reply;
+       if (!req->r_got_reply) {
                req->r_result = result;
                dout("handle_reply result %d bytes %d\n", req->r_result,
                     bytes);
@@ -1581,6 +1781,13 @@ done:
        return;
 
 bad_put:
+       req->r_result = -EIO;
+       __unregister_request(osdc, req);
+       if (req->r_callback)
+               req->r_callback(req, msg);
+       else
+               complete_all(&req->r_completion);
+       complete_request(req);
        ceph_osdc_put_request(req);
 bad_mutex:
        mutex_unlock(&osdc->request_mutex);
@@ -1613,14 +1820,17 @@ static void reset_changed_osds(struct ceph_osd_client *osdc)
  *
  * Caller should hold map_sem for read.
  */
-static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
+static void kick_requests(struct ceph_osd_client *osdc, bool force_resend,
+                         bool force_resend_writes)
 {
        struct ceph_osd_request *req, *nreq;
        struct rb_node *p;
        int needmap = 0;
        int err;
+       bool force_resend_req;
 
-       dout("kick_requests %s\n", force_resend ? " (force resend)" : "");
+       dout("kick_requests %s %s\n", force_resend ? " (force resend)" : "",
+               force_resend_writes ? " (force resend writes)" : "");
        mutex_lock(&osdc->request_mutex);
        for (p = rb_first(&osdc->requests); p; ) {
                req = rb_entry(p, struct ceph_osd_request, r_node);
@@ -1645,7 +1855,10 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                        continue;
                }
 
-               err = __map_request(osdc, req, force_resend);
+               force_resend_req = force_resend ||
+                       (force_resend_writes &&
+                               req->r_flags & CEPH_OSD_FLAG_WRITE);
+               err = __map_request(osdc, req, force_resend_req);
                if (err < 0)
                        continue;  /* error */
                if (req->r_osd == NULL) {
@@ -1665,7 +1878,8 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
                                 r_linger_item) {
                dout("linger req=%p req->r_osd=%p\n", req, req->r_osd);
 
-               err = __map_request(osdc, req, force_resend);
+               err = __map_request(osdc, req,
+                                   force_resend || force_resend_writes);
                dout("__map_request returned %d\n", err);
                if (err == 0)
                        continue;  /* no change and no osd was specified */
@@ -1707,6 +1921,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
        struct ceph_osdmap *newmap = NULL, *oldmap;
        int err;
        struct ceph_fsid fsid;
+       bool was_full;
 
        dout("handle_map have %u\n", osdc->osdmap ? osdc->osdmap->epoch : 0);
        p = msg->front.iov_base;
@@ -1720,6 +1935,8 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
 
        down_write(&osdc->map_sem);
 
+       was_full = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL);
+
        /* incremental maps */
        ceph_decode_32_safe(&p, end, nr_maps, bad);
        dout(" %d inc maps\n", nr_maps);
@@ -1744,7 +1961,10 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
                                ceph_osdmap_destroy(osdc->osdmap);
                                osdc->osdmap = newmap;
                        }
-                       kick_requests(osdc, 0);
+                       was_full = was_full ||
+                               ceph_osdmap_flag(osdc->osdmap,
+                                                CEPH_OSDMAP_FULL);
+                       kick_requests(osdc, 0, was_full);
                } else {
                        dout("ignoring incremental map %u len %d\n",
                             epoch, maplen);
@@ -1787,7 +2007,10 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
                                        skipped_map = 1;
                                ceph_osdmap_destroy(oldmap);
                        }
-                       kick_requests(osdc, skipped_map);
+                       was_full = was_full ||
+                               ceph_osdmap_flag(osdc->osdmap,
+                                                CEPH_OSDMAP_FULL);
+                       kick_requests(osdc, skipped_map, was_full);
                }
                p += maplen;
                nr_maps--;
@@ -1804,7 +2027,9 @@ done:
         * we find out when we are no longer full and stop returning
         * ENOSPC.
         */
-       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL))
+       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
+               ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD) ||
+               ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR))
                ceph_monc_request_next_osdmap(&osdc->client->monc);
 
        mutex_lock(&osdc->request_mutex);
@@ -2068,10 +2293,11 @@ void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off,
        ceph_encode_32(&p, -1);  /* preferred */
 
        /* oid */
-       ceph_encode_32(&p, req->r_oid_len);
-       memcpy(p, req->r_oid, req->r_oid_len);
-       dout("oid '%.*s' len %d\n", req->r_oid_len, req->r_oid, req->r_oid_len);
-       p += req->r_oid_len;
+       ceph_encode_32(&p, req->r_base_oid.name_len);
+       memcpy(p, req->r_base_oid.name, req->r_base_oid.name_len);
+       dout("oid '%.*s' len %d\n", req->r_base_oid.name_len,
+            req->r_base_oid.name, req->r_base_oid.name_len);
+       p += req->r_base_oid.name_len;
 
        /* ops--can imply data */
        ceph_encode_16(&p, (u16)req->r_num_ops);
@@ -2454,7 +2680,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
        struct ceph_osd_client *osdc = osd->o_osdc;
        struct ceph_msg *m;
        struct ceph_osd_request *req;
-       int front = le32_to_cpu(hdr->front_len);
+       int front_len = le32_to_cpu(hdr->front_len);
        int data_len = le32_to_cpu(hdr->data_len);
        u64 tid;
 
@@ -2474,12 +2700,13 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
                     req->r_reply, req->r_reply->con);
        ceph_msg_revoke_incoming(req->r_reply);
 
-       if (front > req->r_reply->front.iov_len) {
+       if (front_len > req->r_reply->front_alloc_len) {
                pr_warning("get_reply front %d > preallocated %d (%u#%llu)\n",
-                          front, (int)req->r_reply->front.iov_len,
+                          front_len, req->r_reply->front_alloc_len,
                           (unsigned int)con->peer_name.type,
                           le64_to_cpu(con->peer_name.num));
-               m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS, false);
+               m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front_len, GFP_NOFS,
+                                false);
                if (!m)
                        goto out;
                ceph_msg_put(req->r_reply);
index dbd9a4792427455e0a2dfdd7d2249c4abcbbb798..aade4a5c1c07f6ab0ca0f1ee66dfacbded110aed 100644 (file)
@@ -464,6 +464,11 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, u64 id)
        return NULL;
 }
 
+struct ceph_pg_pool_info *ceph_pg_pool_by_id(struct ceph_osdmap *map, u64 id)
+{
+       return __lookup_pg_pool(&map->pg_pools, id);
+}
+
 const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id)
 {
        struct ceph_pg_pool_info *pi;
@@ -514,8 +519,8 @@ static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
                pr_warning("got v %d < 5 cv %d of ceph_pg_pool\n", ev, cv);
                return -EINVAL;
        }
-       if (cv > 7) {
-               pr_warning("got v %d cv %d > 7 of ceph_pg_pool\n", ev, cv);
+       if (cv > 9) {
+               pr_warning("got v %d cv %d > 9 of ceph_pg_pool\n", ev, cv);
                return -EINVAL;
        }
        len = ceph_decode_32(p);
@@ -543,12 +548,34 @@ static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
                *p += len;
        }
 
-       /* skip removed snaps */
+       /* skip removed_snaps */
        num = ceph_decode_32(p);
        *p += num * (8 + 8);
 
        *p += 8;  /* skip auid */
        pi->flags = ceph_decode_64(p);
+       *p += 4;  /* skip crash_replay_interval */
+
+       if (ev >= 7)
+               *p += 1;  /* skip min_size */
+
+       if (ev >= 8)
+               *p += 8 + 8;  /* skip quota_max_* */
+
+       if (ev >= 9) {
+               /* skip tiers */
+               num = ceph_decode_32(p);
+               *p += num * 8;
+
+               *p += 8;  /* skip tier_of */
+               *p += 1;  /* skip cache_mode */
+
+               pi->read_tier = ceph_decode_64(p);
+               pi->write_tier = ceph_decode_64(p);
+       } else {
+               pi->read_tier = -1;
+               pi->write_tier = -1;
+       }
 
        /* ignore the rest */
 
@@ -1090,25 +1117,40 @@ invalid:
 EXPORT_SYMBOL(ceph_calc_file_object_mapping);
 
 /*
- * calculate an object layout (i.e. pgid) from an oid,
- * file_layout, and osdmap
+ * Calculate mapping of a (oloc, oid) pair to a PG.  Should only be
+ * called with target's (oloc, oid), since tiering isn't taken into
+ * account.
  */
-int ceph_calc_ceph_pg(struct ceph_pg *pg, const char *oid,
-                       struct ceph_osdmap *osdmap, uint64_t pool)
+int ceph_oloc_oid_to_pg(struct ceph_osdmap *osdmap,
+                       struct ceph_object_locator *oloc,
+                       struct ceph_object_id *oid,
+                       struct ceph_pg *pg_out)
 {
-       struct ceph_pg_pool_info *pool_info;
+       struct ceph_pg_pool_info *pi;
 
-       BUG_ON(!osdmap);
-       pool_info = __lookup_pg_pool(&osdmap->pg_pools, pool);
-       if (!pool_info)
+       pi = __lookup_pg_pool(&osdmap->pg_pools, oloc->pool);
+       if (!pi)
                return -EIO;
-       pg->pool = pool;
-       pg->seed = ceph_str_hash(pool_info->object_hash, oid, strlen(oid));
 
-       dout("%s '%s' pgid %lld.%x\n", __func__, oid, pg->pool, pg->seed);
+       pg_out->pool = oloc->pool;
+       pg_out->seed = ceph_str_hash(pi->object_hash, oid->name,
+                                    oid->name_len);
+
+       dout("%s '%.*s' pgid %llu.%x\n", __func__, oid->name_len, oid->name,
+            pg_out->pool, pg_out->seed);
        return 0;
 }
-EXPORT_SYMBOL(ceph_calc_ceph_pg);
+EXPORT_SYMBOL(ceph_oloc_oid_to_pg);
+
+static int crush_do_rule_ary(const struct crush_map *map, int ruleno, int x,
+                            int *result, int result_max,
+                            const __u32 *weight, int weight_max)
+{
+       int scratch[result_max * 3];
+
+       return crush_do_rule(map, ruleno, x, result, result_max,
+                            weight, weight_max, scratch);
+}
 
 /*
  * Calculate raw osd vector for the given pgid.  Return pointer to osd
@@ -1163,9 +1205,9 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
                                      pool->pgp_num_mask) +
                        (unsigned)pgid.pool;
        }
-       r = crush_do_rule(osdmap->crush, ruleno, pps, osds,
-                         min_t(int, pool->size, *num),
-                         osdmap->osd_weight);
+       r = crush_do_rule_ary(osdmap->crush, ruleno, pps,
+                             osds, min_t(int, pool->size, *num),
+                             osdmap->osd_weight, osdmap->max_osd);
        if (r < 0) {
                pr_err("error %d from crush rule: pool %lld ruleset %d type %d"
                       " size %d\n", r, pgid.pool, pool->crush_ruleset,
index 42fdfc634e568a58bda35d2dbb1effbf44dd1bd4..0a2aee060f9f05241bdedd25149b081e32bd7896 100644 (file)
@@ -536,8 +536,7 @@ static void warn_gssd(void)
        unsigned long now = jiffies;
 
        if (time_after(now, ratelimit)) {
-               printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
-                               "Please check user daemon is running.\n");
+               pr_warn("RPC: AUTH_GSS upcall failed. Please check user daemon is running.\n");
                ratelimit = now + 15*HZ;
        }
 }
@@ -600,7 +599,6 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
        struct rpc_pipe *pipe;
        struct rpc_cred *cred = &gss_cred->gc_base;
        struct gss_upcall_msg *gss_msg;
-       unsigned long timeout;
        DEFINE_WAIT(wait);
        int err;
 
@@ -608,17 +606,16 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
                __func__, from_kuid(&init_user_ns, cred->cr_uid));
 retry:
        err = 0;
-       /* Default timeout is 15s unless we know that gssd is not running */
-       timeout = 15 * HZ;
-       if (!sn->gssd_running)
-               timeout = HZ >> 2;
+       /* if gssd is down, just skip upcalling altogether */
+       if (!gssd_running(net)) {
+               warn_gssd();
+               return -EACCES;
+       }
        gss_msg = gss_setup_upcall(gss_auth, cred);
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                err = wait_event_interruptible_timeout(pipe_version_waitqueue,
-                               sn->pipe_version >= 0, timeout);
+                               sn->pipe_version >= 0, 15 * HZ);
                if (sn->pipe_version < 0) {
-                       if (err == 0)
-                               sn->gssd_running = 0;
                        warn_gssd();
                        err = -EACCES;
                }
index f09b7db2c492f5a3f20a954e07e23b1a2f054c5e..0edada973434e4df883f63a85173f4a7a1de0885 100644 (file)
@@ -1529,9 +1529,13 @@ call_refreshresult(struct rpc_task *task)
        task->tk_action = call_refresh;
        switch (status) {
        case 0:
-               if (rpcauth_uptodatecred(task))
+               if (rpcauth_uptodatecred(task)) {
                        task->tk_action = call_allocate;
-               return;
+                       return;
+               }
+               /* Use rate-limiting and a max number of retries if refresh
+                * had status 0 but failed to update the cred.
+                */
        case -ETIMEDOUT:
                rpc_delay(task, 3*HZ);
        case -EAGAIN:
@@ -1729,6 +1733,7 @@ call_bind_status(struct rpc_task *task)
                return;
        case -ECONNREFUSED:             /* connection problems */
        case -ECONNRESET:
+       case -ECONNABORTED:
        case -ENOTCONN:
        case -EHOSTDOWN:
        case -EHOSTUNREACH:
@@ -1799,7 +1804,9 @@ call_connect_status(struct rpc_task *task)
                return;
        case -ECONNREFUSED:
        case -ECONNRESET:
+       case -ECONNABORTED:
        case -ENETUNREACH:
+       case -EHOSTUNREACH:
                /* retry with existing socket, after a delay */
                rpc_delay(task, 3*HZ);
                if (RPC_IS_SOFTCONN(task))
@@ -1902,6 +1909,7 @@ call_transmit_status(struct rpc_task *task)
                        break;
                }
        case -ECONNRESET:
+       case -ECONNABORTED:
        case -ENOTCONN:
        case -EPIPE:
                rpc_task_force_reencode(task);
@@ -2011,8 +2019,9 @@ call_status(struct rpc_task *task)
                        xprt_conditional_disconnect(req->rq_xprt,
                                        req->rq_connect_cookie);
                break;
-       case -ECONNRESET:
        case -ECONNREFUSED:
+       case -ECONNRESET:
+       case -ECONNABORTED:
                rpc_force_rebind(clnt);
                rpc_delay(task, 3*HZ);
        case -EPIPE:
index 779742cfc1ffe3178fc0c320b6d0832e0f420d64..94e506f9d72bb62440d923360753c98ecf5f6725 100644 (file)
@@ -14,6 +14,7 @@ struct sunrpc_net {
        struct cache_detail *rsi_cache;
 
        struct super_block *pipefs_sb;
+       struct rpc_pipe *gssd_dummy;
        struct mutex pipefs_sb_lock;
 
        struct list_head all_clients;
@@ -32,8 +33,6 @@ struct sunrpc_net {
        int pipe_version;
        atomic_t pipe_users;
        struct proc_dir_entry *use_gssp_proc;
-
-       unsigned int gssd_running;
 };
 
 extern int sunrpc_net_id;
index bf04b30a788a5425b28ba70c11a50b77bfc9c697..b185548985622c0c23b1e0dc01acb783ee81246a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fsnotify.h>
 #include <linux/kernel.h>
 #include <linux/rcupdate.h>
+#include <linux/utsname.h>
 
 #include <asm/ioctls.h>
 #include <linux/poll.h>
@@ -38,7 +39,7 @@
 #define NET_NAME(net)  ((net == &init_net) ? " (init_net)" : "")
 
 static struct file_system_type rpc_pipe_fs_type;
-
+static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
 
 static struct kmem_cache *rpc_inode_cachep __read_mostly;
 
@@ -216,14 +217,11 @@ rpc_destroy_inode(struct inode *inode)
 static int
 rpc_pipe_open(struct inode *inode, struct file *filp)
 {
-       struct net *net = inode->i_sb->s_fs_info;
-       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        struct rpc_pipe *pipe;
        int first_open;
        int res = -ENXIO;
 
        mutex_lock(&inode->i_mutex);
-       sn->gssd_running = 1;
        pipe = RPC_I(inode)->pipe;
        if (pipe == NULL)
                goto out;
@@ -1159,6 +1157,7 @@ enum {
        RPCAUTH_nfsd4_cb,
        RPCAUTH_cache,
        RPCAUTH_nfsd,
+       RPCAUTH_gssd,
        RPCAUTH_RootEOF
 };
 
@@ -1195,6 +1194,10 @@ static const struct rpc_filelist files[] = {
                .name = "nfsd",
                .mode = S_IFDIR | S_IRUGO | S_IXUGO,
        },
+       [RPCAUTH_gssd] = {
+               .name = "gssd",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
 };
 
 /*
@@ -1208,13 +1211,24 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
 }
 EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
 
-void rpc_pipefs_init_net(struct net *net)
+int rpc_pipefs_init_net(struct net *net)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
+       sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
+       if (IS_ERR(sn->gssd_dummy))
+               return PTR_ERR(sn->gssd_dummy);
+
        mutex_init(&sn->pipefs_sb_lock);
-       sn->gssd_running = 1;
        sn->pipe_version = -1;
+       return 0;
+}
+
+void rpc_pipefs_exit_net(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       rpc_destroy_pipe_data(sn->gssd_dummy);
 }
 
 /*
@@ -1244,11 +1258,134 @@ void rpc_put_sb_net(const struct net *net)
 }
 EXPORT_SYMBOL_GPL(rpc_put_sb_net);
 
+static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
+       [0] = {
+               .name = "clntXX",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
+};
+
+static ssize_t
+dummy_downcall(struct file *filp, const char __user *src, size_t len)
+{
+       return -EINVAL;
+}
+
+static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
+       .upcall         = rpc_pipe_generic_upcall,
+       .downcall       = dummy_downcall,
+};
+
+/*
+ * Here we present a bogus "info" file to keep rpc.gssd happy. We don't expect
+ * that it will ever use this info to handle an upcall, but rpc.gssd expects
+ * that this file will be there and have a certain format.
+ */
+static int
+rpc_show_dummy_info(struct seq_file *m, void *v)
+{
+       seq_printf(m, "RPC server: %s\n", utsname()->nodename);
+       seq_printf(m, "service: foo (1) version 0\n");
+       seq_printf(m, "address: 127.0.0.1\n");
+       seq_printf(m, "protocol: tcp\n");
+       seq_printf(m, "port: 0\n");
+       return 0;
+}
+
+static int
+rpc_dummy_info_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rpc_show_dummy_info, NULL);
+}
+
+static const struct file_operations rpc_dummy_info_operations = {
+       .owner          = THIS_MODULE,
+       .open           = rpc_dummy_info_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const struct rpc_filelist gssd_dummy_info_file[] = {
+       [0] = {
+               .name = "info",
+               .i_fop = &rpc_dummy_info_operations,
+               .mode = S_IFREG | S_IRUSR,
+       },
+};
+
+/**
+ * rpc_gssd_dummy_populate - create a dummy gssd pipe
+ * @root:      root of the rpc_pipefs filesystem
+ * @pipe_data: pipe data created when netns is initialized
+ *
+ * Create a dummy set of directories and a pipe that gssd can hold open to
+ * indicate that it is up and running.
+ */
+static struct dentry *
+rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
+{
+       int ret = 0;
+       struct dentry *gssd_dentry;
+       struct dentry *clnt_dentry = NULL;
+       struct dentry *pipe_dentry = NULL;
+       struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
+                                 strlen(files[RPCAUTH_gssd].name));
+
+       /* We should never get this far if "gssd" doesn't exist */
+       gssd_dentry = d_hash_and_lookup(root, &q);
+       if (!gssd_dentry)
+               return ERR_PTR(-ENOENT);
+
+       ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
+       if (ret) {
+               pipe_dentry = ERR_PTR(ret);
+               goto out;
+       }
+
+       q.name = gssd_dummy_clnt_dir[0].name;
+       q.len = strlen(gssd_dummy_clnt_dir[0].name);
+       clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
+       if (!clnt_dentry) {
+               pipe_dentry = ERR_PTR(-ENOENT);
+               goto out;
+       }
+
+       ret = rpc_populate(clnt_dentry, gssd_dummy_info_file, 0, 1, NULL);
+       if (ret) {
+               __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
+               pipe_dentry = ERR_PTR(ret);
+               goto out;
+       }
+
+       pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
+       if (IS_ERR(pipe_dentry)) {
+               __rpc_depopulate(clnt_dentry, gssd_dummy_info_file, 0, 1);
+               __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
+       }
+out:
+       dput(clnt_dentry);
+       dput(gssd_dentry);
+       return pipe_dentry;
+}
+
+static void
+rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry)
+{
+       struct dentry *clnt_dir = pipe_dentry->d_parent;
+       struct dentry *gssd_dir = clnt_dir->d_parent;
+
+       __rpc_rmpipe(clnt_dir->d_inode, pipe_dentry);
+       __rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1);
+       __rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1);
+       dput(pipe_dentry);
+}
+
 static int
 rpc_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *inode;
-       struct dentry *root;
+       struct dentry *root, *gssd_dentry;
        struct net *net = data;
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        int err;
@@ -1266,6 +1403,13 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                return -ENOMEM;
+
+       gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
+       if (IS_ERR(gssd_dentry)) {
+               __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
+               return PTR_ERR(gssd_dentry);
+       }
+
        dprintk("RPC:       sending pipefs MOUNT notification for net %p%s\n",
                net, NET_NAME(net));
        mutex_lock(&sn->pipefs_sb_lock);
@@ -1280,6 +1424,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 
 err_depopulate:
+       rpc_gssd_dummy_depopulate(gssd_dentry);
        blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_UMOUNT,
                                           sb);
@@ -1289,6 +1434,16 @@ err_depopulate:
        return err;
 }
 
+bool
+gssd_running(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       struct rpc_pipe *pipe = sn->gssd_dummy;
+
+       return pipe->nreaders || pipe->nwriters;
+}
+EXPORT_SYMBOL_GPL(gssd_running);
+
 static struct dentry *
 rpc_mount(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *data)
index 3d6498af9adc1a1035005c735ee932de6488bee3..cd30120de9e4eb7ba413135dd2eb690311d784cb 100644 (file)
@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(struct net *net)
        if (err)
                goto err_unixgid;
 
-       rpc_pipefs_init_net(net);
+       err = rpc_pipefs_init_net(net);
+       if (err)
+               goto err_pipefs;
+
        INIT_LIST_HEAD(&sn->all_clients);
        spin_lock_init(&sn->rpc_client_lock);
        spin_lock_init(&sn->rpcb_clnt_lock);
        return 0;
 
+err_pipefs:
+       unix_gid_cache_destroy(net);
 err_unixgid:
        ip_map_cache_destroy(net);
 err_ipmap:
@@ -60,6 +65,7 @@ err_proc:
 
 static __net_exit void sunrpc_exit_net(struct net *net)
 {
+       rpc_pipefs_exit_net(net);
        unix_gid_cache_destroy(net);
        ip_map_cache_destroy(net);
        rpc_proc_exit(net);
index 1750048130a7c0d305a51c87c38d539ee3001fd7..7d4df99f761faa27de43af1b27640e412a3dc8a0 100644 (file)
@@ -749,6 +749,11 @@ static void xprt_connect_status(struct rpc_task *task)
        }
 
        switch (task->tk_status) {
+       case -ECONNREFUSED:
+       case -ECONNRESET:
+       case -ECONNABORTED:
+       case -ENETUNREACH:
+       case -EHOSTUNREACH:
        case -EAGAIN:
                dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid);
                break;
index 75b045e1cd50b00096a3a2ec938c2f82423dffce..2a7ca8ffe83a9ad47576959b30f9664cc3996b0a 100644 (file)
@@ -257,6 +257,7 @@ struct sock_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
+       void                    (*old_error_report)(struct sock *);
 };
 
 /*
@@ -274,6 +275,11 @@ struct sock_xprt {
  */
 #define TCP_RPC_REPLY          (1UL << 6)
 
+static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
+{
+       return (struct rpc_xprt *) sk->sk_user_data;
+}
+
 static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
 {
        return (struct sockaddr *) &xprt->addr;
@@ -799,6 +805,7 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
+       transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -806,6 +813,34 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
+       sk->sk_error_report = transport->old_error_report;
+}
+
+/**
+ * xs_error_report - callback to handle TCP socket state errors
+ * @sk: socket
+ *
+ * Note: we don't call sock_error() since there may be a rpc_task
+ * using the socket, and so we don't want to clear sk->sk_err.
+ */
+static void xs_error_report(struct sock *sk)
+{
+       struct rpc_xprt *xprt;
+       int err;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       if (!(xprt = xprt_from_sock(sk)))
+               goto out;
+
+       err = -sk->sk_err;
+       if (err == 0)
+               goto out;
+       dprintk("RPC:       xs_error_report client %p, error=%d...\n",
+                       xprt, -err);
+       trace_rpc_socket_error(xprt, sk->sk_socket, err);
+       xprt_wake_pending_tasks(xprt, err);
+ out:
+       read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -885,11 +920,6 @@ static void xs_destroy(struct rpc_xprt *xprt)
        module_put(THIS_MODULE);
 }
 
-static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
-{
-       return (struct rpc_xprt *) sk->sk_user_data;
-}
-
 static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
 {
        struct xdr_skb_reader desc = {
@@ -1869,6 +1899,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
+               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_clear_connected(xprt);
@@ -2146,6 +2177,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
+               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
index 1dbd6d1cd1b5f45d62a86d5faa0d8f92eb4227f4..0ea2a1e24ade493ed22c6b817c91a07736b11563 100755 (executable)
@@ -2665,6 +2665,15 @@ sub process {
                                $herecurr);
                }
 
+# check for function declarations without arguments like "int foo()"
+               if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
+                       if (ERROR("FUNCTION_WITHOUT_ARGS",
+                                 "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$linenr - 1] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
+                       }
+               }
+
 # check for uses of DEFINE_PCI_DEVICE_TABLE
                if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
                        if (WARN("DEFINE_PCI_DEVICE_TABLE",
index 17855761e6b77c4c5c13600b76c8cf95fcb82c00..40610984a1b54b06c579f953dabeb5ddb1304525 100644 (file)
@@ -584,12 +584,16 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
                if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 ||
                    strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 ||
                    strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 ||
-                   strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0)
+                   strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0 ||
+                   strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
+                   strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
                        return 1;
        if (info->hdr->e_machine == EM_PPC64)
                /* Special register function linked on all modules during final link of .ko */
                if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 ||
-                   strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0)
+                   strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 ||
+                   strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 ||
+                   strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0)
                        return 1;
        /* Do not ignore this symbol */
        return 0;