Merge branch 'for-arm-soc/virt/mach' of git://git.kernel.org/pub/scm/linux/kernel...
authorOlof Johansson <olof@lixom.net>
Mon, 11 Feb 2013 17:21:51 +0000 (09:21 -0800)
committerOlof Johansson <olof@lixom.net>
Mon, 11 Feb 2013 17:22:09 +0000 (09:22 -0800)
From Will Deacon, this lays the foundation for a basic virtualzed machine type.

* 'for-arm-soc/virt/mach' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux:
  ARM: mach-virt: add SMP support using PSCI
  ARM: Dummy Virtual Machine platform support

Signed-off-by: Olof Johansson <olof@lixom.net>
817 files changed:
Documentation/hid/hid-sensor.txt [changed mode: 0755->0644]
Documentation/kernel-parameters.txt
Documentation/virtual/kvm/api.txt
Documentation/x86/boot.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/include/asm/cputype.h
arch/arm/include/asm/idmap.h
arch/arm/include/asm/kvm_arm.h [new file with mode: 0644]
arch/arm/include/asm/kvm_asm.h [new file with mode: 0644]
arch/arm/include/asm/kvm_coproc.h [new file with mode: 0644]
arch/arm/include/asm/kvm_emulate.h [new file with mode: 0644]
arch/arm/include/asm/kvm_host.h [new file with mode: 0644]
arch/arm/include/asm/kvm_mmio.h [new file with mode: 0644]
arch/arm/include/asm/kvm_mmu.h [new file with mode: 0644]
arch/arm/include/asm/kvm_psci.h [new file with mode: 0644]
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mach/time.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable-3level-hwdef.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/pgtable.h
arch/arm/include/uapi/asm/kvm.h [new file with mode: 0644]
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/perf_event_v6.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/perf_event_xscale.c
arch/arm/kernel/time.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/kvm/Kconfig [new file with mode: 0644]
arch/arm/kvm/Makefile [new file with mode: 0644]
arch/arm/kvm/arm.c [new file with mode: 0644]
arch/arm/kvm/coproc.c [new file with mode: 0644]
arch/arm/kvm/coproc.h [new file with mode: 0644]
arch/arm/kvm/coproc_a15.c [new file with mode: 0644]
arch/arm/kvm/emulate.c [new file with mode: 0644]
arch/arm/kvm/guest.c [new file with mode: 0644]
arch/arm/kvm/init.S [new file with mode: 0644]
arch/arm/kvm/interrupts.S [new file with mode: 0644]
arch/arm/kvm/interrupts_head.S [new file with mode: 0644]
arch/arm/kvm/mmio.c [new file with mode: 0644]
arch/arm/kvm/mmu.c [new file with mode: 0644]
arch/arm/kvm/psci.c [new file with mode: 0644]
arch/arm/kvm/reset.c [new file with mode: 0644]
arch/arm/kvm/trace.h [new file with mode: 0644]
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/at91x40_time.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-eb01.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-flexibity.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200-dt.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-rsi-ews.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a926x.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/generic.h
arch/arm/mach-bcm/board_bcm.c
arch/arm/mach-bcm2835/bcm2835.c
arch/arm/mach-clps711x/board-autcpu12.c
arch/arm/mach-clps711x/board-cdb89712.c
arch/arm/mach-clps711x/board-clep7312.c
arch/arm/mach-clps711x/board-edb7211.c
arch/arm/mach-clps711x/board-fortunet.c
arch/arm/mach-clps711x/board-p720t.c
arch/arm/mach-clps711x/common.c
arch/arm/mach-clps711x/common.h
arch/arm/mach-cns3xxx/cns3420vb.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/core.h
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/board-tnetv107x-evm.c
arch/arm/mach-davinci/da8xx-dt.c
arch/arm/mach-davinci/include/mach/common.h
arch/arm/mach-davinci/time.c
arch/arm/mach-dove/cm-a510.c
arch/arm/mach-dove/common.c
arch/arm/mach-dove/common.h
arch/arm/mach-dove/dove-db-setup.c
arch/arm/mach-ebsa110/core.c
arch/arm/mach-ep93xx/adssphere.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/gesbc9312.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/micro9.c
arch/arm/mach-ep93xx/simone.c
arch/arm/mach-ep93xx/snappercl15.c
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-ep93xx/vision_ep9307.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/mct.c
arch/arm/mach-footbridge/cats-hw.c
arch/arm/mach-footbridge/common.h
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/ebsa285.c
arch/arm/mach-footbridge/isa-timer.c
arch/arm/mach-footbridge/netwinder-hw.c
arch/arm/mach-footbridge/personal.c
arch/arm/mach-gemini/board-nas4220b.c
arch/arm/mach-gemini/board-rut1xx.c
arch/arm/mach-gemini/board-wbd111.c
arch/arm/mach-gemini/board-wbd222.c
arch/arm/mach-h720x/common.c
arch/arm/mach-h720x/common.h
arch/arm/mach-h720x/cpu-h7201.c
arch/arm/mach-h720x/cpu-h7202.c
arch/arm/mach-h720x/h7201-eval.c
arch/arm/mach-h720x/h7202-eval.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/epit.c
arch/arm/mach-imx/imx25-dt.c
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/imx31-dt.c
arch/arm/mach-imx/imx51-dt.c
arch/arm/mach-imx/mach-apf9328.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-bug.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-cpuimx51sd.c
arch/arm/mach-imx/mach-eukrea_cpuimx25.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx27ipcam.c
arch/arm/mach-imx/mach-imx27lite.c
arch/arm/mach-imx/mach-imx53.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-kzm_arm11_01.c
arch/arm/mach-imx/mach-mx1ads.c
arch/arm/mach-imx/mach-mx21ads.c
arch/arm/mach-imx/mach-mx25_3ds.c
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx27ads.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-mx50_rdp.c
arch/arm/mach-imx/mach-mx51_3ds.c
arch/arm/mach-imx/mach-mx51_babbage.c
arch/arm/mach-imx/mach-mxt_td60.c
arch/arm/mach-imx/mach-pca100.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mach-qong.c
arch/arm/mach-imx/mach-scb9328.c
arch/arm/mach-imx/mach-vpr200.c
arch/arm/mach-imx/time.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/iq81340mc.c
arch/arm/mach-iop13xx/iq81340sc.c
arch/arm/mach-iop32x/em7210.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/iq31244.c
arch/arm/mach-iop32x/iq80321.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-iop33x/iq80331.c
arch/arm/mach-iop33x/iq80332.c
arch/arm/mach-ixp4xx/avila-setup.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/coyote-setup.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/fsg-setup.c
arch/arm/mach-ixp4xx/gateway7001-setup.c
arch/arm/mach-ixp4xx/goramo_mlr.c
arch/arm/mach-ixp4xx/gtwx5715-setup.c
arch/arm/mach-ixp4xx/include/mach/platform.h
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-ixp4xx/omixp-setup.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-ixp4xx/wg302v2-setup.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/common.h
arch/arm/mach-kirkwood/d2net_v2-setup.c
arch/arm/mach-kirkwood/db88f6281-bp-setup.c
arch/arm/mach-kirkwood/dockstar-setup.c
arch/arm/mach-kirkwood/guruplug-setup.c
arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
arch/arm/mach-kirkwood/netspace_v2-setup.c
arch/arm/mach-kirkwood/netxbig_v2-setup.c
arch/arm/mach-kirkwood/openrd-setup.c
arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
arch/arm/mach-kirkwood/rd88f6281-setup.c
arch/arm/mach-kirkwood/sheevaplug-setup.c
arch/arm/mach-kirkwood/t5325-setup.c
arch/arm/mach-kirkwood/ts219-setup.c
arch/arm/mach-kirkwood/ts41x-setup.c
arch/arm/mach-ks8695/board-acs5k.c
arch/arm/mach-ks8695/board-dsm320.c
arch/arm/mach-ks8695/board-micrel.c
arch/arm/mach-ks8695/board-og.c
arch/arm/mach-ks8695/board-sg.c
arch/arm/mach-ks8695/generic.h
arch/arm/mach-ks8695/time.c
arch/arm/mach-lpc32xx/common.h
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-lpc32xx/timer.c
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/avengers_lite.c
arch/arm/mach-mmp/brownstone.c
arch/arm/mach-mmp/common.h
arch/arm/mach-mmp/flint.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/mmp2.h
arch/arm/mach-mmp/include/mach/pxa168.h
arch/arm/mach-mmp/include/mach/pxa910.h
arch/arm/mach-mmp/jasper.c
arch/arm/mach-mmp/mmp-dt.c
arch/arm/mach-mmp/mmp2-dt.c
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/pxa910.c
arch/arm/mach-mmp/tavorevb.c
arch/arm/mach-mmp/teton_bga.c
arch/arm/mach-mmp/time.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-msm/board-dt-8660.c
arch/arm/mach-msm/board-dt-8960.c
arch/arm/mach-msm/board-halibut.c
arch/arm/mach-msm/board-mahimahi.c
arch/arm/mach-msm/board-msm7x30.c
arch/arm/mach-msm/board-qsd8x50.c
arch/arm/mach-msm/board-sapphire.c
arch/arm/mach-msm/board-trout.c
arch/arm/mach-msm/common.h
arch/arm/mach-msm/timer.c
arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mv78xx0/common.h
arch/arm/mach-mv78xx0/db78x00-bp-setup.c
arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
arch/arm/mach-mvebu/armada-370-xp.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/timer.c
arch/arm/mach-netx/generic.h
arch/arm/mach-netx/nxdb500.c
arch/arm/mach-netx/nxdkn.c
arch/arm/mach-netx/nxeb500hmi.c
arch/arm/mach-netx/time.c
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-fsample.c
arch/arm/mach-omap1/board-generic.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-palmtt.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-perseus2.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/common.h
arch/arm/mach-omap1/time.c
arch/arm/mach-omap1/timer32k.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-3630sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-am3517crane.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rm680.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/board-ti8168evm.c
arch/arm/mach-omap2/board-zoom.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/timer.c
arch/arm/mach-orion5x/board-dt.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/common.h
arch/arm/mach-orion5x/d2net-setup.c
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/kurobox_pro-setup.c
arch/arm/mach-orion5x/ls-chl-setup.c
arch/arm/mach-orion5x/ls_hgl-setup.c
arch/arm/mach-orion5x/lsmini-setup.c
arch/arm/mach-orion5x/mss2-setup.c
arch/arm/mach-orion5x/mv2120-setup.c
arch/arm/mach-orion5x/net2big-setup.c
arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
arch/arm/mach-orion5x/terastation_pro2-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-orion5x/ts409-setup.c
arch/arm/mach-orion5x/ts78xx-setup.c
arch/arm/mach-orion5x/wnr854t-setup.c
arch/arm/mach-orion5x/wrt350n-v2-setup.c
arch/arm/mach-picoxcell/common.c
arch/arm/mach-picoxcell/common.h
arch/arm/mach-prima2/common.c
arch/arm/mach-prima2/common.h
arch/arm/mach-prima2/timer.c
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/cm-x2xx.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pcm027.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa-dt.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/time.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-realview/include/mach/irqs-eb.h
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-realview/realview_pba8.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mach-rpc/riscpc.c
arch/arm/mach-rpc/time.c
arch/arm/mach-s3c24xx/mach-amlm5900.c
arch/arm/mach-s3c24xx/mach-anubis.c
arch/arm/mach-s3c24xx/mach-at2440evb.c
arch/arm/mach-s3c24xx/mach-bast.c
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-jive.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-n30.c
arch/arm/mach-s3c24xx/mach-nexcoder.c
arch/arm/mach-s3c24xx/mach-osiris.c
arch/arm/mach-s3c24xx/mach-otom.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/mach-rx3715.c
arch/arm/mach-s3c24xx/mach-smdk2410.c
arch/arm/mach-s3c24xx/mach-smdk2413.c
arch/arm/mach-s3c24xx/mach-smdk2416.c
arch/arm/mach-s3c24xx/mach-smdk2440.c
arch/arm/mach-s3c24xx/mach-smdk2443.c
arch/arm/mach-s3c24xx/mach-tct_hammer.c
arch/arm/mach-s3c24xx/mach-vr1000.c
arch/arm/mach-s3c24xx/mach-vstms.c
arch/arm/mach-s3c64xx/mach-anw6410.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-ncp.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s3c64xx/mach-smartq5.c
arch/arm/mach-s3c64xx/mach-smartq7.c
arch/arm/mach-s3c64xx/mach-smdk6400.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkc110.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-s5pv210/mach-torbreck.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/badge4.c
arch/arm/mach-sa1100/cerf.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/generic.h
arch/arm/mach-sa1100/h3100.c
arch/arm/mach-sa1100/h3600.c
arch/arm/mach-sa1100/hackkit.c
arch/arm/mach-sa1100/jornada720.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/nanoengine.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-sa1100/shannon.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mach-sa1100/time.c
arch/arm/mach-shark/core.c
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bonito.c
arch/arm/mach-shmobile/board-kota2.c
arch/arm/mach-shmobile/board-kzm9d.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/include/mach/common.h
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/timer.c
arch/arm/mach-socfpga/socfpga.c
arch/arm/mach-spear13xx/include/mach/generic.h
arch/arm/mach-spear13xx/spear1310.c
arch/arm/mach-spear13xx/spear1340.c
arch/arm/mach-spear13xx/spear13xx.c
arch/arm/mach-spear3xx/include/mach/generic.h
arch/arm/mach-spear3xx/spear300.c
arch/arm/mach-spear3xx/spear310.c
arch/arm/mach-spear3xx/spear320.c
arch/arm/mach-spear3xx/spear3xx.c
arch/arm/mach-spear6xx/spear6xx.c
arch/arm/mach-sunxi/sunxi.c
arch/arm/mach-tegra/board-dt-tegra20.c
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/timer.c
arch/arm/mach-u300/core.c
arch/arm/mach-u300/timer.c
arch/arm/mach-u300/timer.h
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/include/mach/setup.h
arch/arm/mach-ux500/timer.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/core.h
arch/arm/mach-versatile/versatile_ab.c
arch/arm/mach-versatile/versatile_dt.c
arch/arm/mach-versatile/versatile_pb.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-vt8500/Kconfig
arch/arm/mach-vt8500/Makefile
arch/arm/mach-vt8500/common.h
arch/arm/mach-vt8500/vt8500.c
arch/arm/mach-w90x900/mach-nuc910evb.c
arch/arm/mach-w90x900/mach-nuc950evb.c
arch/arm/mach-w90x900/mach-nuc960evb.c
arch/arm/mach-w90x900/nuc9xx.h
arch/arm/mach-w90x900/time.c
arch/arm/mach-zynq/common.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/idmap.c
arch/arm/mm/mmu.c
arch/arm/plat-iop/time.c
arch/arm/plat-orion/time.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/s5p-time.h
arch/arm/plat-samsung/s5p-time.c
arch/arm/plat-samsung/time.c
arch/arm/plat-spear/time.c
arch/avr32/include/asm/dma-mapping.h
arch/blackfin/include/asm/dma-mapping.h
arch/blackfin/kernel/time.c
arch/c6x/include/asm/dma-mapping.h
arch/cris/arch-v10/kernel/time.c
arch/cris/include/asm/dma-mapping.h
arch/cris/kernel/time.c
arch/frv/include/asm/dma-mapping.h
arch/m32r/kernel/time.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/config.c
arch/m68k/atari/time.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/config.c
arch/m68k/hp300/time.c
arch/m68k/hp300/time.h
arch/m68k/include/asm/dma-mapping.h
arch/m68k/include/asm/machdep.h
arch/m68k/kernel/setup_mm.c
arch/m68k/kernel/time.c
arch/m68k/mac/config.c
arch/m68k/mac/via.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/config.c
arch/m68k/sun3/intersil.c
arch/m68k/sun3x/config.c
arch/m68k/sun3x/time.c
arch/m68k/sun3x/time.h
arch/mips/bcm47xx/Kconfig
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/include/asm/dsp.h
arch/mips/include/asm/inst.h
arch/mips/include/asm/mach-pnx833x/war.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/uapi/asm/Kbuild
arch/mips/include/uapi/asm/break.h [moved from arch/mips/include/asm/break.h with 100% similarity]
arch/mips/kernel/ftrace.c
arch/mips/kernel/mcount.S
arch/mips/kernel/vpe.c
arch/mips/lantiq/irq.c
arch/mips/lib/delay.c
arch/mips/mm/ioremap.c
arch/mips/mm/mmap.c
arch/mips/netlogic/xlr/setup.c
arch/mips/pci/pci-ar71xx.c
arch/mips/pci/pci-ar724x.c
arch/mn10300/include/asm/dma-mapping.h
arch/parisc/include/asm/dma-mapping.h
arch/powerpc/mm/hash_low_64.S
arch/x86/ia32/ia32entry.S
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/tools/insn_sanity.c
arch/xtensa/include/asm/dma-mapping.h
block/genhd.c
drivers/atm/iphase.h
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon_nflash.c
drivers/bcma/driver_gpio.c
drivers/bcma/main.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_state.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkfront.c
drivers/char/virtio_console.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/bcm2835_timer.c
drivers/clocksource/clksrc-of.c [new file with mode: 0644]
drivers/clocksource/cs5535-clockevt.c
drivers/clocksource/dw_apb_timer_of.c
drivers/clocksource/nomadik-mtu.c
drivers/clocksource/sunxi_timer.c
drivers/clocksource/tcb_clksrc.c
drivers/clocksource/vt8500_timer.c [moved from arch/arm/mach-vt8500/timer.c with 94% similarity]
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/infiniband/hw/qib/qib_qp.c
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/irqchip/irq-gic.c
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/media/radio/radio-keene.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/mtd/devices/Kconfig
drivers/mtd/maps/physmap_of.c
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/nand_base.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/c_can/c_can.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/tun.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/pinctrl-sirf.c
drivers/regulator/max77686.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/of_regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-vt8500.c
drivers/ssb/driver_gpio.c
drivers/ssb/main.c
drivers/ssb/ssb_private.h
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-timer.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/storage/usual-tables.c
drivers/vhost/net.c
drivers/vhost/tcm_vhost.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/xen/events.c
drivers/xen/xen-pciback/pciback_ops.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_map.c
fs/btrfs/file.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/scrub.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/dlm/user.c
fs/nfs/namespace.c
fs/nfs/nfs4client.c
fs/nfs/nfs4state.c
fs/nfs/super.c
fs/nilfs2/ioctl.c
include/asm-generic/vmlinux.lds.h
include/linux/bcm2835_timer.h
include/linux/clocksource.h
include/linux/dw_apb_timer.h
include/linux/llist.h
include/linux/memcontrol.h
include/linux/mmu_notifier.h
include/linux/sunxi_timer.h
include/linux/time.h
include/linux/usb.h
include/linux/usb/hcd.h
include/linux/usb/usbnet.h
include/linux/vt8500_timer.h [new file with mode: 0644]
include/net/transp_v6.h
include/uapi/linux/kvm.h
include/uapi/linux/usb/ch9.h
kernel/events/core.c
kernel/rcutree_plugin.h
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/time/clockevents.c
kernel/time/timekeeping.c
lib/digsig.c
mm/huge_memory.c
mm/hugetlb.c
mm/migrate.c
mm/mmap.c
net/bluetooth/hci_conn.c
net/bluetooth/smp.c
net/core/pktgen.c
net/core/skbuff.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_gre.c
net/ipv6/ipv6_sockglue.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip6.c
net/l2tp/l2tp_ppp.c
net/openvswitch/vport-netdev.c
net/packet/af_packet.c
net/sched/sch_netem.c
net/sctp/auth.c
net/sctp/endpointola.c
net/sctp/socket.c
net/sunrpc/sched.c
net/sunrpc/svcsock.c
net/wireless/scan.c
samples/seccomp/Makefile
scripts/checkpatch.pl
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm.c
sound/soc/fsl/imx-pcm.h
tools/vm/.gitignore [new file with mode: 0644]

old mode 100755 (executable)
new mode 100644 (file)
index 363e348..6c72381 100644 (file)
@@ -2438,7 +2438,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        real-time workloads.  It can also improve energy
                        efficiency for asymmetric multiprocessors.
 
-       rcu_nocbs_poll  [KNL,BOOT]
+       rcu_nocb_poll   [KNL,BOOT]
                        Rather than requiring that offloaded CPUs
                        (specified by rcu_nocbs= above) explicitly
                        awaken the corresponding "rcuoN" kthreads,
index a4df553..c25439a 100644 (file)
@@ -293,7 +293,7 @@ kvm_run' (see below).
 4.11 KVM_GET_REGS
 
 Capability: basic
-Architectures: all
+Architectures: all except ARM
 Type: vcpu ioctl
 Parameters: struct kvm_regs (out)
 Returns: 0 on success, -1 on error
@@ -314,7 +314,7 @@ struct kvm_regs {
 4.12 KVM_SET_REGS
 
 Capability: basic
-Architectures: all
+Architectures: all except ARM
 Type: vcpu ioctl
 Parameters: struct kvm_regs (in)
 Returns: 0 on success, -1 on error
@@ -600,7 +600,7 @@ struct kvm_fpu {
 4.24 KVM_CREATE_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
-Architectures: x86, ia64
+Architectures: x86, ia64, ARM
 Type: vm ioctl
 Parameters: none
 Returns: 0 on success, -1 on error
@@ -608,21 +608,39 @@ Returns: 0 on success, -1 on error
 Creates an interrupt controller model in the kernel.  On x86, creates a virtual
 ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
 local APIC.  IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
-only go to the IOAPIC.  On ia64, a IOSAPIC is created.
+only go to the IOAPIC.  On ia64, a IOSAPIC is created. On ARM, a GIC is
+created.
 
 
 4.25 KVM_IRQ_LINE
 
 Capability: KVM_CAP_IRQCHIP
-Architectures: x86, ia64
+Architectures: x86, ia64, arm
 Type: vm ioctl
 Parameters: struct kvm_irq_level
 Returns: 0 on success, -1 on error
 
 Sets the level of a GSI input to the interrupt controller model in the kernel.
-Requires that an interrupt controller model has been previously created with
-KVM_CREATE_IRQCHIP.  Note that edge-triggered interrupts require the level
-to be set to 1 and then back to 0.
+On some architectures it is required that an interrupt controller model has
+been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
+interrupts require the level to be set to 1 and then back to 0.
+
+ARM can signal an interrupt either at the CPU level, or at the in-kernel irqchip
+(GIC), and for in-kernel irqchip can tell the GIC to use PPIs designated for
+specific cpus.  The irq field is interpreted like this:
+
+ Â bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
+  field: | irq_type  | vcpu_index |     irq_id     |
+
+The irq_type field has the following values:
+- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
+- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
+               (the vcpu_index field is ignored)
+- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
+
+(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
+
+In both cases, level is used to raise/lower the line.
 
 struct kvm_irq_level {
        union {
@@ -1775,6 +1793,27 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_VPA_DTL   | 128
   PPC   | KVM_REG_PPC_EPCR     | 32
 
+ARM registers are mapped using the lower 32 bits.  The upper 16 of that
+is the register group type, or coprocessor number:
+
+ARM core registers have the following id bit patterns:
+  0x4002 0000 0010 <index into the kvm_regs struct:16>
+
+ARM 32-bit CP15 registers have the following id bit patterns:
+  0x4002 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
+
+ARM 64-bit CP15 registers have the following id bit patterns:
+  0x4003 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
+
+ARM CCSIDR registers are demultiplexed by CSSELR value:
+  0x4002 0000 0011 00 <csselr:8>
+
+ARM 32-bit VFP control registers have the following id bit patterns:
+  0x4002 0000 0012 1 <regno:12>
+
+ARM 64-bit FP registers have the following id bit patterns:
+  0x4002 0000 0012 0 <regno:12>
+
 4.69 KVM_GET_ONE_REG
 
 Capability: KVM_CAP_ONE_REG
@@ -2127,6 +2166,50 @@ written, then `n_invalid' invalid entries, invalidating any previously
 valid entries found.
 
 
+4.77 KVM_ARM_VCPU_INIT
+
+Capability: basic
+Architectures: arm
+Type: vcpu ioctl
+Parameters: struct struct kvm_vcpu_init (in)
+Returns: 0 on success; -1 on error
+Errors:
+ Â EINVAL: Â Â Â the target is unknown, or the combination of features is invalid.
+ Â ENOENT: Â Â Â a features bit specified is unknown.
+
+This tells KVM what type of CPU to present to the guest, and what
+optional features it should have. Â This will cause a reset of the cpu
+registers to their initial values. Â If this is not called, KVM_RUN will
+return ENOEXEC for that vcpu.
+
+Note that because some registers reflect machine topology, all vcpus
+should be created before this ioctl is invoked.
+
+Possible features:
+       - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
+         Depends on KVM_CAP_ARM_PSCI.
+
+
+4.78 KVM_GET_REG_LIST
+
+Capability: basic
+Architectures: arm
+Type: vcpu ioctl
+Parameters: struct kvm_reg_list (in/out)
+Returns: 0 on success; -1 on error
+Errors:
+ Â E2BIG: Â Â Â Â the reg index list is too big to fit in the array specified by
+ Â Â Â Â Â Â Â Â Â Â Â Â the user (the number required will be written into n).
+
+struct kvm_reg_list {
+       __u64 n; /* number of registers in reg[] */
+       __u64 reg[0];
+};
+
+This ioctl returns the guest registers that are supported for the
+KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
+
+
 5. The kvm_run structure
 ------------------------
 
index 3edb4c2..e540fd6 100644 (file)
@@ -57,7 +57,7 @@ Protocol 2.10:        (Kernel 2.6.31) Added a protocol for relaxed alignment
 Protocol 2.11: (Kernel 3.6) Added a field for offset of EFI handover
                protocol entry point.
 
-Protocol 2.12: (Kernel 3.9) Added the xloadflags field and extension fields
+Protocol 2.12: (Kernel 3.8) Added the xloadflags field and extension fields
                to struct boot_params for for loading bzImage and ramdisk
                above 4G in 64bit.
 
index 43dbae1..38633ee 100644 (file)
@@ -1489,7 +1489,7 @@ AVR32 ARCHITECTURE
 M:     Haavard Skinnemoen <hskinnemoen@gmail.com>
 M:     Hans-Christian Egtvedt <egtvedt@samfundet.no>
 W:     http://www.atmel.com/products/AVR32/
-W:     http://avr32linux.org/
+W:     http://mirror.egtvedt.no/avr32linux.org/
 W:     http://avrfreaks.net/
 S:     Maintained
 F:     arch/avr32/
@@ -4482,6 +4482,15 @@ F:       arch/s390/include/asm/kvm*
 F:     arch/s390/kvm/
 F:     drivers/s390/kvm/
 
+KERNEL VIRTUAL MACHINE (KVM) FOR ARM
+M:     Christoffer Dall <cdall@cs.columbia.edu>
+L:     kvmarm@lists.cs.columbia.edu
+W:     http://systems.cs.columbia.edu/projects/kvm-arm
+S:     Maintained
+F:     arch/arm/include/uapi/asm/kvm*
+F:     arch/arm/include/asm/kvm*
+F:     arch/arm/kvm/
+
 KEXEC
 M:     Eric Biederman <ebiederm@xmission.com>
 W:     http://kernel.org/pub/linux/utils/kernel/kexec/
index 2d3c92c..08ef9bd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 8
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
-NAME = Terrified Chipmunk
+EXTRAVERSION = -rc7
+NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index b7562a7..441eda1 100644 (file)
@@ -2336,3 +2336,5 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+source "arch/arm/kvm/Kconfig"
index ea4f481..3b82b36 100644 (file)
@@ -253,6 +253,7 @@ core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)     += $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)             += arch/arm/vfp/
 core-$(CONFIG_XEN)             += arch/arm/xen/
+core-$(CONFIG_KVM_ARM_HOST)    += arch/arm/kvm/
 
 # If we have a machine-specific directory, then include it in the build.
 core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
index a59dcb5..ad41ec2 100644 (file)
@@ -64,6 +64,24 @@ extern unsigned int processor_id;
 #define read_cpuid_ext(reg) 0
 #endif
 
+#define ARM_CPU_IMP_ARM                        0x41
+#define ARM_CPU_IMP_INTEL              0x69
+
+#define ARM_CPU_PART_ARM1136           0xB360
+#define ARM_CPU_PART_ARM1156           0xB560
+#define ARM_CPU_PART_ARM1176           0xB760
+#define ARM_CPU_PART_ARM11MPCORE       0xB020
+#define ARM_CPU_PART_CORTEX_A8         0xC080
+#define ARM_CPU_PART_CORTEX_A9         0xC090
+#define ARM_CPU_PART_CORTEX_A5         0xC050
+#define ARM_CPU_PART_CORTEX_A15                0xC0F0
+#define ARM_CPU_PART_CORTEX_A7         0xC070
+
+#define ARM_CPU_XSCALE_ARCH_MASK       0xe000
+#define ARM_CPU_XSCALE_ARCH_V1         0x2000
+#define ARM_CPU_XSCALE_ARCH_V2         0x4000
+#define ARM_CPU_XSCALE_ARCH_V3         0x6000
+
 /*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
@@ -74,6 +92,21 @@ static inline unsigned int __attribute_const__ read_cpuid_id(void)
        return read_cpuid(CPUID_ID);
 }
 
+static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
+{
+       return (read_cpuid_id() & 0xFF000000) >> 24;
+}
+
+static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
+{
+       return read_cpuid_id() & 0xFFF0;
+}
+
+static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void)
+{
+       return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK;
+}
+
 static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
 {
        return read_cpuid(CPUID_CACHETYPE);
index bf863ed..1a66f90 100644 (file)
@@ -8,6 +8,7 @@
 #define __idmap __section(.idmap.text) noinline notrace
 
 extern pgd_t *idmap_pgd;
+extern pgd_t *hyp_pgd;
 
 void setup_mm_for_reboot(void);
 
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
new file mode 100644 (file)
index 0000000..7c3d813
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_ARM_H__
+#define __ARM_KVM_ARM_H__
+
+#include <linux/types.h>
+
+/* Hyp Configuration Register (HCR) bits */
+#define HCR_TGE                (1 << 27)
+#define HCR_TVM                (1 << 26)
+#define HCR_TTLB       (1 << 25)
+#define HCR_TPU                (1 << 24)
+#define HCR_TPC                (1 << 23)
+#define HCR_TSW                (1 << 22)
+#define HCR_TAC                (1 << 21)
+#define HCR_TIDCP      (1 << 20)
+#define HCR_TSC                (1 << 19)
+#define HCR_TID3       (1 << 18)
+#define HCR_TID2       (1 << 17)
+#define HCR_TID1       (1 << 16)
+#define HCR_TID0       (1 << 15)
+#define HCR_TWE                (1 << 14)
+#define HCR_TWI                (1 << 13)
+#define HCR_DC         (1 << 12)
+#define HCR_BSU                (3 << 10)
+#define HCR_BSU_IS     (1 << 10)
+#define HCR_FB         (1 << 9)
+#define HCR_VA         (1 << 8)
+#define HCR_VI         (1 << 7)
+#define HCR_VF         (1 << 6)
+#define HCR_AMO                (1 << 5)
+#define HCR_IMO                (1 << 4)
+#define HCR_FMO                (1 << 3)
+#define HCR_PTW                (1 << 2)
+#define HCR_SWIO       (1 << 1)
+#define HCR_VM         1
+
+/*
+ * The bits we set in HCR:
+ * TAC:                Trap ACTLR
+ * TSC:                Trap SMC
+ * TSW:                Trap cache operations by set/way
+ * TWI:                Trap WFI
+ * TIDCP:      Trap L2CTLR/L2ECTLR
+ * BSU_IS:     Upgrade barriers to the inner shareable domain
+ * FB:         Force broadcast of all maintainance operations
+ * AMO:                Override CPSR.A and enable signaling with VA
+ * IMO:                Override CPSR.I and enable signaling with VI
+ * FMO:                Override CPSR.F and enable signaling with VF
+ * SWIO:       Turn set/way invalidates into set/way clean+invalidate
+ */
+#define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
+                       HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
+                       HCR_SWIO | HCR_TIDCP)
+#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+
+/* System Control Register (SCTLR) bits */
+#define SCTLR_TE       (1 << 30)
+#define SCTLR_EE       (1 << 25)
+#define SCTLR_V                (1 << 13)
+
+/* Hyp System Control Register (HSCTLR) bits */
+#define HSCTLR_TE      (1 << 30)
+#define HSCTLR_EE      (1 << 25)
+#define HSCTLR_FI      (1 << 21)
+#define HSCTLR_WXN     (1 << 19)
+#define HSCTLR_I       (1 << 12)
+#define HSCTLR_C       (1 << 2)
+#define HSCTLR_A       (1 << 1)
+#define HSCTLR_M       1
+#define HSCTLR_MASK    (HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I | \
+                        HSCTLR_WXN | HSCTLR_FI | HSCTLR_EE | HSCTLR_TE)
+
+/* TTBCR and HTCR Registers bits */
+#define TTBCR_EAE      (1 << 31)
+#define TTBCR_IMP      (1 << 30)
+#define TTBCR_SH1      (3 << 28)
+#define TTBCR_ORGN1    (3 << 26)
+#define TTBCR_IRGN1    (3 << 24)
+#define TTBCR_EPD1     (1 << 23)
+#define TTBCR_A1       (1 << 22)
+#define TTBCR_T1SZ     (3 << 16)
+#define TTBCR_SH0      (3 << 12)
+#define TTBCR_ORGN0    (3 << 10)
+#define TTBCR_IRGN0    (3 << 8)
+#define TTBCR_EPD0     (1 << 7)
+#define TTBCR_T0SZ     3
+#define HTCR_MASK      (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
+
+/* Hyp System Trap Register */
+#define HSTR_T(x)      (1 << x)
+#define HSTR_TTEE      (1 << 16)
+#define HSTR_TJDBX     (1 << 17)
+
+/* Hyp Coprocessor Trap Register */
+#define HCPTR_TCP(x)   (1 << x)
+#define HCPTR_TCP_MASK (0x3fff)
+#define HCPTR_TASE     (1 << 15)
+#define HCPTR_TTA      (1 << 20)
+#define HCPTR_TCPAC    (1 << 31)
+
+/* Hyp Debug Configuration Register bits */
+#define HDCR_TDRA      (1 << 11)
+#define HDCR_TDOSA     (1 << 10)
+#define HDCR_TDA       (1 << 9)
+#define HDCR_TDE       (1 << 8)
+#define HDCR_HPME      (1 << 7)
+#define HDCR_TPM       (1 << 6)
+#define HDCR_TPMCR     (1 << 5)
+#define HDCR_HPMN_MASK (0x1F)
+
+/*
+ * The architecture supports 40-bit IPA as input to the 2nd stage translations
+ * and PTRS_PER_S2_PGD becomes 1024, because each entry covers 1GB of address
+ * space.
+ */
+#define KVM_PHYS_SHIFT (40)
+#define KVM_PHYS_SIZE  (1ULL << KVM_PHYS_SHIFT)
+#define KVM_PHYS_MASK  (KVM_PHYS_SIZE - 1ULL)
+#define PTRS_PER_S2_PGD        (1ULL << (KVM_PHYS_SHIFT - 30))
+#define S2_PGD_ORDER   get_order(PTRS_PER_S2_PGD * sizeof(pgd_t))
+#define S2_PGD_SIZE    (1 << S2_PGD_ORDER)
+
+/* Virtualization Translation Control Register (VTCR) bits */
+#define VTCR_SH0       (3 << 12)
+#define VTCR_ORGN0     (3 << 10)
+#define VTCR_IRGN0     (3 << 8)
+#define VTCR_SL0       (3 << 6)
+#define VTCR_S         (1 << 4)
+#define VTCR_T0SZ      (0xf)
+#define VTCR_MASK      (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0 | VTCR_SL0 | \
+                        VTCR_S | VTCR_T0SZ)
+#define VTCR_HTCR_SH   (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0)
+#define VTCR_SL_L2     (0 << 6)        /* Starting-level: 2 */
+#define VTCR_SL_L1     (1 << 6)        /* Starting-level: 1 */
+#define KVM_VTCR_SL0   VTCR_SL_L1
+/* stage-2 input address range defined as 2^(32-T0SZ) */
+#define KVM_T0SZ       (32 - KVM_PHYS_SHIFT)
+#define KVM_VTCR_T0SZ  (KVM_T0SZ & VTCR_T0SZ)
+#define KVM_VTCR_S     ((KVM_VTCR_T0SZ << 1) & VTCR_S)
+
+/* Virtualization Translation Table Base Register (VTTBR) bits */
+#if KVM_VTCR_SL0 == VTCR_SL_L2 /* see ARM DDI 0406C: B4-1720 */
+#define VTTBR_X                (14 - KVM_T0SZ)
+#else
+#define VTTBR_X                (5 - KVM_T0SZ)
+#endif
+#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
+#define VTTBR_BADDR_MASK  (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
+#define VTTBR_VMID_SHIFT  (48LLU)
+#define VTTBR_VMID_MASK          (0xffLLU << VTTBR_VMID_SHIFT)
+
+/* Hyp Syndrome Register (HSR) bits */
+#define HSR_EC_SHIFT   (26)
+#define HSR_EC         (0x3fU << HSR_EC_SHIFT)
+#define HSR_IL         (1U << 25)
+#define HSR_ISS                (HSR_IL - 1)
+#define HSR_ISV_SHIFT  (24)
+#define HSR_ISV                (1U << HSR_ISV_SHIFT)
+#define HSR_SRT_SHIFT  (16)
+#define HSR_SRT_MASK   (0xf << HSR_SRT_SHIFT)
+#define HSR_FSC                (0x3f)
+#define HSR_FSC_TYPE   (0x3c)
+#define HSR_SSE                (1 << 21)
+#define HSR_WNR                (1 << 6)
+#define HSR_CV_SHIFT   (24)
+#define HSR_CV         (1U << HSR_CV_SHIFT)
+#define HSR_COND_SHIFT (20)
+#define HSR_COND       (0xfU << HSR_COND_SHIFT)
+
+#define FSC_FAULT      (0x04)
+#define FSC_PERM       (0x0c)
+
+/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
+#define HPFAR_MASK     (~0xf)
+
+#define HSR_EC_UNKNOWN (0x00)
+#define HSR_EC_WFI     (0x01)
+#define HSR_EC_CP15_32 (0x03)
+#define HSR_EC_CP15_64 (0x04)
+#define HSR_EC_CP14_MR (0x05)
+#define HSR_EC_CP14_LS (0x06)
+#define HSR_EC_CP_0_13 (0x07)
+#define HSR_EC_CP10_ID (0x08)
+#define HSR_EC_JAZELLE (0x09)
+#define HSR_EC_BXJ     (0x0A)
+#define HSR_EC_CP14_64 (0x0C)
+#define HSR_EC_SVC_HYP (0x11)
+#define HSR_EC_HVC     (0x12)
+#define HSR_EC_SMC     (0x13)
+#define HSR_EC_IABT    (0x20)
+#define HSR_EC_IABT_HYP        (0x21)
+#define HSR_EC_DABT    (0x24)
+#define HSR_EC_DABT_HYP        (0x25)
+
+#define HSR_HVC_IMM_MASK       ((1UL << 16) - 1)
+
+#endif /* __ARM_KVM_ARM_H__ */
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
new file mode 100644 (file)
index 0000000..5e06e81
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_ASM_H__
+#define __ARM_KVM_ASM_H__
+
+/* 0 is reserved as an invalid value. */
+#define c0_MPIDR       1       /* MultiProcessor ID Register */
+#define c0_CSSELR      2       /* Cache Size Selection Register */
+#define c1_SCTLR       3       /* System Control Register */
+#define c1_ACTLR       4       /* Auxilliary Control Register */
+#define c1_CPACR       5       /* Coprocessor Access Control */
+#define c2_TTBR0       6       /* Translation Table Base Register 0 */
+#define c2_TTBR0_high  7       /* TTBR0 top 32 bits */
+#define c2_TTBR1       8       /* Translation Table Base Register 1 */
+#define c2_TTBR1_high  9       /* TTBR1 top 32 bits */
+#define c2_TTBCR       10      /* Translation Table Base Control R. */
+#define c3_DACR                11      /* Domain Access Control Register */
+#define c5_DFSR                12      /* Data Fault Status Register */
+#define c5_IFSR                13      /* Instruction Fault Status Register */
+#define c5_ADFSR       14      /* Auxilary Data Fault Status R */
+#define c5_AIFSR       15      /* Auxilary Instrunction Fault Status R */
+#define c6_DFAR                16      /* Data Fault Address Register */
+#define c6_IFAR                17      /* Instruction Fault Address Register */
+#define c9_L2CTLR      18      /* Cortex A15 L2 Control Register */
+#define c10_PRRR       19      /* Primary Region Remap Register */
+#define c10_NMRR       20      /* Normal Memory Remap Register */
+#define c12_VBAR       21      /* Vector Base Address Register */
+#define c13_CID                22      /* Context ID Register */
+#define c13_TID_URW    23      /* Thread ID, User R/W */
+#define c13_TID_URO    24      /* Thread ID, User R/O */
+#define c13_TID_PRIV   25      /* Thread ID, Privileged */
+#define NR_CP15_REGS   26      /* Number of regs (incl. invalid) */
+
+#define ARM_EXCEPTION_RESET      0
+#define ARM_EXCEPTION_UNDEFINED   1
+#define ARM_EXCEPTION_SOFTWARE    2
+#define ARM_EXCEPTION_PREF_ABORT  3
+#define ARM_EXCEPTION_DATA_ABORT  4
+#define ARM_EXCEPTION_IRQ        5
+#define ARM_EXCEPTION_FIQ        6
+#define ARM_EXCEPTION_HVC        7
+
+#ifndef __ASSEMBLY__
+struct kvm;
+struct kvm_vcpu;
+
+extern char __kvm_hyp_init[];
+extern char __kvm_hyp_init_end[];
+
+extern char __kvm_hyp_exit[];
+extern char __kvm_hyp_exit_end[];
+
+extern char __kvm_hyp_vector[];
+
+extern char __kvm_hyp_code_start[];
+extern char __kvm_hyp_code_end[];
+
+extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+
+extern void __kvm_flush_vm_context(void);
+extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+
+extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+#endif
+
+#endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
new file mode 100644 (file)
index 0000000..4917c2f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Rusty Russell IBM Corporation
+ *
+ * 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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_COPROC_H__
+#define __ARM_KVM_COPROC_H__
+#include <linux/kvm_host.h>
+
+void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
+
+struct kvm_coproc_target_table {
+       unsigned target;
+       const struct coproc_reg *table;
+       size_t num;
+};
+void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
+
+int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
+
+unsigned long kvm_arm_num_guest_msrs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_msrindices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+void kvm_coproc_table_init(void);
+
+struct kvm_one_reg;
+int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
+int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
+unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
+#endif /* __ARM_KVM_COPROC_H__ */
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
new file mode 100644 (file)
index 0000000..fd61199
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_EMULATE_H__
+#define __ARM_KVM_EMULATE_H__
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_mmio.h>
+
+u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
+u32 *vcpu_spsr(struct kvm_vcpu *vcpu);
+
+int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run);
+void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr);
+void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
+void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
+
+static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
+{
+       return 1;
+}
+
+static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
+{
+       return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
+}
+
+static inline u32 *vcpu_cpsr(struct kvm_vcpu *vcpu)
+{
+       return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
+}
+
+static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
+{
+       *vcpu_cpsr(vcpu) |= PSR_T_BIT;
+}
+
+static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
+{
+       unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
+       return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
+}
+
+static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
+{
+       unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
+       return cpsr_mode > USR_MODE;;
+}
+
+static inline bool kvm_vcpu_reg_is_pc(struct kvm_vcpu *vcpu, int reg)
+{
+       return reg == 15;
+}
+
+#endif /* __ARM_KVM_EMULATE_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
new file mode 100644 (file)
index 0000000..98b4d1a
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_HOST_H__
+#define __ARM_KVM_HOST_H__
+
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_mmio.h>
+#include <asm/fpstate.h>
+
+#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
+#define KVM_MEMORY_SLOTS 32
+#define KVM_PRIVATE_MEM_SLOTS 4
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_HAVE_ONE_REG
+
+#define KVM_VCPU_MAX_FEATURES 1
+
+/* We don't currently support large pages. */
+#define KVM_HPAGE_GFN_SHIFT(x) 0
+#define KVM_NR_PAGE_SIZES      1
+#define KVM_PAGES_PER_HPAGE(x) (1UL<<31)
+
+struct kvm_vcpu;
+u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
+int kvm_target_cpu(void);
+int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
+void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
+
+struct kvm_arch {
+       /* VTTBR value associated with below pgd and vmid */
+       u64    vttbr;
+
+       /*
+        * Anything that is not used directly from assembly code goes
+        * here.
+        */
+
+       /* The VMID generation used for the virt. memory system */
+       u64    vmid_gen;
+       u32    vmid;
+
+       /* Stage-2 page table */
+       pgd_t *pgd;
+};
+
+#define KVM_NR_MEM_OBJS     40
+
+/*
+ * We don't want allocation failures within the mmu code, so we preallocate
+ * enough memory for a single page fault in a cache.
+ */
+struct kvm_mmu_memory_cache {
+       int nobjs;
+       void *objects[KVM_NR_MEM_OBJS];
+};
+
+struct kvm_vcpu_arch {
+       struct kvm_regs regs;
+
+       int target; /* Processor target */
+       DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
+
+       /* System control coprocessor (cp15) */
+       u32 cp15[NR_CP15_REGS];
+
+       /* The CPU type we expose to the VM */
+       u32 midr;
+
+       /* Exception Information */
+       u32 hsr;                /* Hyp Syndrome Register */
+       u32 hxfar;              /* Hyp Data/Inst Fault Address Register */
+       u32 hpfar;              /* Hyp IPA Fault Address Register */
+
+       /* Floating point registers (VFP and Advanced SIMD/NEON) */
+       struct vfp_hard_struct vfp_guest;
+       struct vfp_hard_struct *vfp_host;
+
+       /*
+        * Anything that is not used directly from assembly code goes
+        * here.
+        */
+       /* dcache set/way operation pending */
+       int last_pcpu;
+       cpumask_t require_dcache_flush;
+
+       /* Don't run the guest on this vcpu */
+       bool pause;
+
+       /* IO related fields */
+       struct kvm_decode mmio_decode;
+
+       /* Interrupt related fields */
+       u32 irq_lines;          /* IRQ and FIQ levels */
+
+       /* Hyp exception information */
+       u32 hyp_pc;             /* PC when exception was taken from Hyp mode */
+
+       /* Cache some mmu pages needed inside spinlock regions */
+       struct kvm_mmu_memory_cache mmu_page_cache;
+
+       /* Detect first run of a vcpu */
+       bool has_run_once;
+};
+
+struct kvm_vm_stat {
+       u32 remote_tlb_flush;
+};
+
+struct kvm_vcpu_stat {
+       u32 halt_wakeup;
+};
+
+struct kvm_vcpu_init;
+int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
+                       const struct kvm_vcpu_init *init);
+unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
+struct kvm_one_reg;
+int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+u64 kvm_call_hyp(void *hypfn, ...);
+void force_vm_exit(const cpumask_t *mask);
+
+#define KVM_ARCH_WANT_MMU_NOTIFIER
+struct kvm;
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+int kvm_unmap_hva_range(struct kvm *kvm,
+                       unsigned long start, unsigned long end);
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
+
+unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
+
+/* We do not have shadow page tables, hence the empty hooks */
+static inline int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       return 0;
+}
+
+static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+       return 0;
+}
+#endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
new file mode 100644 (file)
index 0000000..adcc0d7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_MMIO_H__
+#define __ARM_KVM_MMIO_H__
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+
+struct kvm_decode {
+       unsigned long rt;
+       bool sign_extend;
+};
+
+/*
+ * The in-kernel MMIO emulation code wants to use a copy of run->mmio,
+ * which is an anonymous type. Use our own type instead.
+ */
+struct kvm_exit_mmio {
+       phys_addr_t     phys_addr;
+       u8              data[8];
+       u32             len;
+       bool            is_write;
+};
+
+static inline void kvm_prepare_mmio(struct kvm_run *run,
+                                   struct kvm_exit_mmio *mmio)
+{
+       run->mmio.phys_addr     = mmio->phys_addr;
+       run->mmio.len           = mmio->len;
+       run->mmio.is_write      = mmio->is_write;
+       memcpy(run->mmio.data, mmio->data, mmio->len);
+       run->exit_reason        = KVM_EXIT_MMIO;
+}
+
+int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
+                phys_addr_t fault_ipa);
+
+#endif /* __ARM_KVM_MMIO_H__ */
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
new file mode 100644 (file)
index 0000000..421a20b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_MMU_H__
+#define __ARM_KVM_MMU_H__
+
+int create_hyp_mappings(void *from, void *to);
+int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
+void free_hyp_pmds(void);
+
+int kvm_alloc_stage2_pgd(struct kvm *kvm);
+void kvm_free_stage2_pgd(struct kvm *kvm);
+int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
+                         phys_addr_t pa, unsigned long size);
+
+int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
+
+void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
+
+phys_addr_t kvm_mmu_get_httbr(void);
+int kvm_mmu_init(void);
+void kvm_clear_hyp_idmap(void);
+
+static inline bool kvm_is_write_fault(unsigned long hsr)
+{
+       unsigned long hsr_ec = hsr >> HSR_EC_SHIFT;
+       if (hsr_ec == HSR_EC_IABT)
+               return false;
+       else if ((hsr & HSR_ISV) && !(hsr & HSR_WNR))
+               return false;
+       else
+               return true;
+}
+
+#endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
new file mode 100644 (file)
index 0000000..9a83d98
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_KVM_PSCI_H__
+#define __ARM_KVM_PSCI_H__
+
+bool kvm_psci_call(struct kvm_vcpu *vcpu);
+
+#endif /* __ARM_KVM_PSCI_H__ */
index 917d4fc..308ad7d 100644 (file)
@@ -12,7 +12,6 @@
 
 struct tag;
 struct meminfo;
-struct sys_timer;
 struct pt_regs;
 struct smp_operations;
 #ifdef CONFIG_SMP
@@ -48,7 +47,7 @@ struct machine_desc {
        void                    (*map_io)(void);/* IO mapping function  */
        void                    (*init_early)(void);
        void                    (*init_irq)(void);
-       struct sys_timer        *timer;         /* system tick timer    */
+       void                    (*init_time)(void);
        void                    (*init_machine)(void);
        void                    (*init_late)(void);
 #ifdef CONFIG_MULTI_IRQ_HANDLER
index 6ca945f..90c12e1 100644 (file)
 #ifndef __ASM_ARM_MACH_TIME_H
 #define __ASM_ARM_MACH_TIME_H
 
-/*
- * This is our kernel timer structure.
- *
- * - init
- *   Initialise the kernels jiffy timer source, claim interrupt
- *   using setup_irq.  This is called early on during initialisation
- *   while interrupts are still disabled on the local CPU.
- * - suspend
- *   Suspend the kernel jiffy timer source, if necessary.  This
- *   is called with interrupts disabled, after all normal devices
- *   have been suspended.  If no action is required, set this to
- *   NULL.
- * - resume
- *   Resume the kernel jiffy timer source, if necessary.  This
- *   is called with interrupts disabled before any normal devices
- *   are resumed.  If no action is required, set this to NULL.
- * - offset
- *   Return the timer offset in microseconds since the last timer
- *   interrupt.  Note: this must take account of any unprocessed
- *   timer interrupt which may be pending.
- */
-struct sys_timer {
-       void                    (*init)(void);
-       void                    (*suspend)(void);
-       void                    (*resume)(void);
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-       unsigned long           (*offset)(void);
-#endif
-};
-
 extern void timer_tick(void);
 
 struct timespec;
index 73cf03a..1c4df27 100644 (file)
@@ -37,7 +37,7 @@
  */
 #define PAGE_OFFSET            UL(CONFIG_PAGE_OFFSET)
 #define TASK_SIZE              (UL(CONFIG_PAGE_OFFSET) - UL(0x01000000))
-#define TASK_UNMAPPED_BASE     (UL(CONFIG_PAGE_OFFSET) / 3)
+#define TASK_UNMAPPED_BASE     ALIGN(TASK_SIZE / 3, SZ_16M)
 
 /*
  * The maximum size of a 26-bit user space task.
index d795282..18f5cef 100644 (file)
@@ -32,6 +32,9 @@
 #define PMD_TYPE_SECT          (_AT(pmdval_t, 1) << 0)
 #define PMD_BIT4               (_AT(pmdval_t, 0))
 #define PMD_DOMAIN(x)          (_AT(pmdval_t, 0))
+#define PMD_APTABLE_SHIFT      (61)
+#define PMD_APTABLE            (_AT(pgdval_t, 3) << PGD_APTABLE_SHIFT)
+#define PMD_PXNTABLE           (_AT(pgdval_t, 1) << 59)
 
 /*
  *   - section
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_nG            (_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
 #define PMD_SECT_XN            (_AT(pmdval_t, 1) << 54)
 #define PMD_SECT_AP_WRITE      (_AT(pmdval_t, 0))
 #define PMD_SECT_AP_READ       (_AT(pmdval_t, 0))
+#define PMD_SECT_AP1           (_AT(pmdval_t, 1) << 6)
 #define PMD_SECT_TEX(x)                (_AT(pmdval_t, 0))
 
 /*
index a3f3792..6ef8afd 100644 (file)
  */
 #define L_PGD_SWAPPER          (_AT(pgdval_t, 1) << 55)        /* swapper_pg_dir entry */
 
+/*
+ * 2nd stage PTE definitions for LPAE.
+ */
+#define L_PTE_S2_MT_UNCACHED    (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */
+#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
+#define L_PTE_S2_MT_WRITEBACK   (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
+#define L_PTE_S2_RDONLY                 (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
+#define L_PTE_S2_RDWR           (_AT(pteval_t, 2) << 6)   /* HAP[2:1] */
+
+/*
+ * Hyp-mode PL2 PTE definitions for LPAE.
+ */
+#define L_PTE_HYP              L_PTE_USER
+
 #ifndef __ASSEMBLY__
 
 #define pud_none(pud)          (!pud_val(pud))
 #define pud_bad(pud)           (!(pud_val(pud) & 2))
 #define pud_present(pud)       (pud_val(pud))
+#define pmd_table(pmd)         ((pmd_val(pmd) & PMD_TYPE_MASK) == \
+                                                PMD_TYPE_TABLE)
+#define pmd_sect(pmd)          ((pmd_val(pmd) & PMD_TYPE_MASK) == \
+                                                PMD_TYPE_SECT)
 
 #define pud_clear(pudp)                        \
        do {                            \
index 9c82f98..f30ac3b 100644 (file)
@@ -70,6 +70,9 @@ extern void __pgd_error(const char *file, int line, pgd_t);
 
 extern pgprot_t                pgprot_user;
 extern pgprot_t                pgprot_kernel;
+extern pgprot_t                pgprot_hyp_device;
+extern pgprot_t                pgprot_s2;
+extern pgprot_t                pgprot_s2_device;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
@@ -82,6 +85,10 @@ extern pgprot_t              pgprot_kernel;
 #define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
 #define PAGE_KERNEL            _MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC       pgprot_kernel
+#define PAGE_HYP               _MOD_PROT(pgprot_kernel, L_PTE_HYP)
+#define PAGE_HYP_DEVICE                _MOD_PROT(pgprot_hyp_device, L_PTE_HYP)
+#define PAGE_S2                        _MOD_PROT(pgprot_s2, L_PTE_S2_RDONLY)
+#define PAGE_S2_DEVICE         _MOD_PROT(pgprot_s2_device, L_PTE_USER | L_PTE_S2_RDONLY)
 
 #define __PAGE_NONE            __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN | L_PTE_NONE)
 #define __PAGE_SHARED          __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
new file mode 100644 (file)
index 0000000..3303ff5
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_H__
+#define __ARM_KVM_H__
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_IRQ_LINE
+
+#define KVM_REG_SIZE(id)                                               \
+       (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+/* Valid for svc_regs, abt_regs, und_regs, irq_regs in struct kvm_regs */
+#define KVM_ARM_SVC_sp         svc_regs[0]
+#define KVM_ARM_SVC_lr         svc_regs[1]
+#define KVM_ARM_SVC_spsr       svc_regs[2]
+#define KVM_ARM_ABT_sp         abt_regs[0]
+#define KVM_ARM_ABT_lr         abt_regs[1]
+#define KVM_ARM_ABT_spsr       abt_regs[2]
+#define KVM_ARM_UND_sp         und_regs[0]
+#define KVM_ARM_UND_lr         und_regs[1]
+#define KVM_ARM_UND_spsr       und_regs[2]
+#define KVM_ARM_IRQ_sp         irq_regs[0]
+#define KVM_ARM_IRQ_lr         irq_regs[1]
+#define KVM_ARM_IRQ_spsr       irq_regs[2]
+
+/* Valid only for fiq_regs in struct kvm_regs */
+#define KVM_ARM_FIQ_r8         fiq_regs[0]
+#define KVM_ARM_FIQ_r9         fiq_regs[1]
+#define KVM_ARM_FIQ_r10                fiq_regs[2]
+#define KVM_ARM_FIQ_fp         fiq_regs[3]
+#define KVM_ARM_FIQ_ip         fiq_regs[4]
+#define KVM_ARM_FIQ_sp         fiq_regs[5]
+#define KVM_ARM_FIQ_lr         fiq_regs[6]
+#define KVM_ARM_FIQ_spsr       fiq_regs[7]
+
+struct kvm_regs {
+       struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
+       __u32 svc_regs[3];      /* SP_svc, LR_svc, SPSR_svc */
+       __u32 abt_regs[3];      /* SP_abt, LR_abt, SPSR_abt */
+       __u32 und_regs[3];      /* SP_und, LR_und, SPSR_und */
+       __u32 irq_regs[3];      /* SP_irq, LR_irq, SPSR_irq */
+       __u32 fiq_regs[8];      /* R8_fiq - R14_fiq, SPSR_fiq */
+};
+
+/* Supported Processor Types */
+#define KVM_ARM_TARGET_CORTEX_A15      0
+#define KVM_ARM_NUM_TARGETS            1
+
+#define KVM_ARM_VCPU_POWER_OFF         0 /* CPU is started in OFF state */
+
+struct kvm_vcpu_init {
+       __u32 target;
+       __u32 features[7];
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+};
+
+struct kvm_guest_debug_arch {
+};
+
+struct kvm_debug_exit_arch {
+};
+
+struct kvm_sync_regs {
+};
+
+struct kvm_arch_memory_slot {
+};
+
+/* If you need to interpret the index values, here is the key: */
+#define KVM_REG_ARM_COPROC_MASK                0x000000000FFF0000
+#define KVM_REG_ARM_COPROC_SHIFT       16
+#define KVM_REG_ARM_32_OPC2_MASK       0x0000000000000007
+#define KVM_REG_ARM_32_OPC2_SHIFT      0
+#define KVM_REG_ARM_OPC1_MASK          0x0000000000000078
+#define KVM_REG_ARM_OPC1_SHIFT         3
+#define KVM_REG_ARM_CRM_MASK           0x0000000000000780
+#define KVM_REG_ARM_CRM_SHIFT          7
+#define KVM_REG_ARM_32_CRN_MASK                0x0000000000007800
+#define KVM_REG_ARM_32_CRN_SHIFT       11
+
+/* Normal registers are mapped as coprocessor 16. */
+#define KVM_REG_ARM_CORE               (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_CORE_REG(name)     (offsetof(struct kvm_regs, name) / 4)
+
+/* Some registers need more space to represent values. */
+#define KVM_REG_ARM_DEMUX              (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_DEMUX_ID_MASK      0x000000000000FF00
+#define KVM_REG_ARM_DEMUX_ID_SHIFT     8
+#define KVM_REG_ARM_DEMUX_ID_CCSIDR    (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
+#define KVM_REG_ARM_DEMUX_VAL_MASK     0x00000000000000FF
+#define KVM_REG_ARM_DEMUX_VAL_SHIFT    0
+
+/* VFP registers: we could overload CP10 like ARM does, but that's ugly. */
+#define KVM_REG_ARM_VFP                        (0x0012 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_VFP_MASK           0x000000000000FFFF
+#define KVM_REG_ARM_VFP_BASE_REG       0x0
+#define KVM_REG_ARM_VFP_FPSID          0x1000
+#define KVM_REG_ARM_VFP_FPSCR          0x1001
+#define KVM_REG_ARM_VFP_MVFR1          0x1006
+#define KVM_REG_ARM_VFP_MVFR0          0x1007
+#define KVM_REG_ARM_VFP_FPEXC          0x1008
+#define KVM_REG_ARM_VFP_FPINST         0x1009
+#define KVM_REG_ARM_VFP_FPINST2                0x100A
+
+
+/* KVM_IRQ_LINE irq field index values */
+#define KVM_ARM_IRQ_TYPE_SHIFT         24
+#define KVM_ARM_IRQ_TYPE_MASK          0xff
+#define KVM_ARM_IRQ_VCPU_SHIFT         16
+#define KVM_ARM_IRQ_VCPU_MASK          0xff
+#define KVM_ARM_IRQ_NUM_SHIFT          0
+#define KVM_ARM_IRQ_NUM_MASK           0xffff
+
+/* irq_type field */
+#define KVM_ARM_IRQ_TYPE_CPU           0
+#define KVM_ARM_IRQ_TYPE_SPI           1
+#define KVM_ARM_IRQ_TYPE_PPI           2
+
+/* out-of-kernel GIC cpu interrupt injection irq_number field */
+#define KVM_ARM_IRQ_CPU_IRQ            0
+#define KVM_ARM_IRQ_CPU_FIQ            1
+
+/* Highest supported SPI, from VGIC_NR_IRQS */
+#define KVM_ARM_IRQ_GIC_MAX            127
+
+/* PSCI interface */
+#define KVM_PSCI_FN_BASE               0x95c1ba5e
+#define KVM_PSCI_FN(n)                 (KVM_PSCI_FN_BASE + (n))
+
+#define KVM_PSCI_FN_CPU_SUSPEND                KVM_PSCI_FN(0)
+#define KVM_PSCI_FN_CPU_OFF            KVM_PSCI_FN(1)
+#define KVM_PSCI_FN_CPU_ON             KVM_PSCI_FN(2)
+#define KVM_PSCI_FN_MIGRATE            KVM_PSCI_FN(3)
+
+#define KVM_PSCI_RET_SUCCESS           0
+#define KVM_PSCI_RET_NI                        ((unsigned long)-1)
+#define KVM_PSCI_RET_INVAL             ((unsigned long)-2)
+#define KVM_PSCI_RET_DENIED            ((unsigned long)-3)
+
+#endif /* __ARM_KVM_H__ */
index c985b48..c8b3272 100644 (file)
@@ -13,6 +13,9 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#ifdef CONFIG_KVM_ARM_HOST
+#include <linux/kvm_host.h>
+#endif
 #include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
@@ -146,5 +149,27 @@ int main(void)
   DEFINE(DMA_BIDIRECTIONAL,    DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,                DMA_TO_DEVICE);
   DEFINE(DMA_FROM_DEVICE,      DMA_FROM_DEVICE);
+#ifdef CONFIG_KVM_ARM_HOST
+  DEFINE(VCPU_KVM,             offsetof(struct kvm_vcpu, kvm));
+  DEFINE(VCPU_MIDR,            offsetof(struct kvm_vcpu, arch.midr));
+  DEFINE(VCPU_CP15,            offsetof(struct kvm_vcpu, arch.cp15));
+  DEFINE(VCPU_VFP_GUEST,       offsetof(struct kvm_vcpu, arch.vfp_guest));
+  DEFINE(VCPU_VFP_HOST,                offsetof(struct kvm_vcpu, arch.vfp_host));
+  DEFINE(VCPU_REGS,            offsetof(struct kvm_vcpu, arch.regs));
+  DEFINE(VCPU_USR_REGS,                offsetof(struct kvm_vcpu, arch.regs.usr_regs));
+  DEFINE(VCPU_SVC_REGS,                offsetof(struct kvm_vcpu, arch.regs.svc_regs));
+  DEFINE(VCPU_ABT_REGS,                offsetof(struct kvm_vcpu, arch.regs.abt_regs));
+  DEFINE(VCPU_UND_REGS,                offsetof(struct kvm_vcpu, arch.regs.und_regs));
+  DEFINE(VCPU_IRQ_REGS,                offsetof(struct kvm_vcpu, arch.regs.irq_regs));
+  DEFINE(VCPU_FIQ_REGS,                offsetof(struct kvm_vcpu, arch.regs.fiq_regs));
+  DEFINE(VCPU_PC,              offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
+  DEFINE(VCPU_CPSR,            offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
+  DEFINE(VCPU_IRQ_LINES,       offsetof(struct kvm_vcpu, arch.irq_lines));
+  DEFINE(VCPU_HSR,             offsetof(struct kvm_vcpu, arch.hsr));
+  DEFINE(VCPU_HxFAR,           offsetof(struct kvm_vcpu, arch.hxfar));
+  DEFINE(VCPU_HPFAR,           offsetof(struct kvm_vcpu, arch.hpfar));
+  DEFINE(VCPU_HYP_PC,          offsetof(struct kvm_vcpu, arch.hyp_pc));
+  DEFINE(KVM_VTTBR,            offsetof(struct kvm, arch.vttbr));
+#endif
   return 0; 
 }
index f9e8657..31e0eb3 100644 (file)
@@ -149,12 +149,6 @@ again:
 static void
 armpmu_read(struct perf_event *event)
 {
-       struct hw_perf_event *hwc = &event->hw;
-
-       /* Don't read disabled counters! */
-       if (hwc->idx < 0)
-               return;
-
        armpmu_event_update(event);
 }
 
@@ -207,8 +201,6 @@ armpmu_del(struct perf_event *event, int flags)
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
-       WARN_ON(idx < 0);
-
        armpmu_stop(event, PERF_EF_UPDATE);
        hw_events->events[idx] = NULL;
        clear_bit(idx, hw_events->used_mask);
@@ -358,7 +350,7 @@ __hw_perf_event_init(struct perf_event *event)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       int mapping, err;
+       int mapping;
 
        mapping = armpmu->map_event(event);
 
@@ -407,14 +399,12 @@ __hw_perf_event_init(struct perf_event *event)
                local64_set(&hwc->period_left, hwc->sample_period);
        }
 
-       err = 0;
        if (event->group_leader != event) {
-               err = validate_group(event);
-               if (err)
+               if (validate_group(event) != 0);
                        return -EINVAL;
        }
 
-       return err;
+       return 0;
 }
 
 static int armpmu_event_init(struct perf_event *event)
index 5f66206..1f2740e 100644 (file)
@@ -147,7 +147,7 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
        cpu_pmu->free_irq       = cpu_pmu_free_irq;
 
        /* Ensure the PMU has sane values out of reset. */
-       if (cpu_pmu && cpu_pmu->reset)
+       if (cpu_pmu->reset)
                on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
 }
 
@@ -201,48 +201,46 @@ static struct platform_device_id cpu_pmu_plat_device_ids[] = {
 static int probe_current_pmu(struct arm_pmu *pmu)
 {
        int cpu = get_cpu();
-       unsigned long cpuid = read_cpuid_id();
-       unsigned long implementor = (cpuid & 0xFF000000) >> 24;
-       unsigned long part_number = (cpuid & 0xFFF0);
+       unsigned long implementor = read_cpuid_implementor();
+       unsigned long part_number = read_cpuid_part_number();
        int ret = -ENODEV;
 
        pr_info("probing PMU on CPU %d\n", cpu);
 
        /* ARM Ltd CPUs. */
-       if (0x41 == implementor) {
+       if (implementor == ARM_CPU_IMP_ARM) {
                switch (part_number) {
-               case 0xB360:    /* ARM1136 */
-               case 0xB560:    /* ARM1156 */
-               case 0xB760:    /* ARM1176 */
+               case ARM_CPU_PART_ARM1136:
+               case ARM_CPU_PART_ARM1156:
+               case ARM_CPU_PART_ARM1176:
                        ret = armv6pmu_init(pmu);
                        break;
-               case 0xB020:    /* ARM11mpcore */
+               case ARM_CPU_PART_ARM11MPCORE:
                        ret = armv6mpcore_pmu_init(pmu);
                        break;
-               case 0xC080:    /* Cortex-A8 */
+               case ARM_CPU_PART_CORTEX_A8:
                        ret = armv7_a8_pmu_init(pmu);
                        break;
-               case 0xC090:    /* Cortex-A9 */
+               case ARM_CPU_PART_CORTEX_A9:
                        ret = armv7_a9_pmu_init(pmu);
                        break;
-               case 0xC050:    /* Cortex-A5 */
+               case ARM_CPU_PART_CORTEX_A5:
                        ret = armv7_a5_pmu_init(pmu);
                        break;
-               case 0xC0F0:    /* Cortex-A15 */
+               case ARM_CPU_PART_CORTEX_A15:
                        ret = armv7_a15_pmu_init(pmu);
                        break;
-               case 0xC070:    /* Cortex-A7 */
+               case ARM_CPU_PART_CORTEX_A7:
                        ret = armv7_a7_pmu_init(pmu);
                        break;
                }
        /* Intel CPUs [xscale]. */
-       } else if (0x69 == implementor) {
-               part_number = (cpuid >> 13) & 0x7;
-               switch (part_number) {
-               case 1:
+       } else if (implementor == ARM_CPU_IMP_INTEL) {
+               switch (xscale_cpu_arch_version()) {
+               case ARM_CPU_XSCALE_ARCH_V1:
                        ret = xscale1pmu_init(pmu);
                        break;
-               case 2:
+               case ARM_CPU_XSCALE_ARCH_V2:
                        ret = xscale2pmu_init(pmu);
                        break;
                }
@@ -279,17 +277,22 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
        }
 
        if (ret) {
-               pr_info("failed to register PMU devices!");
-               kfree(pmu);
-               return ret;
+               pr_info("failed to probe PMU!");
+               goto out_free;
        }
 
        cpu_pmu = pmu;
        cpu_pmu->plat_device = pdev;
        cpu_pmu_init(cpu_pmu);
-       armpmu_register(cpu_pmu, PERF_TYPE_RAW);
+       ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW);
 
-       return 0;
+       if (!ret)
+               return 0;
+
+out_free:
+       pr_info("failed to register PMU devices!");
+       kfree(pmu);
+       return ret;
 }
 
 static struct platform_driver cpu_pmu_driver = {
index 041d052..03664b0 100644 (file)
@@ -106,7 +106,7 @@ static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                },
                [C(OP_WRITE)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV6_PERFCTR_ICACHE_MISS,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
@@ -259,7 +259,7 @@ static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                },
                [C(OP_WRITE)] = {
                        [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+                       [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
index 4fbc757..8c79a9e 100644 (file)
@@ -157,8 +157,8 @@ static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
                },
                [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
@@ -282,7 +282,7 @@ static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                },
                [C(OP_WRITE)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
@@ -399,8 +399,8 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
                },
                [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                /*
                 * The prefetch counters don't differentiate between the I
@@ -527,8 +527,8 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
                },
                [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
@@ -651,8 +651,8 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                        [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
                },
                [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
index 2b0fe30..63990c4 100644 (file)
@@ -83,7 +83,7 @@ static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
                },
                [C(OP_WRITE)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
-                       [C(RESULT_MISS)]        = XSCALE_PERFCTR_ICACHE_MISS,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
                },
                [C(OP_PREFETCH)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
index 09be0c3..955d92d 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/profile.h>
-#include <linux/syscore_ops.h>
 #include <linux/timer.h>
 #include <linux/irq.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-/*
- * Our system timer.
- */
-static struct sys_timer *system_timer;
-
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
     defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
 /* this needs a better home */
@@ -69,16 +63,6 @@ unsigned long profile_pc(struct pt_regs *regs)
 EXPORT_SYMBOL(profile_pc);
 #endif
 
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-u32 arch_gettimeoffset(void)
-{
-       if (system_timer->offset != NULL)
-               return system_timer->offset() * 1000;
-
-       return 0;
-}
-#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
-
 #ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * Kernel system timer support.
@@ -129,43 +113,8 @@ int __init register_persistent_clock(clock_access_fn read_boot,
        return -EINVAL;
 }
 
-#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
-static int timer_suspend(void)
-{
-       if (system_timer->suspend)
-               system_timer->suspend();
-
-       return 0;
-}
-
-static void timer_resume(void)
-{
-       if (system_timer->resume)
-               system_timer->resume();
-}
-#else
-#define timer_suspend NULL
-#define timer_resume NULL
-#endif
-
-static struct syscore_ops timer_syscore_ops = {
-       .suspend        = timer_suspend,
-       .resume         = timer_resume,
-};
-
-static int __init timer_init_syscore_ops(void)
-{
-       register_syscore_ops(&timer_syscore_ops);
-
-       return 0;
-}
-
-device_initcall(timer_init_syscore_ops);
-
 void __init time_init(void)
 {
-       system_timer = machine_desc->timer;
-       system_timer->init();
+       machine_desc->init_time();
        sched_clock_postinit();
 }
-
index 11c1785..b571484 100644 (file)
        ALIGN_FUNCTION();                                               \
        VMLINUX_SYMBOL(__idmap_text_start) = .;                         \
        *(.idmap.text)                                                  \
-       VMLINUX_SYMBOL(__idmap_text_end) = .;
+       VMLINUX_SYMBOL(__idmap_text_end) = .;                           \
+       ALIGN_FUNCTION();                                               \
+       VMLINUX_SYMBOL(__hyp_idmap_text_start) = .;                     \
+       *(.hyp.idmap.text)                                              \
+       VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define ARM_CPU_DISCARD(x)
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
new file mode 100644 (file)
index 0000000..05227cb
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# KVM configuration
+#
+
+source "virt/kvm/Kconfig"
+
+menuconfig VIRTUALIZATION
+       bool "Virtualization"
+       ---help---
+         Say Y here to get to see options for using your Linux host to run
+         other operating systems inside virtual machines (guests).
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and
+         disabled.
+
+if VIRTUALIZATION
+
+config KVM
+       bool "Kernel-based Virtual Machine (KVM) support"
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       select KVM_MMIO
+       select KVM_ARM_HOST
+       depends on ARM_VIRT_EXT && ARM_LPAE
+       ---help---
+         Support hosting virtualized guest machines. You will also
+         need to select one or more of the processor modules below.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         If unsure, say N.
+
+config KVM_ARM_HOST
+       bool "KVM host support for ARM cpus."
+       depends on KVM
+       depends on MMU
+       select  MMU_NOTIFIER
+       ---help---
+         Provides host support for ARM processors.
+
+config KVM_ARM_MAX_VCPUS
+       int "Number maximum supported virtual CPUs per VM"
+       depends on KVM_ARM_HOST
+       default 4
+       help
+         Static number of max supported virtual CPUs per VM.
+
+         If you choose a high number, the vcpu structures will be quite
+         large, so only choose a reasonable number that you expect to
+         actually use.
+
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
new file mode 100644 (file)
index 0000000..ea27987
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# Makefile for Kernel-based Virtual Machine module
+#
+
+plus_virt := $(call as-instr,.arch_extension virt,+virt)
+ifeq ($(plus_virt),+virt)
+       plus_virt_def := -DREQUIRES_VIRT=1
+endif
+
+ccflags-y += -Ivirt/kvm -Iarch/arm/kvm
+CFLAGS_arm.o := -I. $(plus_virt_def)
+CFLAGS_mmu.o := -I.
+
+AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
+AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
+
+kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
+
+obj-y += kvm-arm.o init.o interrupts.o
+obj-y += arm.o guest.o mmu.o emulate.o reset.o
+obj-y += coproc.o coproc_a15.o mmio.o psci.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
new file mode 100644 (file)
index 0000000..2d30e3a
--- /dev/null
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/kvm.h>
+#include <trace/events/kvm.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#include <asm/unified.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/mman.h>
+#include <asm/cputype.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#include <asm/virt.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_coproc.h>
+#include <asm/kvm_psci.h>
+#include <asm/opcodes.h>
+
+#ifdef REQUIRES_VIRT
+__asm__(".arch_extension       virt");
+#endif
+
+static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
+static struct vfp_hard_struct __percpu *kvm_host_vfp_state;
+static unsigned long hyp_default_vectors;
+
+/* The VMID used in the VTTBR */
+static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
+static u8 kvm_next_vmid;
+static DEFINE_SPINLOCK(kvm_vmid_lock);
+
+int kvm_arch_hardware_enable(void *garbage)
+{
+       return 0;
+}
+
+int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
+{
+       return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+}
+
+int kvm_arch_hardware_setup(void)
+{
+       return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+       *(int *)rtn = 0;
+}
+
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
+/**
+ * kvm_arch_init_vm - initializes a VM data structure
+ * @kvm:       pointer to the KVM struct
+ */
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+{
+       int ret = 0;
+
+       if (type)
+               return -EINVAL;
+
+       ret = kvm_alloc_stage2_pgd(kvm);
+       if (ret)
+               goto out_fail_alloc;
+
+       ret = create_hyp_mappings(kvm, kvm + 1);
+       if (ret)
+               goto out_free_stage2_pgd;
+
+       /* Mark the initial VMID generation invalid */
+       kvm->arch.vmid_gen = 0;
+
+       return ret;
+out_free_stage2_pgd:
+       kvm_free_stage2_pgd(kvm);
+out_fail_alloc:
+       return ret;
+}
+
+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+
+void kvm_arch_free_memslot(struct kvm_memory_slot *free,
+                          struct kvm_memory_slot *dont)
+{
+}
+
+int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
+{
+       return 0;
+}
+
+/**
+ * kvm_arch_destroy_vm - destroy the VM data structure
+ * @kvm:       pointer to the KVM struct
+ */
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+       int i;
+
+       kvm_free_stage2_pgd(kvm);
+
+       for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+               if (kvm->vcpus[i]) {
+                       kvm_arch_vcpu_free(kvm->vcpus[i]);
+                       kvm->vcpus[i] = NULL;
+               }
+       }
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+       int r;
+       switch (ext) {
+       case KVM_CAP_USER_MEMORY:
+       case KVM_CAP_SYNC_MMU:
+       case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
+       case KVM_CAP_ONE_REG:
+       case KVM_CAP_ARM_PSCI:
+               r = 1;
+               break;
+       case KVM_CAP_COALESCED_MMIO:
+               r = KVM_COALESCED_MMIO_PAGE_OFFSET;
+               break;
+       case KVM_CAP_NR_VCPUS:
+               r = num_online_cpus();
+               break;
+       case KVM_CAP_MAX_VCPUS:
+               r = KVM_MAX_VCPUS;
+               break;
+       default:
+               r = 0;
+               break;
+       }
+       return r;
+}
+
+long kvm_arch_dev_ioctl(struct file *filp,
+                       unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_set_memory_region(struct kvm *kvm,
+                              struct kvm_userspace_memory_region *mem,
+                              struct kvm_memory_slot old,
+                              int user_alloc)
+{
+       return 0;
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+                                  struct kvm_memory_slot *memslot,
+                                  struct kvm_memory_slot old,
+                                  struct kvm_userspace_memory_region *mem,
+                                  int user_alloc)
+{
+       return 0;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+                                  struct kvm_userspace_memory_region *mem,
+                                  struct kvm_memory_slot old,
+                                  int user_alloc)
+{
+}
+
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+                                  struct kvm_memory_slot *slot)
+{
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+       int err;
+       struct kvm_vcpu *vcpu;
+
+       vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+       if (!vcpu) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = kvm_vcpu_init(vcpu, kvm, id);
+       if (err)
+               goto free_vcpu;
+
+       err = create_hyp_mappings(vcpu, vcpu + 1);
+       if (err)
+               goto vcpu_uninit;
+
+       return vcpu;
+vcpu_uninit:
+       kvm_vcpu_uninit(vcpu);
+free_vcpu:
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
+out:
+       return ERR_PTR(err);
+}
+
+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
+{
+       kvm_mmu_free_memory_caches(vcpu);
+       kmem_cache_free(kvm_vcpu_cache, vcpu);
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+       kvm_arch_vcpu_free(vcpu);
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+int __attribute_const__ kvm_target_cpu(void)
+{
+       unsigned long implementor = read_cpuid_implementor();
+       unsigned long part_number = read_cpuid_part_number();
+
+       if (implementor != ARM_CPU_IMP_ARM)
+               return -EINVAL;
+
+       switch (part_number) {
+       case ARM_CPU_PART_CORTEX_A15:
+               return KVM_ARM_TARGET_CORTEX_A15;
+       default:
+               return -EINVAL;
+       }
+}
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       /* Force users to call KVM_ARM_VCPU_INIT */
+       vcpu->arch.target = -1;
+       return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+       vcpu->cpu = cpu;
+       vcpu->arch.vfp_host = this_cpu_ptr(kvm_host_vfp_state);
+
+       /*
+        * Check whether this vcpu requires the cache to be flushed on
+        * this physical CPU. This is a consequence of doing dcache
+        * operations by set/way on this vcpu. We do it here to be in
+        * a non-preemptible section.
+        */
+       if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush))
+               flush_cache_all(); /* We'd really want v7_flush_dcache_all() */
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+}
+
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+                                       struct kvm_guest_debug *dbg)
+{
+       return -EINVAL;
+}
+
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+{
+       return -EINVAL;
+}
+
+/**
+ * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled
+ * @v:         The VCPU pointer
+ *
+ * If the guest CPU is not waiting for interrupts or an interrupt line is
+ * asserted, the CPU is by definition runnable.
+ */
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
+{
+       return !!v->arch.irq_lines;
+}
+
+/* Just ensure a guest exit from a particular CPU */
+static void exit_vm_noop(void *info)
+{
+}
+
+void force_vm_exit(const cpumask_t *mask)
+{
+       smp_call_function_many(mask, exit_vm_noop, NULL, true);
+}
+
+/**
+ * need_new_vmid_gen - check that the VMID is still valid
+ * @kvm: The VM's VMID to checkt
+ *
+ * return true if there is a new generation of VMIDs being used
+ *
+ * The hardware supports only 256 values with the value zero reserved for the
+ * host, so we check if an assigned value belongs to a previous generation,
+ * which which requires us to assign a new value. If we're the first to use a
+ * VMID for the new generation, we must flush necessary caches and TLBs on all
+ * CPUs.
+ */
+static bool need_new_vmid_gen(struct kvm *kvm)
+{
+       return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen));
+}
+
+/**
+ * update_vttbr - Update the VTTBR with a valid VMID before the guest runs
+ * @kvm        The guest that we are about to run
+ *
+ * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the
+ * VM has a valid VMID, otherwise assigns a new one and flushes corresponding
+ * caches and TLBs.
+ */
+static void update_vttbr(struct kvm *kvm)
+{
+       phys_addr_t pgd_phys;
+       u64 vmid;
+
+       if (!need_new_vmid_gen(kvm))
+               return;
+
+       spin_lock(&kvm_vmid_lock);
+
+       /*
+        * We need to re-check the vmid_gen here to ensure that if another vcpu
+        * already allocated a valid vmid for this vm, then this vcpu should
+        * use the same vmid.
+        */
+       if (!need_new_vmid_gen(kvm)) {
+               spin_unlock(&kvm_vmid_lock);
+               return;
+       }
+
+       /* First user of a new VMID generation? */
+       if (unlikely(kvm_next_vmid == 0)) {
+               atomic64_inc(&kvm_vmid_gen);
+               kvm_next_vmid = 1;
+
+               /*
+                * On SMP we know no other CPUs can use this CPU's or each
+                * other's VMID after force_vm_exit returns since the
+                * kvm_vmid_lock blocks them from reentry to the guest.
+                */
+               force_vm_exit(cpu_all_mask);
+               /*
+                * Now broadcast TLB + ICACHE invalidation over the inner
+                * shareable domain to make sure all data structures are
+                * clean.
+                */
+               kvm_call_hyp(__kvm_flush_vm_context);
+       }
+
+       kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen);
+       kvm->arch.vmid = kvm_next_vmid;
+       kvm_next_vmid++;
+
+       /* update vttbr to be used with the new vmid */
+       pgd_phys = virt_to_phys(kvm->arch.pgd);
+       vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK;
+       kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK;
+       kvm->arch.vttbr |= vmid;
+
+       spin_unlock(&kvm_vmid_lock);
+}
+
+static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       /* SVC called from Hyp mode should never get here */
+       kvm_debug("SVC called from Hyp mode shouldn't go here\n");
+       BUG();
+       return -EINVAL; /* Squash warning */
+}
+
+static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
+                     vcpu->arch.hsr & HSR_HVC_IMM_MASK);
+
+       if (kvm_psci_call(vcpu))
+               return 1;
+
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       if (kvm_psci_call(vcpu))
+               return 1;
+
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       /* The hypervisor should never cause aborts */
+       kvm_err("Prefetch Abort taken from Hyp mode at %#08x (HSR: %#08x)\n",
+               vcpu->arch.hxfar, vcpu->arch.hsr);
+       return -EFAULT;
+}
+
+static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       /* This is either an error in the ws. code or an external abort */
+       kvm_err("Data Abort taken from Hyp mode at %#08x (HSR: %#08x)\n",
+               vcpu->arch.hxfar, vcpu->arch.hsr);
+       return -EFAULT;
+}
+
+typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
+static exit_handle_fn arm_exit_handlers[] = {
+       [HSR_EC_WFI]            = kvm_handle_wfi,
+       [HSR_EC_CP15_32]        = kvm_handle_cp15_32,
+       [HSR_EC_CP15_64]        = kvm_handle_cp15_64,
+       [HSR_EC_CP14_MR]        = kvm_handle_cp14_access,
+       [HSR_EC_CP14_LS]        = kvm_handle_cp14_load_store,
+       [HSR_EC_CP14_64]        = kvm_handle_cp14_access,
+       [HSR_EC_CP_0_13]        = kvm_handle_cp_0_13_access,
+       [HSR_EC_CP10_ID]        = kvm_handle_cp10_id,
+       [HSR_EC_SVC_HYP]        = handle_svc_hyp,
+       [HSR_EC_HVC]            = handle_hvc,
+       [HSR_EC_SMC]            = handle_smc,
+       [HSR_EC_IABT]           = kvm_handle_guest_abort,
+       [HSR_EC_IABT_HYP]       = handle_pabt_hyp,
+       [HSR_EC_DABT]           = kvm_handle_guest_abort,
+       [HSR_EC_DABT_HYP]       = handle_dabt_hyp,
+};
+
+/*
+ * A conditional instruction is allowed to trap, even though it
+ * wouldn't be executed.  So let's re-implement the hardware, in
+ * software!
+ */
+static bool kvm_condition_valid(struct kvm_vcpu *vcpu)
+{
+       unsigned long cpsr, cond, insn;
+
+       /*
+        * Exception Code 0 can only happen if we set HCR.TGE to 1, to
+        * catch undefined instructions, and then we won't get past
+        * the arm_exit_handlers test anyway.
+        */
+       BUG_ON(((vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT) == 0);
+
+       /* Top two bits non-zero?  Unconditional. */
+       if (vcpu->arch.hsr >> 30)
+               return true;
+
+       cpsr = *vcpu_cpsr(vcpu);
+
+       /* Is condition field valid? */
+       if ((vcpu->arch.hsr & HSR_CV) >> HSR_CV_SHIFT)
+               cond = (vcpu->arch.hsr & HSR_COND) >> HSR_COND_SHIFT;
+       else {
+               /* This can happen in Thumb mode: examine IT state. */
+               unsigned long it;
+
+               it = ((cpsr >> 8) & 0xFC) | ((cpsr >> 25) & 0x3);
+
+               /* it == 0 => unconditional. */
+               if (it == 0)
+                       return true;
+
+               /* The cond for this insn works out as the top 4 bits. */
+               cond = (it >> 4);
+       }
+
+       /* Shift makes it look like an ARM-mode instruction */
+       insn = cond << 28;
+       return arm_check_condition(insn, cpsr) != ARM_OPCODE_CONDTEST_FAIL;
+}
+
+/*
+ * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
+ * proper exit to QEMU.
+ */
+static int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
+                      int exception_index)
+{
+       unsigned long hsr_ec;
+
+       switch (exception_index) {
+       case ARM_EXCEPTION_IRQ:
+               return 1;
+       case ARM_EXCEPTION_UNDEFINED:
+               kvm_err("Undefined exception in Hyp mode at: %#08x\n",
+                       vcpu->arch.hyp_pc);
+               BUG();
+               panic("KVM: Hypervisor undefined exception!\n");
+       case ARM_EXCEPTION_DATA_ABORT:
+       case ARM_EXCEPTION_PREF_ABORT:
+       case ARM_EXCEPTION_HVC:
+               hsr_ec = (vcpu->arch.hsr & HSR_EC) >> HSR_EC_SHIFT;
+
+               if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers)
+                   || !arm_exit_handlers[hsr_ec]) {
+                       kvm_err("Unkown exception class: %#08lx, "
+                               "hsr: %#08x\n", hsr_ec,
+                               (unsigned int)vcpu->arch.hsr);
+                       BUG();
+               }
+
+               /*
+                * See ARM ARM B1.14.1: "Hyp traps on instructions
+                * that fail their condition code check"
+                */
+               if (!kvm_condition_valid(vcpu)) {
+                       bool is_wide = vcpu->arch.hsr & HSR_IL;
+                       kvm_skip_instr(vcpu, is_wide);
+                       return 1;
+               }
+
+               return arm_exit_handlers[hsr_ec](vcpu, run);
+       default:
+               kvm_pr_unimpl("Unsupported exception type: %d",
+                             exception_index);
+               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+               return 0;
+       }
+}
+
+static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
+{
+       if (likely(vcpu->arch.has_run_once))
+               return 0;
+
+       vcpu->arch.has_run_once = true;
+
+       /*
+        * Handle the "start in power-off" case by calling into the
+        * PSCI code.
+        */
+       if (test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) {
+               *vcpu_reg(vcpu, 0) = KVM_PSCI_FN_CPU_OFF;
+               kvm_psci_call(vcpu);
+       }
+
+       return 0;
+}
+
+static void vcpu_pause(struct kvm_vcpu *vcpu)
+{
+       wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
+
+       wait_event_interruptible(*wq, !vcpu->arch.pause);
+}
+
+/**
+ * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
+ * @vcpu:      The VCPU pointer
+ * @run:       The kvm_run structure pointer used for userspace state exchange
+ *
+ * This function is called through the VCPU_RUN ioctl called from user space. It
+ * will execute VM code in a loop until the time slice for the process is used
+ * or some emulation is needed from user space in which case the function will
+ * return with return value 0 and with the kvm_run structure filled in with the
+ * required data for the requested emulation.
+ */
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       int ret;
+       sigset_t sigsaved;
+
+       /* Make sure they initialize the vcpu with KVM_ARM_VCPU_INIT */
+       if (unlikely(vcpu->arch.target < 0))
+               return -ENOEXEC;
+
+       ret = kvm_vcpu_first_run_init(vcpu);
+       if (ret)
+               return ret;
+
+       if (run->exit_reason == KVM_EXIT_MMIO) {
+               ret = kvm_handle_mmio_return(vcpu, vcpu->run);
+               if (ret)
+                       return ret;
+       }
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+       ret = 1;
+       run->exit_reason = KVM_EXIT_UNKNOWN;
+       while (ret > 0) {
+               /*
+                * Check conditions before entering the guest
+                */
+               cond_resched();
+
+               update_vttbr(vcpu->kvm);
+
+               if (vcpu->arch.pause)
+                       vcpu_pause(vcpu);
+
+               local_irq_disable();
+
+               /*
+                * Re-check atomic conditions
+                */
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       run->exit_reason = KVM_EXIT_INTR;
+               }
+
+               if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
+                       local_irq_enable();
+                       continue;
+               }
+
+               /**************************************************************
+                * Enter the guest
+                */
+               trace_kvm_entry(*vcpu_pc(vcpu));
+               kvm_guest_enter();
+               vcpu->mode = IN_GUEST_MODE;
+
+               ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
+
+               vcpu->mode = OUTSIDE_GUEST_MODE;
+               vcpu->arch.last_pcpu = smp_processor_id();
+               kvm_guest_exit();
+               trace_kvm_exit(*vcpu_pc(vcpu));
+               /*
+                * We may have taken a host interrupt in HYP mode (ie
+                * while executing the guest). This interrupt is still
+                * pending, as we haven't serviced it yet!
+                *
+                * We're now back in SVC mode, with interrupts
+                * disabled.  Enabling the interrupts now will have
+                * the effect of taking the interrupt again, in SVC
+                * mode this time.
+                */
+               local_irq_enable();
+
+               /*
+                * Back from guest
+                *************************************************************/
+
+               ret = handle_exit(vcpu, run, ret);
+       }
+
+       if (vcpu->sigset_active)
+               sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+       return ret;
+}
+
+static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level)
+{
+       int bit_index;
+       bool set;
+       unsigned long *ptr;
+
+       if (number == KVM_ARM_IRQ_CPU_IRQ)
+               bit_index = __ffs(HCR_VI);
+       else /* KVM_ARM_IRQ_CPU_FIQ */
+               bit_index = __ffs(HCR_VF);
+
+       ptr = (unsigned long *)&vcpu->arch.irq_lines;
+       if (level)
+               set = test_and_set_bit(bit_index, ptr);
+       else
+               set = test_and_clear_bit(bit_index, ptr);
+
+       /*
+        * If we didn't change anything, no need to wake up or kick other CPUs
+        */
+       if (set == level)
+               return 0;
+
+       /*
+        * The vcpu irq_lines field was updated, wake up sleeping VCPUs and
+        * trigger a world-switch round on the running physical CPU to set the
+        * virtual IRQ/FIQ fields in the HCR appropriately.
+        */
+       kvm_vcpu_kick(vcpu);
+
+       return 0;
+}
+
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level)
+{
+       u32 irq = irq_level->irq;
+       unsigned int irq_type, vcpu_idx, irq_num;
+       int nrcpus = atomic_read(&kvm->online_vcpus);
+       struct kvm_vcpu *vcpu = NULL;
+       bool level = irq_level->level;
+
+       irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK;
+       vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK;
+       irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK;
+
+       trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level);
+
+       if (irq_type != KVM_ARM_IRQ_TYPE_CPU)
+               return -EINVAL;
+
+       if (vcpu_idx >= nrcpus)
+               return -EINVAL;
+
+       vcpu = kvm_get_vcpu(kvm, vcpu_idx);
+       if (!vcpu)
+               return -EINVAL;
+
+       if (irq_num > KVM_ARM_IRQ_CPU_FIQ)
+               return -EINVAL;
+
+       return vcpu_interrupt_line(vcpu, irq_num, level);
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+                        unsigned int ioctl, unsigned long arg)
+{
+       struct kvm_vcpu *vcpu = filp->private_data;
+       void __user *argp = (void __user *)arg;
+
+       switch (ioctl) {
+       case KVM_ARM_VCPU_INIT: {
+               struct kvm_vcpu_init init;
+
+               if (copy_from_user(&init, argp, sizeof(init)))
+                       return -EFAULT;
+
+               return kvm_vcpu_set_target(vcpu, &init);
+
+       }
+       case KVM_SET_ONE_REG:
+       case KVM_GET_ONE_REG: {
+               struct kvm_one_reg reg;
+               if (copy_from_user(&reg, argp, sizeof(reg)))
+                       return -EFAULT;
+               if (ioctl == KVM_SET_ONE_REG)
+                       return kvm_arm_set_reg(vcpu, &reg);
+               else
+                       return kvm_arm_get_reg(vcpu, &reg);
+       }
+       case KVM_GET_REG_LIST: {
+               struct kvm_reg_list __user *user_list = argp;
+               struct kvm_reg_list reg_list;
+               unsigned n;
+
+               if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
+                       return -EFAULT;
+               n = reg_list.n;
+               reg_list.n = kvm_arm_num_regs(vcpu);
+               if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
+                       return -EFAULT;
+               if (n < reg_list.n)
+                       return -E2BIG;
+               return kvm_arm_copy_reg_indices(vcpu, user_list->reg);
+       }
+       default:
+               return -EINVAL;
+       }
+}
+
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
+{
+       return -EINVAL;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+                      unsigned int ioctl, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+static void cpu_init_hyp_mode(void *vector)
+{
+       unsigned long long pgd_ptr;
+       unsigned long pgd_low, pgd_high;
+       unsigned long hyp_stack_ptr;
+       unsigned long stack_page;
+       unsigned long vector_ptr;
+
+       /* Switch from the HYP stub to our own HYP init vector */
+       __hyp_set_vectors((unsigned long)vector);
+
+       pgd_ptr = (unsigned long long)kvm_mmu_get_httbr();
+       pgd_low = (pgd_ptr & ((1ULL << 32) - 1));
+       pgd_high = (pgd_ptr >> 32ULL);
+       stack_page = __get_cpu_var(kvm_arm_hyp_stack_page);
+       hyp_stack_ptr = stack_page + PAGE_SIZE;
+       vector_ptr = (unsigned long)__kvm_hyp_vector;
+
+       /*
+        * Call initialization code, and switch to the full blown
+        * HYP code. The init code doesn't need to preserve these registers as
+        * r1-r3 and r12 are already callee save according to the AAPCS.
+        * Note that we slightly misuse the prototype by casing the pgd_low to
+        * a void *.
+        */
+       kvm_call_hyp((void *)pgd_low, pgd_high, hyp_stack_ptr, vector_ptr);
+}
+
+/**
+ * Inits Hyp-mode on all online CPUs
+ */
+static int init_hyp_mode(void)
+{
+       phys_addr_t init_phys_addr;
+       int cpu;
+       int err = 0;
+
+       /*
+        * Allocate Hyp PGD and setup Hyp identity mapping
+        */
+       err = kvm_mmu_init();
+       if (err)
+               goto out_err;
+
+       /*
+        * It is probably enough to obtain the default on one
+        * CPU. It's unlikely to be different on the others.
+        */
+       hyp_default_vectors = __hyp_get_vectors();
+
+       /*
+        * Allocate stack pages for Hypervisor-mode
+        */
+       for_each_possible_cpu(cpu) {
+               unsigned long stack_page;
+
+               stack_page = __get_free_page(GFP_KERNEL);
+               if (!stack_page) {
+                       err = -ENOMEM;
+                       goto out_free_stack_pages;
+               }
+
+               per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page;
+       }
+
+       /*
+        * Execute the init code on each CPU.
+        *
+        * Note: The stack is not mapped yet, so don't do anything else than
+        * initializing the hypervisor mode on each CPU using a local stack
+        * space for temporary storage.
+        */
+       init_phys_addr = virt_to_phys(__kvm_hyp_init);
+       for_each_online_cpu(cpu) {
+               smp_call_function_single(cpu, cpu_init_hyp_mode,
+                                        (void *)(long)init_phys_addr, 1);
+       }
+
+       /*
+        * Unmap the identity mapping
+        */
+       kvm_clear_hyp_idmap();
+
+       /*
+        * Map the Hyp-code called directly from the host
+        */
+       err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end);
+       if (err) {
+               kvm_err("Cannot map world-switch code\n");
+               goto out_free_mappings;
+       }
+
+       /*
+        * Map the Hyp stack pages
+        */
+       for_each_possible_cpu(cpu) {
+               char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu);
+               err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE);
+
+               if (err) {
+                       kvm_err("Cannot map hyp stack\n");
+                       goto out_free_mappings;
+               }
+       }
+
+       /*
+        * Map the host VFP structures
+        */
+       kvm_host_vfp_state = alloc_percpu(struct vfp_hard_struct);
+       if (!kvm_host_vfp_state) {
+               err = -ENOMEM;
+               kvm_err("Cannot allocate host VFP state\n");
+               goto out_free_mappings;
+       }
+
+       for_each_possible_cpu(cpu) {
+               struct vfp_hard_struct *vfp;
+
+               vfp = per_cpu_ptr(kvm_host_vfp_state, cpu);
+               err = create_hyp_mappings(vfp, vfp + 1);
+
+               if (err) {
+                       kvm_err("Cannot map host VFP state: %d\n", err);
+                       goto out_free_vfp;
+               }
+       }
+
+       kvm_info("Hyp mode initialized successfully\n");
+       return 0;
+out_free_vfp:
+       free_percpu(kvm_host_vfp_state);
+out_free_mappings:
+       free_hyp_pmds();
+out_free_stack_pages:
+       for_each_possible_cpu(cpu)
+               free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
+out_err:
+       kvm_err("error initializing Hyp mode: %d\n", err);
+       return err;
+}
+
+/**
+ * Initialize Hyp-mode and memory mappings on all CPUs.
+ */
+int kvm_arch_init(void *opaque)
+{
+       int err;
+
+       if (!is_hyp_mode_available()) {
+               kvm_err("HYP mode not available\n");
+               return -ENODEV;
+       }
+
+       if (kvm_target_cpu() < 0) {
+               kvm_err("Target CPU not supported!\n");
+               return -ENODEV;
+       }
+
+       err = init_hyp_mode();
+       if (err)
+               goto out_err;
+
+       kvm_coproc_table_init();
+       return 0;
+out_err:
+       return err;
+}
+
+/* NOP: Compiling as a module not supported */
+void kvm_arch_exit(void)
+{
+}
+
+static int arm_init(void)
+{
+       int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+       return rc;
+}
+
+module_init(arm_init);
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
new file mode 100644 (file)
index 0000000..d782638
--- /dev/null
@@ -0,0 +1,1046 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Authors: Rusty Russell <rusty@rustcorp.com.au>
+ *          Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <linux/mm.h>
+#include <linux/kvm_host.h>
+#include <linux/uaccess.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_host.h>
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_coproc.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <trace/events/kvm.h>
+#include <asm/vfp.h>
+#include "../vfp/vfpinstr.h"
+
+#include "trace.h"
+#include "coproc.h"
+
+
+/******************************************************************************
+ * Co-processor emulation
+ *****************************************************************************/
+
+/* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
+static u32 cache_levels;
+
+/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
+#define CSSELR_MAX 12
+
+int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       /*
+        * We can get here, if the host has been built without VFPv3 support,
+        * but the guest attempted a floating point operation.
+        */
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+/* See note at ARM ARM B1.14.4 */
+static bool access_dcsw(struct kvm_vcpu *vcpu,
+                       const struct coproc_params *p,
+                       const struct coproc_reg *r)
+{
+       u32 val;
+       int cpu;
+
+       cpu = get_cpu();
+
+       if (!p->is_write)
+               return read_from_write_only(vcpu, p);
+
+       cpumask_setall(&vcpu->arch.require_dcache_flush);
+       cpumask_clear_cpu(cpu, &vcpu->arch.require_dcache_flush);
+
+       /* If we were already preempted, take the long way around */
+       if (cpu != vcpu->arch.last_pcpu) {
+               flush_cache_all();
+               goto done;
+       }
+
+       val = *vcpu_reg(vcpu, p->Rt1);
+
+       switch (p->CRm) {
+       case 6:                 /* Upgrade DCISW to DCCISW, as per HCR.SWIO */
+       case 14:                /* DCCISW */
+               asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r" (val));
+               break;
+
+       case 10:                /* DCCSW */
+               asm volatile("mcr p15, 0, %0, c7, c10, 2" : : "r" (val));
+               break;
+       }
+
+done:
+       put_cpu();
+
+       return true;
+}
+
+/*
+ * We could trap ID_DFR0 and tell the guest we don't support performance
+ * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
+ * NAKed, so it will read the PMCR anyway.
+ *
+ * Therefore we tell the guest we have 0 counters.  Unfortunately, we
+ * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
+ * all PM registers, which doesn't crash the guest kernel at least.
+ */
+static bool pm_fake(struct kvm_vcpu *vcpu,
+                   const struct coproc_params *p,
+                   const struct coproc_reg *r)
+{
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+       else
+               return read_zero(vcpu, p);
+}
+
+#define access_pmcr pm_fake
+#define access_pmcntenset pm_fake
+#define access_pmcntenclr pm_fake
+#define access_pmovsr pm_fake
+#define access_pmselr pm_fake
+#define access_pmceid0 pm_fake
+#define access_pmceid1 pm_fake
+#define access_pmccntr pm_fake
+#define access_pmxevtyper pm_fake
+#define access_pmxevcntr pm_fake
+#define access_pmuserenr pm_fake
+#define access_pmintenset pm_fake
+#define access_pmintenclr pm_fake
+
+/* Architected CP15 registers.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ */
+static const struct coproc_reg cp15_regs[] = {
+       /* CSSELR: swapped by interrupt.S. */
+       { CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32,
+                       NULL, reset_unknown, c0_CSSELR },
+
+       /* TTBR0/TTBR1: swapped by interrupt.S. */
+       { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
+       { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
+
+       /* TTBCR: swapped by interrupt.S. */
+       { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
+                       NULL, reset_val, c2_TTBCR, 0x00000000 },
+
+       /* DACR: swapped by interrupt.S. */
+       { CRn( 3), CRm( 0), Op1( 0), Op2( 0), is32,
+                       NULL, reset_unknown, c3_DACR },
+
+       /* DFSR/IFSR/ADFSR/AIFSR: swapped by interrupt.S. */
+       { CRn( 5), CRm( 0), Op1( 0), Op2( 0), is32,
+                       NULL, reset_unknown, c5_DFSR },
+       { CRn( 5), CRm( 0), Op1( 0), Op2( 1), is32,
+                       NULL, reset_unknown, c5_IFSR },
+       { CRn( 5), CRm( 1), Op1( 0), Op2( 0), is32,
+                       NULL, reset_unknown, c5_ADFSR },
+       { CRn( 5), CRm( 1), Op1( 0), Op2( 1), is32,
+                       NULL, reset_unknown, c5_AIFSR },
+
+       /* DFAR/IFAR: swapped by interrupt.S. */
+       { CRn( 6), CRm( 0), Op1( 0), Op2( 0), is32,
+                       NULL, reset_unknown, c6_DFAR },
+       { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32,
+                       NULL, reset_unknown, c6_IFAR },
+       /*
+        * DC{C,I,CI}SW operations:
+        */
+       { CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw},
+       { CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
+       { CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
+       /*
+        * Dummy performance monitor implementation.
+        */
+       { CRn( 9), CRm(12), Op1( 0), Op2( 0), is32, access_pmcr},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 1), is32, access_pmcntenset},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 2), is32, access_pmcntenclr},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 3), is32, access_pmovsr},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 5), is32, access_pmselr},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 6), is32, access_pmceid0},
+       { CRn( 9), CRm(12), Op1( 0), Op2( 7), is32, access_pmceid1},
+       { CRn( 9), CRm(13), Op1( 0), Op2( 0), is32, access_pmccntr},
+       { CRn( 9), CRm(13), Op1( 0), Op2( 1), is32, access_pmxevtyper},
+       { CRn( 9), CRm(13), Op1( 0), Op2( 2), is32, access_pmxevcntr},
+       { CRn( 9), CRm(14), Op1( 0), Op2( 0), is32, access_pmuserenr},
+       { CRn( 9), CRm(14), Op1( 0), Op2( 1), is32, access_pmintenset},
+       { CRn( 9), CRm(14), Op1( 0), Op2( 2), is32, access_pmintenclr},
+
+       /* PRRR/NMRR (aka MAIR0/MAIR1): swapped by interrupt.S. */
+       { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32,
+                       NULL, reset_unknown, c10_PRRR},
+       { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32,
+                       NULL, reset_unknown, c10_NMRR},
+
+       /* VBAR: swapped by interrupt.S. */
+       { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
+                       NULL, reset_val, c12_VBAR, 0x00000000 },
+
+       /* CONTEXTIDR/TPIDRURW/TPIDRURO/TPIDRPRW: swapped by interrupt.S. */
+       { CRn(13), CRm( 0), Op1( 0), Op2( 1), is32,
+                       NULL, reset_val, c13_CID, 0x00000000 },
+       { CRn(13), CRm( 0), Op1( 0), Op2( 2), is32,
+                       NULL, reset_unknown, c13_TID_URW },
+       { CRn(13), CRm( 0), Op1( 0), Op2( 3), is32,
+                       NULL, reset_unknown, c13_TID_URO },
+       { CRn(13), CRm( 0), Op1( 0), Op2( 4), is32,
+                       NULL, reset_unknown, c13_TID_PRIV },
+};
+
+/* Target specific emulation tables */
+static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
+
+void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
+{
+       target_tables[table->target] = table;
+}
+
+/* Get specific register table for this target. */
+static const struct coproc_reg *get_target_table(unsigned target, size_t *num)
+{
+       struct kvm_coproc_target_table *table;
+
+       table = target_tables[target];
+       *num = table->num;
+       return table->table;
+}
+
+static const struct coproc_reg *find_reg(const struct coproc_params *params,
+                                        const struct coproc_reg table[],
+                                        unsigned int num)
+{
+       unsigned int i;
+
+       for (i = 0; i < num; i++) {
+               const struct coproc_reg *r = &table[i];
+
+               if (params->is_64bit != r->is_64)
+                       continue;
+               if (params->CRn != r->CRn)
+                       continue;
+               if (params->CRm != r->CRm)
+                       continue;
+               if (params->Op1 != r->Op1)
+                       continue;
+               if (params->Op2 != r->Op2)
+                       continue;
+
+               return r;
+       }
+       return NULL;
+}
+
+static int emulate_cp15(struct kvm_vcpu *vcpu,
+                       const struct coproc_params *params)
+{
+       size_t num;
+       const struct coproc_reg *table, *r;
+
+       trace_kvm_emulate_cp15_imp(params->Op1, params->Rt1, params->CRn,
+                                  params->CRm, params->Op2, params->is_write);
+
+       table = get_target_table(vcpu->arch.target, &num);
+
+       /* Search target-specific then generic table. */
+       r = find_reg(params, table, num);
+       if (!r)
+               r = find_reg(params, cp15_regs, ARRAY_SIZE(cp15_regs));
+
+       if (likely(r)) {
+               /* If we don't have an accessor, we should never get here! */
+               BUG_ON(!r->access);
+
+               if (likely(r->access(vcpu, params, r))) {
+                       /* Skip instruction, since it was emulated */
+                       kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1);
+                       return 1;
+               }
+               /* If access function fails, it should complain. */
+       } else {
+               kvm_err("Unsupported guest CP15 access at: %08x\n",
+                       *vcpu_pc(vcpu));
+               print_cp_instr(params);
+       }
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
+/**
+ * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params;
+
+       params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
+       params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
+       params.is_write = ((vcpu->arch.hsr & 1) == 0);
+       params.is_64bit = true;
+
+       params.Op1 = (vcpu->arch.hsr >> 16) & 0xf;
+       params.Op2 = 0;
+       params.Rt2 = (vcpu->arch.hsr >> 10) & 0xf;
+       params.CRn = 0;
+
+       return emulate_cp15(vcpu, &params);
+}
+
+static void reset_coproc_regs(struct kvm_vcpu *vcpu,
+                             const struct coproc_reg *table, size_t num)
+{
+       unsigned long i;
+
+       for (i = 0; i < num; i++)
+               if (table[i].reset)
+                       table[i].reset(vcpu, &table[i]);
+}
+
+/**
+ * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params;
+
+       params.CRm = (vcpu->arch.hsr >> 1) & 0xf;
+       params.Rt1 = (vcpu->arch.hsr >> 5) & 0xf;
+       params.is_write = ((vcpu->arch.hsr & 1) == 0);
+       params.is_64bit = false;
+
+       params.CRn = (vcpu->arch.hsr >> 10) & 0xf;
+       params.Op1 = (vcpu->arch.hsr >> 14) & 0x7;
+       params.Op2 = (vcpu->arch.hsr >> 17) & 0x7;
+       params.Rt2 = 0;
+
+       return emulate_cp15(vcpu, &params);
+}
+
+/******************************************************************************
+ * Userspace API
+ *****************************************************************************/
+
+static bool index_to_params(u64 id, struct coproc_params *params)
+{
+       switch (id & KVM_REG_SIZE_MASK) {
+       case KVM_REG_SIZE_U32:
+               /* Any unused index bits means it's not valid. */
+               if (id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK
+                          | KVM_REG_ARM_COPROC_MASK
+                          | KVM_REG_ARM_32_CRN_MASK
+                          | KVM_REG_ARM_CRM_MASK
+                          | KVM_REG_ARM_OPC1_MASK
+                          | KVM_REG_ARM_32_OPC2_MASK))
+                       return false;
+
+               params->is_64bit = false;
+               params->CRn = ((id & KVM_REG_ARM_32_CRN_MASK)
+                              >> KVM_REG_ARM_32_CRN_SHIFT);
+               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+                              >> KVM_REG_ARM_CRM_SHIFT);
+               params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
+                              >> KVM_REG_ARM_OPC1_SHIFT);
+               params->Op2 = ((id & KVM_REG_ARM_32_OPC2_MASK)
+                              >> KVM_REG_ARM_32_OPC2_SHIFT);
+               return true;
+       case KVM_REG_SIZE_U64:
+               /* Any unused index bits means it's not valid. */
+               if (id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK
+                             | KVM_REG_ARM_COPROC_MASK
+                             | KVM_REG_ARM_CRM_MASK
+                             | KVM_REG_ARM_OPC1_MASK))
+                       return false;
+               params->is_64bit = true;
+               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
+                              >> KVM_REG_ARM_CRM_SHIFT);
+               params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
+                              >> KVM_REG_ARM_OPC1_SHIFT);
+               params->Op2 = 0;
+               params->CRn = 0;
+               return true;
+       default:
+               return false;
+       }
+}
+
+/* Decode an index value, and find the cp15 coproc_reg entry. */
+static const struct coproc_reg *index_to_coproc_reg(struct kvm_vcpu *vcpu,
+                                                   u64 id)
+{
+       size_t num;
+       const struct coproc_reg *table, *r;
+       struct coproc_params params;
+
+       /* We only do cp15 for now. */
+       if ((id & KVM_REG_ARM_COPROC_MASK) >> KVM_REG_ARM_COPROC_SHIFT != 15)
+               return NULL;
+
+       if (!index_to_params(id, &params))
+               return NULL;
+
+       table = get_target_table(vcpu->arch.target, &num);
+       r = find_reg(&params, table, num);
+       if (!r)
+               r = find_reg(&params, cp15_regs, ARRAY_SIZE(cp15_regs));
+
+       /* Not saved in the cp15 array? */
+       if (r && !r->reg)
+               r = NULL;
+
+       return r;
+}
+
+/*
+ * These are the invariant cp15 registers: we let the guest see the host
+ * versions of these, so they're part of the guest state.
+ *
+ * A future CPU may provide a mechanism to present different values to
+ * the guest, or a future kvm may trap them.
+ */
+/* Unfortunately, there's no register-argument for mrc, so generate. */
+#define FUNCTION_FOR32(crn, crm, op1, op2, name)                       \
+       static void get_##name(struct kvm_vcpu *v,                      \
+                              const struct coproc_reg *r)              \
+       {                                                               \
+               u32 val;                                                \
+                                                                       \
+               asm volatile("mrc p15, " __stringify(op1)               \
+                            ", %0, c" __stringify(crn)                 \
+                            ", c" __stringify(crm)                     \
+                            ", " __stringify(op2) "\n" : "=r" (val));  \
+               ((struct coproc_reg *)r)->val = val;                    \
+       }
+
+FUNCTION_FOR32(0, 0, 0, 0, MIDR)
+FUNCTION_FOR32(0, 0, 0, 1, CTR)
+FUNCTION_FOR32(0, 0, 0, 2, TCMTR)
+FUNCTION_FOR32(0, 0, 0, 3, TLBTR)
+FUNCTION_FOR32(0, 0, 0, 6, REVIDR)
+FUNCTION_FOR32(0, 1, 0, 0, ID_PFR0)
+FUNCTION_FOR32(0, 1, 0, 1, ID_PFR1)
+FUNCTION_FOR32(0, 1, 0, 2, ID_DFR0)
+FUNCTION_FOR32(0, 1, 0, 3, ID_AFR0)
+FUNCTION_FOR32(0, 1, 0, 4, ID_MMFR0)
+FUNCTION_FOR32(0, 1, 0, 5, ID_MMFR1)
+FUNCTION_FOR32(0, 1, 0, 6, ID_MMFR2)
+FUNCTION_FOR32(0, 1, 0, 7, ID_MMFR3)
+FUNCTION_FOR32(0, 2, 0, 0, ID_ISAR0)
+FUNCTION_FOR32(0, 2, 0, 1, ID_ISAR1)
+FUNCTION_FOR32(0, 2, 0, 2, ID_ISAR2)
+FUNCTION_FOR32(0, 2, 0, 3, ID_ISAR3)
+FUNCTION_FOR32(0, 2, 0, 4, ID_ISAR4)
+FUNCTION_FOR32(0, 2, 0, 5, ID_ISAR5)
+FUNCTION_FOR32(0, 0, 1, 1, CLIDR)
+FUNCTION_FOR32(0, 0, 1, 7, AIDR)
+
+/* ->val is filled in by kvm_invariant_coproc_table_init() */
+static struct coproc_reg invariant_cp15[] = {
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 0), is32, NULL, get_MIDR },
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 1), is32, NULL, get_CTR },
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 2), is32, NULL, get_TCMTR },
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 3), is32, NULL, get_TLBTR },
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 6), is32, NULL, get_REVIDR },
+
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 0), is32, NULL, get_ID_PFR0 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 1), is32, NULL, get_ID_PFR1 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 2), is32, NULL, get_ID_DFR0 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 3), is32, NULL, get_ID_AFR0 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 4), is32, NULL, get_ID_MMFR0 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 5), is32, NULL, get_ID_MMFR1 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 6), is32, NULL, get_ID_MMFR2 },
+       { CRn( 0), CRm( 1), Op1( 0), Op2( 7), is32, NULL, get_ID_MMFR3 },
+
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 0), is32, NULL, get_ID_ISAR0 },
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 1), is32, NULL, get_ID_ISAR1 },
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 2), is32, NULL, get_ID_ISAR2 },
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 3), is32, NULL, get_ID_ISAR3 },
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 4), is32, NULL, get_ID_ISAR4 },
+       { CRn( 0), CRm( 2), Op1( 0), Op2( 5), is32, NULL, get_ID_ISAR5 },
+
+       { CRn( 0), CRm( 0), Op1( 1), Op2( 1), is32, NULL, get_CLIDR },
+       { CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
+};
+
+static int reg_from_user(void *val, const void __user *uaddr, u64 id)
+{
+       /* This Just Works because we are little endian. */
+       if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
+               return -EFAULT;
+       return 0;
+}
+
+static int reg_to_user(void __user *uaddr, const void *val, u64 id)
+{
+       /* This Just Works because we are little endian. */
+       if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
+               return -EFAULT;
+       return 0;
+}
+
+static int get_invariant_cp15(u64 id, void __user *uaddr)
+{
+       struct coproc_params params;
+       const struct coproc_reg *r;
+
+       if (!index_to_params(id, &params))
+               return -ENOENT;
+
+       r = find_reg(&params, invariant_cp15, ARRAY_SIZE(invariant_cp15));
+       if (!r)
+               return -ENOENT;
+
+       return reg_to_user(uaddr, &r->val, id);
+}
+
+static int set_invariant_cp15(u64 id, void __user *uaddr)
+{
+       struct coproc_params params;
+       const struct coproc_reg *r;
+       int err;
+       u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
+
+       if (!index_to_params(id, &params))
+               return -ENOENT;
+       r = find_reg(&params, invariant_cp15, ARRAY_SIZE(invariant_cp15));
+       if (!r)
+               return -ENOENT;
+
+       err = reg_from_user(&val, uaddr, id);
+       if (err)
+               return err;
+
+       /* This is what we mean by invariant: you can't change it. */
+       if (r->val != val)
+               return -EINVAL;
+
+       return 0;
+}
+
+static bool is_valid_cache(u32 val)
+{
+       u32 level, ctype;
+
+       if (val >= CSSELR_MAX)
+               return -ENOENT;
+
+       /* Bottom bit is Instruction or Data bit.  Next 3 bits are level. */
+        level = (val >> 1);
+        ctype = (cache_levels >> (level * 3)) & 7;
+
+       switch (ctype) {
+       case 0: /* No cache */
+               return false;
+       case 1: /* Instruction cache only */
+               return (val & 1);
+       case 2: /* Data cache only */
+       case 4: /* Unified cache */
+               return !(val & 1);
+       case 3: /* Separate instruction and data caches */
+               return true;
+       default: /* Reserved: we can't know instruction or data. */
+               return false;
+       }
+}
+
+/* Which cache CCSIDR represents depends on CSSELR value. */
+static u32 get_ccsidr(u32 csselr)
+{
+       u32 ccsidr;
+
+       /* Make sure noone else changes CSSELR during this! */
+       local_irq_disable();
+       /* Put value into CSSELR */
+       asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
+       isb();
+       /* Read result out of CCSIDR */
+       asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
+       local_irq_enable();
+
+       return ccsidr;
+}
+
+static int demux_c15_get(u64 id, void __user *uaddr)
+{
+       u32 val;
+       u32 __user *uval = uaddr;
+
+       /* Fail if we have unknown bits set. */
+       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
+                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
+               return -ENOENT;
+
+       switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
+       case KVM_REG_ARM_DEMUX_ID_CCSIDR:
+               if (KVM_REG_SIZE(id) != 4)
+                       return -ENOENT;
+               val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+                       >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
+               if (!is_valid_cache(val))
+                       return -ENOENT;
+
+               return put_user(get_ccsidr(val), uval);
+       default:
+               return -ENOENT;
+       }
+}
+
+static int demux_c15_set(u64 id, void __user *uaddr)
+{
+       u32 val, newval;
+       u32 __user *uval = uaddr;
+
+       /* Fail if we have unknown bits set. */
+       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
+                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
+               return -ENOENT;
+
+       switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
+       case KVM_REG_ARM_DEMUX_ID_CCSIDR:
+               if (KVM_REG_SIZE(id) != 4)
+                       return -ENOENT;
+               val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
+                       >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
+               if (!is_valid_cache(val))
+                       return -ENOENT;
+
+               if (get_user(newval, uval))
+                       return -EFAULT;
+
+               /* This is also invariant: you can't change it. */
+               if (newval != get_ccsidr(val))
+                       return -EINVAL;
+               return 0;
+       default:
+               return -ENOENT;
+       }
+}
+
+#ifdef CONFIG_VFPv3
+static const int vfp_sysregs[] = { KVM_REG_ARM_VFP_FPEXC,
+                                  KVM_REG_ARM_VFP_FPSCR,
+                                  KVM_REG_ARM_VFP_FPINST,
+                                  KVM_REG_ARM_VFP_FPINST2,
+                                  KVM_REG_ARM_VFP_MVFR0,
+                                  KVM_REG_ARM_VFP_MVFR1,
+                                  KVM_REG_ARM_VFP_FPSID };
+
+static unsigned int num_fp_regs(void)
+{
+       if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK) >> MVFR0_A_SIMD_BIT) == 2)
+               return 32;
+       else
+               return 16;
+}
+
+static unsigned int num_vfp_regs(void)
+{
+       /* Normal FP regs + control regs. */
+       return num_fp_regs() + ARRAY_SIZE(vfp_sysregs);
+}
+
+static int copy_vfp_regids(u64 __user *uindices)
+{
+       unsigned int i;
+       const u64 u32reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP;
+       const u64 u64reg = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+
+       for (i = 0; i < num_fp_regs(); i++) {
+               if (put_user((u64reg | KVM_REG_ARM_VFP_BASE_REG) + i,
+                            uindices))
+                       return -EFAULT;
+               uindices++;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(vfp_sysregs); i++) {
+               if (put_user(u32reg | vfp_sysregs[i], uindices))
+                       return -EFAULT;
+               uindices++;
+       }
+
+       return num_vfp_regs();
+}
+
+static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
+{
+       u32 vfpid = (id & KVM_REG_ARM_VFP_MASK);
+       u32 val;
+
+       /* Fail if we have unknown bits set. */
+       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
+                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
+               return -ENOENT;
+
+       if (vfpid < num_fp_regs()) {
+               if (KVM_REG_SIZE(id) != 8)
+                       return -ENOENT;
+               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpregs[vfpid],
+                                  id);
+       }
+
+       /* FP control registers are all 32 bit. */
+       if (KVM_REG_SIZE(id) != 4)
+               return -ENOENT;
+
+       switch (vfpid) {
+       case KVM_REG_ARM_VFP_FPEXC:
+               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpexc, id);
+       case KVM_REG_ARM_VFP_FPSCR:
+               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpscr, id);
+       case KVM_REG_ARM_VFP_FPINST:
+               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpinst, id);
+       case KVM_REG_ARM_VFP_FPINST2:
+               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpinst2, id);
+       case KVM_REG_ARM_VFP_MVFR0:
+               val = fmrx(MVFR0);
+               return reg_to_user(uaddr, &val, id);
+       case KVM_REG_ARM_VFP_MVFR1:
+               val = fmrx(MVFR1);
+               return reg_to_user(uaddr, &val, id);
+       case KVM_REG_ARM_VFP_FPSID:
+               val = fmrx(FPSID);
+               return reg_to_user(uaddr, &val, id);
+       default:
+               return -ENOENT;
+       }
+}
+
+static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
+{
+       u32 vfpid = (id & KVM_REG_ARM_VFP_MASK);
+       u32 val;
+
+       /* Fail if we have unknown bits set. */
+       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
+                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
+               return -ENOENT;
+
+       if (vfpid < num_fp_regs()) {
+               if (KVM_REG_SIZE(id) != 8)
+                       return -ENOENT;
+               return reg_from_user(&vcpu->arch.vfp_guest.fpregs[vfpid],
+                                    uaddr, id);
+       }
+
+       /* FP control registers are all 32 bit. */
+       if (KVM_REG_SIZE(id) != 4)
+               return -ENOENT;
+
+       switch (vfpid) {
+       case KVM_REG_ARM_VFP_FPEXC:
+               return reg_from_user(&vcpu->arch.vfp_guest.fpexc, uaddr, id);
+       case KVM_REG_ARM_VFP_FPSCR:
+               return reg_from_user(&vcpu->arch.vfp_guest.fpscr, uaddr, id);
+       case KVM_REG_ARM_VFP_FPINST:
+               return reg_from_user(&vcpu->arch.vfp_guest.fpinst, uaddr, id);
+       case KVM_REG_ARM_VFP_FPINST2:
+               return reg_from_user(&vcpu->arch.vfp_guest.fpinst2, uaddr, id);
+       /* These are invariant. */
+       case KVM_REG_ARM_VFP_MVFR0:
+               if (reg_from_user(&val, uaddr, id))
+                       return -EFAULT;
+               if (val != fmrx(MVFR0))
+                       return -EINVAL;
+               return 0;
+       case KVM_REG_ARM_VFP_MVFR1:
+               if (reg_from_user(&val, uaddr, id))
+                       return -EFAULT;
+               if (val != fmrx(MVFR1))
+                       return -EINVAL;
+               return 0;
+       case KVM_REG_ARM_VFP_FPSID:
+               if (reg_from_user(&val, uaddr, id))
+                       return -EFAULT;
+               if (val != fmrx(FPSID))
+                       return -EINVAL;
+               return 0;
+       default:
+               return -ENOENT;
+       }
+}
+#else /* !CONFIG_VFPv3 */
+static unsigned int num_vfp_regs(void)
+{
+       return 0;
+}
+
+static int copy_vfp_regids(u64 __user *uindices)
+{
+       return 0;
+}
+
+static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
+{
+       return -ENOENT;
+}
+
+static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
+{
+       return -ENOENT;
+}
+#endif /* !CONFIG_VFPv3 */
+
+int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       const struct coproc_reg *r;
+       void __user *uaddr = (void __user *)(long)reg->addr;
+
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
+               return demux_c15_get(reg->id, uaddr);
+
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_VFP)
+               return vfp_get_reg(vcpu, reg->id, uaddr);
+
+       r = index_to_coproc_reg(vcpu, reg->id);
+       if (!r)
+               return get_invariant_cp15(reg->id, uaddr);
+
+       /* Note: copies two regs if size is 64 bit. */
+       return reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+}
+
+int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       const struct coproc_reg *r;
+       void __user *uaddr = (void __user *)(long)reg->addr;
+
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
+               return demux_c15_set(reg->id, uaddr);
+
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_VFP)
+               return vfp_set_reg(vcpu, reg->id, uaddr);
+
+       r = index_to_coproc_reg(vcpu, reg->id);
+       if (!r)
+               return set_invariant_cp15(reg->id, uaddr);
+
+       /* Note: copies two regs if size is 64 bit */
+       return reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+}
+
+static unsigned int num_demux_regs(void)
+{
+       unsigned int i, count = 0;
+
+       for (i = 0; i < CSSELR_MAX; i++)
+               if (is_valid_cache(i))
+                       count++;
+
+       return count;
+}
+
+static int write_demux_regids(u64 __user *uindices)
+{
+       u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
+       unsigned int i;
+
+       val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
+       for (i = 0; i < CSSELR_MAX; i++) {
+               if (!is_valid_cache(i))
+                       continue;
+               if (put_user(val | i, uindices))
+                       return -EFAULT;
+               uindices++;
+       }
+       return 0;
+}
+
+static u64 cp15_to_index(const struct coproc_reg *reg)
+{
+       u64 val = KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT);
+       if (reg->is_64) {
+               val |= KVM_REG_SIZE_U64;
+               val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
+               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+       } else {
+               val |= KVM_REG_SIZE_U32;
+               val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
+               val |= (reg->Op2 << KVM_REG_ARM_32_OPC2_SHIFT);
+               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
+               val |= (reg->CRn << KVM_REG_ARM_32_CRN_SHIFT);
+       }
+       return val;
+}
+
+static bool copy_reg_to_user(const struct coproc_reg *reg, u64 __user **uind)
+{
+       if (!*uind)
+               return true;
+
+       if (put_user(cp15_to_index(reg), *uind))
+               return false;
+
+       (*uind)++;
+       return true;
+}
+
+/* Assumed ordered tables, see kvm_coproc_table_init. */
+static int walk_cp15(struct kvm_vcpu *vcpu, u64 __user *uind)
+{
+       const struct coproc_reg *i1, *i2, *end1, *end2;
+       unsigned int total = 0;
+       size_t num;
+
+       /* We check for duplicates here, to allow arch-specific overrides. */
+       i1 = get_target_table(vcpu->arch.target, &num);
+       end1 = i1 + num;
+       i2 = cp15_regs;
+       end2 = cp15_regs + ARRAY_SIZE(cp15_regs);
+
+       BUG_ON(i1 == end1 || i2 == end2);
+
+       /* Walk carefully, as both tables may refer to the same register. */
+       while (i1 || i2) {
+               int cmp = cmp_reg(i1, i2);
+               /* target-specific overrides generic entry. */
+               if (cmp <= 0) {
+                       /* Ignore registers we trap but don't save. */
+                       if (i1->reg) {
+                               if (!copy_reg_to_user(i1, &uind))
+                                       return -EFAULT;
+                               total++;
+                       }
+               } else {
+                       /* Ignore registers we trap but don't save. */
+                       if (i2->reg) {
+                               if (!copy_reg_to_user(i2, &uind))
+                                       return -EFAULT;
+                               total++;
+                       }
+               }
+
+               if (cmp <= 0 && ++i1 == end1)
+                       i1 = NULL;
+               if (cmp >= 0 && ++i2 == end2)
+                       i2 = NULL;
+       }
+       return total;
+}
+
+unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu)
+{
+       return ARRAY_SIZE(invariant_cp15)
+               + num_demux_regs()
+               + num_vfp_regs()
+               + walk_cp15(vcpu, (u64 __user *)NULL);
+}
+
+int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+       unsigned int i;
+       int err;
+
+       /* Then give them all the invariant registers' indices. */
+       for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++) {
+               if (put_user(cp15_to_index(&invariant_cp15[i]), uindices))
+                       return -EFAULT;
+               uindices++;
+       }
+
+       err = walk_cp15(vcpu, uindices);
+       if (err < 0)
+               return err;
+       uindices += err;
+
+       err = copy_vfp_regids(uindices);
+       if (err < 0)
+               return err;
+       uindices += err;
+
+       return write_demux_regids(uindices);
+}
+
+void kvm_coproc_table_init(void)
+{
+       unsigned int i;
+
+       /* Make sure tables are unique and in order. */
+       for (i = 1; i < ARRAY_SIZE(cp15_regs); i++)
+               BUG_ON(cmp_reg(&cp15_regs[i-1], &cp15_regs[i]) >= 0);
+
+       /* We abuse the reset function to overwrite the table itself. */
+       for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++)
+               invariant_cp15[i].reset(NULL, &invariant_cp15[i]);
+
+       /*
+        * CLIDR format is awkward, so clean it up.  See ARM B4.1.20:
+        *
+        *   If software reads the Cache Type fields from Ctype1
+        *   upwards, once it has seen a value of 0b000, no caches
+        *   exist at further-out levels of the hierarchy. So, for
+        *   example, if Ctype3 is the first Cache Type field with a
+        *   value of 0b000, the values of Ctype4 to Ctype7 must be
+        *   ignored.
+        */
+       asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r" (cache_levels));
+       for (i = 0; i < 7; i++)
+               if (((cache_levels >> (i*3)) & 7) == 0)
+                       break;
+       /* Clear all higher bits. */
+       cache_levels &= (1 << (i*3))-1;
+}
+
+/**
+ * kvm_reset_coprocs - sets cp15 registers to reset value
+ * @vcpu: The VCPU pointer
+ *
+ * This function finds the right table above and sets the registers on the
+ * virtual CPU struct to their architecturally defined reset values.
+ */
+void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
+{
+       size_t num;
+       const struct coproc_reg *table;
+
+       /* Catch someone adding a register without putting in reset entry. */
+       memset(vcpu->arch.cp15, 0x42, sizeof(vcpu->arch.cp15));
+
+       /* Generic chip reset first (so target could override). */
+       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
+
+       table = get_target_table(vcpu->arch.target, &num);
+       reset_coproc_regs(vcpu, table, num);
+
+       for (num = 1; num < NR_CP15_REGS; num++)
+               if (vcpu->arch.cp15[num] == 0x42424242)
+                       panic("Didn't reset vcpu->arch.cp15[%zi]", num);
+}
diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h
new file mode 100644 (file)
index 0000000..992adfa
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Authors: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_COPROC_LOCAL_H__
+#define __ARM_KVM_COPROC_LOCAL_H__
+
+struct coproc_params {
+       unsigned long CRn;
+       unsigned long CRm;
+       unsigned long Op1;
+       unsigned long Op2;
+       unsigned long Rt1;
+       unsigned long Rt2;
+       bool is_64bit;
+       bool is_write;
+};
+
+struct coproc_reg {
+       /* MRC/MCR/MRRC/MCRR instruction which accesses it. */
+       unsigned long CRn;
+       unsigned long CRm;
+       unsigned long Op1;
+       unsigned long Op2;
+
+       bool is_64;
+
+       /* Trapped access from guest, if non-NULL. */
+       bool (*access)(struct kvm_vcpu *,
+                      const struct coproc_params *,
+                      const struct coproc_reg *);
+
+       /* Initialization for vcpu. */
+       void (*reset)(struct kvm_vcpu *, const struct coproc_reg *);
+
+       /* Index into vcpu->arch.cp15[], or 0 if we don't need to save it. */
+       unsigned long reg;
+
+       /* Value (usually reset value) */
+       u64 val;
+};
+
+static inline void print_cp_instr(const struct coproc_params *p)
+{
+       /* Look, we even formatted it for you to paste into the table! */
+       if (p->is_64bit) {
+               kvm_pr_unimpl(" { CRm(%2lu), Op1(%2lu), is64, func_%s },\n",
+                             p->CRm, p->Op1, p->is_write ? "write" : "read");
+       } else {
+               kvm_pr_unimpl(" { CRn(%2lu), CRm(%2lu), Op1(%2lu), Op2(%2lu), is32,"
+                             " func_%s },\n",
+                             p->CRn, p->CRm, p->Op1, p->Op2,
+                             p->is_write ? "write" : "read");
+       }
+}
+
+static inline bool ignore_write(struct kvm_vcpu *vcpu,
+                               const struct coproc_params *p)
+{
+       return true;
+}
+
+static inline bool read_zero(struct kvm_vcpu *vcpu,
+                            const struct coproc_params *p)
+{
+       *vcpu_reg(vcpu, p->Rt1) = 0;
+       return true;
+}
+
+static inline bool write_to_read_only(struct kvm_vcpu *vcpu,
+                                     const struct coproc_params *params)
+{
+       kvm_debug("CP15 write to read-only register at: %08x\n",
+                 *vcpu_pc(vcpu));
+       print_cp_instr(params);
+       return false;
+}
+
+static inline bool read_from_write_only(struct kvm_vcpu *vcpu,
+                                       const struct coproc_params *params)
+{
+       kvm_debug("CP15 read to write-only register at: %08x\n",
+                 *vcpu_pc(vcpu));
+       print_cp_instr(params);
+       return false;
+}
+
+/* Reset functions */
+static inline void reset_unknown(struct kvm_vcpu *vcpu,
+                                const struct coproc_reg *r)
+{
+       BUG_ON(!r->reg);
+       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.cp15));
+       vcpu->arch.cp15[r->reg] = 0xdecafbad;
+}
+
+static inline void reset_val(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
+{
+       BUG_ON(!r->reg);
+       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.cp15));
+       vcpu->arch.cp15[r->reg] = r->val;
+}
+
+static inline void reset_unknown64(struct kvm_vcpu *vcpu,
+                                  const struct coproc_reg *r)
+{
+       BUG_ON(!r->reg);
+       BUG_ON(r->reg + 1 >= ARRAY_SIZE(vcpu->arch.cp15));
+
+       vcpu->arch.cp15[r->reg] = 0xdecafbad;
+       vcpu->arch.cp15[r->reg+1] = 0xd0c0ffee;
+}
+
+static inline int cmp_reg(const struct coproc_reg *i1,
+                         const struct coproc_reg *i2)
+{
+       BUG_ON(i1 == i2);
+       if (!i1)
+               return 1;
+       else if (!i2)
+               return -1;
+       if (i1->CRn != i2->CRn)
+               return i1->CRn - i2->CRn;
+       if (i1->CRm != i2->CRm)
+               return i1->CRm - i2->CRm;
+       if (i1->Op1 != i2->Op1)
+               return i1->Op1 - i2->Op1;
+       return i1->Op2 - i2->Op2;
+}
+
+
+#define CRn(_x)                .CRn = _x
+#define CRm(_x)        .CRm = _x
+#define Op1(_x)        .Op1 = _x
+#define Op2(_x)        .Op2 = _x
+#define is64           .is_64 = true
+#define is32           .is_64 = false
+
+#endif /* __ARM_KVM_COPROC_LOCAL_H__ */
diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c
new file mode 100644 (file)
index 0000000..685063a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Authors: Rusty Russell <rusty@rustcorp.au>
+ *          Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <linux/kvm_host.h>
+#include <asm/cputype.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_host.h>
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_coproc.h>
+#include <linux/init.h>
+
+static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
+{
+       /*
+        * Compute guest MPIDR:
+        * (Even if we present only one VCPU to the guest on an SMP
+        * host we don't set the U bit in the MPIDR, or vice versa, as
+        * revealing the underlying hardware properties is likely to
+        * be the best choice).
+        */
+       vcpu->arch.cp15[c0_MPIDR] = (read_cpuid_mpidr() & ~MPIDR_LEVEL_MASK)
+               | (vcpu->vcpu_id & MPIDR_LEVEL_MASK);
+}
+
+#include "coproc.h"
+
+/* A15 TRM 4.3.28: RO WI */
+static bool access_actlr(struct kvm_vcpu *vcpu,
+                        const struct coproc_params *p,
+                        const struct coproc_reg *r)
+{
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+
+       *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
+       return true;
+}
+
+/* A15 TRM 4.3.60: R/O. */
+static bool access_cbar(struct kvm_vcpu *vcpu,
+                       const struct coproc_params *p,
+                       const struct coproc_reg *r)
+{
+       if (p->is_write)
+               return write_to_read_only(vcpu, p);
+       return read_zero(vcpu, p);
+}
+
+/* A15 TRM 4.3.48: R/O WI. */
+static bool access_l2ctlr(struct kvm_vcpu *vcpu,
+                         const struct coproc_params *p,
+                         const struct coproc_reg *r)
+{
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+
+       *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
+       return true;
+}
+
+static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
+{
+       u32 l2ctlr, ncores;
+
+       asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
+       l2ctlr &= ~(3 << 24);
+       ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
+       l2ctlr |= (ncores & 3) << 24;
+
+       vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
+}
+
+static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
+{
+       u32 actlr;
+
+       /* ACTLR contains SMP bit: make sure you create all cpus first! */
+       asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
+       /* Make the SMP bit consistent with the guest configuration */
+       if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
+               actlr |= 1U << 6;
+       else
+               actlr &= ~(1U << 6);
+
+       vcpu->arch.cp15[c1_ACTLR] = actlr;
+}
+
+/* A15 TRM 4.3.49: R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). */
+static bool access_l2ectlr(struct kvm_vcpu *vcpu,
+                          const struct coproc_params *p,
+                          const struct coproc_reg *r)
+{
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+
+       *vcpu_reg(vcpu, p->Rt1) = 0;
+       return true;
+}
+
+/*
+ * A15-specific CP15 registers.
+ * Important: Must be sorted ascending by CRn, CRM, Op1, Op2
+ */
+static const struct coproc_reg a15_regs[] = {
+       /* MPIDR: we use VMPIDR for guest access. */
+       { CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
+                       NULL, reset_mpidr, c0_MPIDR },
+
+       /* SCTLR: swapped by interrupt.S. */
+       { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
+                       NULL, reset_val, c1_SCTLR, 0x00C50078 },
+       /* ACTLR: trapped by HCR.TAC bit. */
+       { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
+                       access_actlr, reset_actlr, c1_ACTLR },
+       /* CPACR: swapped by interrupt.S. */
+       { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
+                       NULL, reset_val, c1_CPACR, 0x00000000 },
+
+       /*
+        * L2CTLR access (guest wants to know #CPUs).
+        */
+       { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
+                       access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
+       { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
+
+       /* The Configuration Base Address Register. */
+       { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
+};
+
+static struct kvm_coproc_target_table a15_target_table = {
+       .target = KVM_ARM_TARGET_CORTEX_A15,
+       .table = a15_regs,
+       .num = ARRAY_SIZE(a15_regs),
+};
+
+static int __init coproc_a15_init(void)
+{
+       unsigned int i;
+
+       for (i = 1; i < ARRAY_SIZE(a15_regs); i++)
+               BUG_ON(cmp_reg(&a15_regs[i-1],
+                              &a15_regs[i]) >= 0);
+
+       kvm_register_target_coproc_table(&a15_target_table);
+       return 0;
+}
+late_initcall(coproc_a15_init);
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
new file mode 100644 (file)
index 0000000..d61450a
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <linux/kvm_host.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_emulate.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+#define VCPU_NR_MODES          6
+#define VCPU_REG_OFFSET_USR    0
+#define VCPU_REG_OFFSET_FIQ    1
+#define VCPU_REG_OFFSET_IRQ    2
+#define VCPU_REG_OFFSET_SVC    3
+#define VCPU_REG_OFFSET_ABT    4
+#define VCPU_REG_OFFSET_UND    5
+#define REG_OFFSET(_reg) \
+       (offsetof(struct kvm_regs, _reg) / sizeof(u32))
+
+#define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num])
+
+static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {
+       /* USR/SYS Registers */
+       [VCPU_REG_OFFSET_USR] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
+               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
+               USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
+       },
+
+       /* FIQ Registers */
+       [VCPU_REG_OFFSET_FIQ] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7),
+               REG_OFFSET(fiq_regs[0]), /* r8 */
+               REG_OFFSET(fiq_regs[1]), /* r9 */
+               REG_OFFSET(fiq_regs[2]), /* r10 */
+               REG_OFFSET(fiq_regs[3]), /* r11 */
+               REG_OFFSET(fiq_regs[4]), /* r12 */
+               REG_OFFSET(fiq_regs[5]), /* r13 */
+               REG_OFFSET(fiq_regs[6]), /* r14 */
+       },
+
+       /* IRQ Registers */
+       [VCPU_REG_OFFSET_IRQ] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
+               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
+               USR_REG_OFFSET(12),
+               REG_OFFSET(irq_regs[0]), /* r13 */
+               REG_OFFSET(irq_regs[1]), /* r14 */
+       },
+
+       /* SVC Registers */
+       [VCPU_REG_OFFSET_SVC] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
+               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
+               USR_REG_OFFSET(12),
+               REG_OFFSET(svc_regs[0]), /* r13 */
+               REG_OFFSET(svc_regs[1]), /* r14 */
+       },
+
+       /* ABT Registers */
+       [VCPU_REG_OFFSET_ABT] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
+               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
+               USR_REG_OFFSET(12),
+               REG_OFFSET(abt_regs[0]), /* r13 */
+               REG_OFFSET(abt_regs[1]), /* r14 */
+       },
+
+       /* UND Registers */
+       [VCPU_REG_OFFSET_UND] = {
+               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
+               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
+               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
+               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
+               USR_REG_OFFSET(12),
+               REG_OFFSET(und_regs[0]), /* r13 */
+               REG_OFFSET(und_regs[1]), /* r14 */
+       },
+};
+
+/*
+ * Return a pointer to the register number valid in the current mode of
+ * the virtual CPU.
+ */
+u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
+{
+       u32 *reg_array = (u32 *)&vcpu->arch.regs;
+       u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
+
+       switch (mode) {
+       case USR_MODE...SVC_MODE:
+               mode &= ~MODE32_BIT; /* 0 ... 3 */
+               break;
+
+       case ABT_MODE:
+               mode = VCPU_REG_OFFSET_ABT;
+               break;
+
+       case UND_MODE:
+               mode = VCPU_REG_OFFSET_UND;
+               break;
+
+       case SYSTEM_MODE:
+               mode = VCPU_REG_OFFSET_USR;
+               break;
+
+       default:
+               BUG();
+       }
+
+       return reg_array + vcpu_reg_offsets[mode][reg_num];
+}
+
+/*
+ * Return the SPSR for the current mode of the virtual CPU.
+ */
+u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
+{
+       u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
+       switch (mode) {
+       case SVC_MODE:
+               return &vcpu->arch.regs.KVM_ARM_SVC_spsr;
+       case ABT_MODE:
+               return &vcpu->arch.regs.KVM_ARM_ABT_spsr;
+       case UND_MODE:
+               return &vcpu->arch.regs.KVM_ARM_UND_spsr;
+       case IRQ_MODE:
+               return &vcpu->arch.regs.KVM_ARM_IRQ_spsr;
+       case FIQ_MODE:
+               return &vcpu->arch.regs.KVM_ARM_FIQ_spsr;
+       default:
+               BUG();
+       }
+}
+
+/**
+ * kvm_handle_wfi - handle a wait-for-interrupts instruction executed by a guest
+ * @vcpu:      the vcpu pointer
+ * @run:       the kvm_run structure pointer
+ *
+ * Simply sets the wait_for_interrupts flag on the vcpu structure, which will
+ * halt execution of world-switches and schedule other host processes until
+ * there is an incoming IRQ or FIQ to the VM.
+ */
+int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       trace_kvm_wfi(*vcpu_pc(vcpu));
+       kvm_vcpu_block(vcpu);
+       return 1;
+}
+
+/**
+ * adjust_itstate - adjust ITSTATE when emulating instructions in IT-block
+ * @vcpu:      The VCPU pointer
+ *
+ * When exceptions occur while instructions are executed in Thumb IF-THEN
+ * blocks, the ITSTATE field of the CPSR is not advanved (updated), so we have
+ * to do this little bit of work manually. The fields map like this:
+ *
+ * IT[7:0] -> CPSR[26:25],CPSR[15:10]
+ */
+static void kvm_adjust_itstate(struct kvm_vcpu *vcpu)
+{
+       unsigned long itbits, cond;
+       unsigned long cpsr = *vcpu_cpsr(vcpu);
+       bool is_arm = !(cpsr & PSR_T_BIT);
+
+       BUG_ON(is_arm && (cpsr & PSR_IT_MASK));
+
+       if (!(cpsr & PSR_IT_MASK))
+               return;
+
+       cond = (cpsr & 0xe000) >> 13;
+       itbits = (cpsr & 0x1c00) >> (10 - 2);
+       itbits |= (cpsr & (0x3 << 25)) >> 25;
+
+       /* Perform ITAdvance (see page A-52 in ARM DDI 0406C) */
+       if ((itbits & 0x7) == 0)
+               itbits = cond = 0;
+       else
+               itbits = (itbits << 1) & 0x1f;
+
+       cpsr &= ~PSR_IT_MASK;
+       cpsr |= cond << 13;
+       cpsr |= (itbits & 0x1c) << (10 - 2);
+       cpsr |= (itbits & 0x3) << 25;
+       *vcpu_cpsr(vcpu) = cpsr;
+}
+
+/**
+ * kvm_skip_instr - skip a trapped instruction and proceed to the next
+ * @vcpu: The vcpu pointer
+ */
+void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
+{
+       bool is_thumb;
+
+       is_thumb = !!(*vcpu_cpsr(vcpu) & PSR_T_BIT);
+       if (is_thumb && !is_wide_instr)
+               *vcpu_pc(vcpu) += 2;
+       else
+               *vcpu_pc(vcpu) += 4;
+       kvm_adjust_itstate(vcpu);
+}
+
+
+/******************************************************************************
+ * Inject exceptions into the guest
+ */
+
+static u32 exc_vector_base(struct kvm_vcpu *vcpu)
+{
+       u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
+       u32 vbar = vcpu->arch.cp15[c12_VBAR];
+
+       if (sctlr & SCTLR_V)
+               return 0xffff0000;
+       else /* always have security exceptions */
+               return vbar;
+}
+
+/**
+ * kvm_inject_undefined - inject an undefined exception into the guest
+ * @vcpu: The VCPU to receive the undefined exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ *
+ * Modelled after TakeUndefInstrException() pseudocode.
+ */
+void kvm_inject_undefined(struct kvm_vcpu *vcpu)
+{
+       u32 new_lr_value;
+       u32 new_spsr_value;
+       u32 cpsr = *vcpu_cpsr(vcpu);
+       u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
+       bool is_thumb = (cpsr & PSR_T_BIT);
+       u32 vect_offset = 4;
+       u32 return_offset = (is_thumb) ? 2 : 4;
+
+       new_spsr_value = cpsr;
+       new_lr_value = *vcpu_pc(vcpu) - return_offset;
+
+       *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | UND_MODE;
+       *vcpu_cpsr(vcpu) |= PSR_I_BIT;
+       *vcpu_cpsr(vcpu) &= ~(PSR_IT_MASK | PSR_J_BIT | PSR_E_BIT | PSR_T_BIT);
+
+       if (sctlr & SCTLR_TE)
+               *vcpu_cpsr(vcpu) |= PSR_T_BIT;
+       if (sctlr & SCTLR_EE)
+               *vcpu_cpsr(vcpu) |= PSR_E_BIT;
+
+       /* Note: These now point to UND banked copies */
+       *vcpu_spsr(vcpu) = cpsr;
+       *vcpu_reg(vcpu, 14) = new_lr_value;
+
+       /* Branch to exception vector */
+       *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
+}
+
+/*
+ * Modelled after TakeDataAbortException() and TakePrefetchAbortException
+ * pseudocode.
+ */
+static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
+{
+       u32 new_lr_value;
+       u32 new_spsr_value;
+       u32 cpsr = *vcpu_cpsr(vcpu);
+       u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
+       bool is_thumb = (cpsr & PSR_T_BIT);
+       u32 vect_offset;
+       u32 return_offset = (is_thumb) ? 4 : 0;
+       bool is_lpae;
+
+       new_spsr_value = cpsr;
+       new_lr_value = *vcpu_pc(vcpu) + return_offset;
+
+       *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | ABT_MODE;
+       *vcpu_cpsr(vcpu) |= PSR_I_BIT | PSR_A_BIT;
+       *vcpu_cpsr(vcpu) &= ~(PSR_IT_MASK | PSR_J_BIT | PSR_E_BIT | PSR_T_BIT);
+
+       if (sctlr & SCTLR_TE)
+               *vcpu_cpsr(vcpu) |= PSR_T_BIT;
+       if (sctlr & SCTLR_EE)
+               *vcpu_cpsr(vcpu) |= PSR_E_BIT;
+
+       /* Note: These now point to ABT banked copies */
+       *vcpu_spsr(vcpu) = cpsr;
+       *vcpu_reg(vcpu, 14) = new_lr_value;
+
+       if (is_pabt)
+               vect_offset = 12;
+       else
+               vect_offset = 16;
+
+       /* Branch to exception vector */
+       *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
+
+       if (is_pabt) {
+               /* Set DFAR and DFSR */
+               vcpu->arch.cp15[c6_IFAR] = addr;
+               is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
+               /* Always give debug fault for now - should give guest a clue */
+               if (is_lpae)
+                       vcpu->arch.cp15[c5_IFSR] = 1 << 9 | 0x22;
+               else
+                       vcpu->arch.cp15[c5_IFSR] = 2;
+       } else { /* !iabt */
+               /* Set DFAR and DFSR */
+               vcpu->arch.cp15[c6_DFAR] = addr;
+               is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
+               /* Always give debug fault for now - should give guest a clue */
+               if (is_lpae)
+                       vcpu->arch.cp15[c5_DFSR] = 1 << 9 | 0x22;
+               else
+                       vcpu->arch.cp15[c5_DFSR] = 2;
+       }
+
+}
+
+/**
+ * kvm_inject_dabt - inject a data abort into the guest
+ * @vcpu: The VCPU to receive the undefined exception
+ * @addr: The address to report in the DFAR
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+       inject_abt(vcpu, false, addr);
+}
+
+/**
+ * kvm_inject_pabt - inject a prefetch abort into the guest
+ * @vcpu: The VCPU to receive the undefined exception
+ * @addr: The address to report in the DFAR
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+       inject_abt(vcpu, true, addr);
+}
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
new file mode 100644 (file)
index 0000000..2339d96
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/kvm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_coproc.h>
+
+#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM }
+#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU }
+
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+       { NULL }
+};
+
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+
+static u64 core_reg_offset_from_id(u64 id)
+{
+       return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
+}
+
+static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       u32 __user *uaddr = (u32 __user *)(long)reg->addr;
+       struct kvm_regs *regs = &vcpu->arch.regs;
+       u64 off;
+
+       if (KVM_REG_SIZE(reg->id) != 4)
+               return -ENOENT;
+
+       /* Our ID is an index into the kvm_regs struct. */
+       off = core_reg_offset_from_id(reg->id);
+       if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
+               return -ENOENT;
+
+       return put_user(((u32 *)regs)[off], uaddr);
+}
+
+static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       u32 __user *uaddr = (u32 __user *)(long)reg->addr;
+       struct kvm_regs *regs = &vcpu->arch.regs;
+       u64 off, val;
+
+       if (KVM_REG_SIZE(reg->id) != 4)
+               return -ENOENT;
+
+       /* Our ID is an index into the kvm_regs struct. */
+       off = core_reg_offset_from_id(reg->id);
+       if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
+               return -ENOENT;
+
+       if (get_user(val, uaddr) != 0)
+               return -EFAULT;
+
+       if (off == KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr)) {
+               unsigned long mode = val & MODE_MASK;
+               switch (mode) {
+               case USR_MODE:
+               case FIQ_MODE:
+               case IRQ_MODE:
+               case SVC_MODE:
+               case ABT_MODE:
+               case UND_MODE:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       ((u32 *)regs)[off] = val;
+       return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+       return -EINVAL;
+}
+
+static unsigned long num_core_regs(void)
+{
+       return sizeof(struct kvm_regs) / sizeof(u32);
+}
+
+/**
+ * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
+ *
+ * This is for all registers.
+ */
+unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
+{
+       return num_core_regs() + kvm_arm_num_coproc_regs(vcpu);
+}
+
+/**
+ * kvm_arm_copy_reg_indices - get indices of all registers.
+ *
+ * We do core registers right here, then we apppend coproc regs.
+ */
+int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+       unsigned int i;
+       const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE;
+
+       for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) {
+               if (put_user(core_reg | i, uindices))
+                       return -EFAULT;
+               uindices++;
+       }
+
+       return kvm_arm_copy_coproc_indices(vcpu, uindices);
+}
+
+int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       /* We currently use nothing arch-specific in upper 32 bits */
+       if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
+               return -EINVAL;
+
+       /* Register group 16 means we want a core register. */
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
+               return get_core_reg(vcpu, reg);
+
+       return kvm_arm_coproc_get_reg(vcpu, reg);
+}
+
+int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+       /* We currently use nothing arch-specific in upper 32 bits */
+       if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
+               return -EINVAL;
+
+       /* Register group 16 means we set a core register. */
+       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
+               return set_core_reg(vcpu, reg);
+
+       return kvm_arm_coproc_set_reg(vcpu, reg);
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+                                 struct kvm_sregs *sregs)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+                                 struct kvm_sregs *sregs)
+{
+       return -EINVAL;
+}
+
+int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
+                       const struct kvm_vcpu_init *init)
+{
+       unsigned int i;
+
+       /* We can only do a cortex A15 for now. */
+       if (init->target != kvm_target_cpu())
+               return -EINVAL;
+
+       vcpu->arch.target = init->target;
+       bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
+
+       /* -ENOENT for unknown features, -EINVAL for invalid combinations. */
+       for (i = 0; i < sizeof(init->features) * 8; i++) {
+               if (test_bit(i, (void *)init->features)) {
+                       if (i >= KVM_VCPU_MAX_FEATURES)
+                               return -ENOENT;
+                       set_bit(i, vcpu->arch.features);
+               }
+       }
+
+       /* Now we know what it is, we can reset it. */
+       return kvm_reset_vcpu(vcpu);
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+       return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+                                 struct kvm_translation *tr)
+{
+       return -EINVAL;
+}
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
new file mode 100644 (file)
index 0000000..9f37a79
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <asm/unified.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+
+/********************************************************************
+ * Hypervisor initialization
+ *   - should be called with:
+ *       r0,r1 = Hypervisor pgd pointer
+ *       r2 = top of Hyp stack (kernel VA)
+ *       r3 = pointer to hyp vectors
+ */
+
+       .text
+       .pushsection    .hyp.idmap.text,"ax"
+       .align 5
+__kvm_hyp_init:
+       .globl __kvm_hyp_init
+
+       @ Hyp-mode exception vector
+       W(b)    .
+       W(b)    .
+       W(b)    .
+       W(b)    .
+       W(b)    .
+       W(b)    __do_hyp_init
+       W(b)    .
+       W(b)    .
+
+__do_hyp_init:
+       @ Set the HTTBR to point to the hypervisor PGD pointer passed
+       mcrr    p15, 4, r0, r1, c2
+
+       @ Set the HTCR and VTCR to the same shareability and cacheability
+       @ settings as the non-secure TTBCR and with T0SZ == 0.
+       mrc     p15, 4, r0, c2, c0, 2   @ HTCR
+       ldr     r12, =HTCR_MASK
+       bic     r0, r0, r12
+       mrc     p15, 0, r1, c2, c0, 2   @ TTBCR
+       and     r1, r1, #(HTCR_MASK & ~TTBCR_T0SZ)
+       orr     r0, r0, r1
+       mcr     p15, 4, r0, c2, c0, 2   @ HTCR
+
+       mrc     p15, 4, r1, c2, c1, 2   @ VTCR
+       ldr     r12, =VTCR_MASK
+       bic     r1, r1, r12
+       bic     r0, r0, #(~VTCR_HTCR_SH)        @ clear non-reusable HTCR bits
+       orr     r1, r0, r1
+       orr     r1, r1, #(KVM_VTCR_SL0 | KVM_VTCR_T0SZ | KVM_VTCR_S)
+       mcr     p15, 4, r1, c2, c1, 2   @ VTCR
+
+       @ Use the same memory attributes for hyp. accesses as the kernel
+       @ (copy MAIRx ro HMAIRx).
+       mrc     p15, 0, r0, c10, c2, 0
+       mcr     p15, 4, r0, c10, c2, 0
+       mrc     p15, 0, r0, c10, c2, 1
+       mcr     p15, 4, r0, c10, c2, 1
+
+       @ Set the HSCTLR to:
+       @  - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
+       @  - Endianness: Kernel config
+       @  - Fast Interrupt Features: Kernel config
+       @  - Write permission implies XN: disabled
+       @  - Instruction cache: enabled
+       @  - Data/Unified cache: enabled
+       @  - Memory alignment checks: enabled
+       @  - MMU: enabled (this code must be run from an identity mapping)
+       mrc     p15, 4, r0, c1, c0, 0   @ HSCR
+       ldr     r12, =HSCTLR_MASK
+       bic     r0, r0, r12
+       mrc     p15, 0, r1, c1, c0, 0   @ SCTLR
+       ldr     r12, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
+       and     r1, r1, r12
+ ARM(  ldr     r12, =(HSCTLR_M | HSCTLR_A)                     )
+ THUMB(        ldr     r12, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE)         )
+       orr     r1, r1, r12
+       orr     r0, r0, r1
+       isb
+       mcr     p15, 4, r0, c1, c0, 0   @ HSCR
+       isb
+
+       @ Set stack pointer and return to the kernel
+       mov     sp, r2
+
+       @ Set HVBAR to point to the HYP vectors
+       mcr     p15, 4, r3, c12, c0, 0  @ HVBAR
+
+       eret
+
+       .ltorg
+
+       .globl __kvm_hyp_init_end
+__kvm_hyp_init_end:
+
+       .popsection
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
new file mode 100644 (file)
index 0000000..c5400d2
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/unified.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_arm.h>
+#include <asm/vfpmacros.h>
+#include "interrupts_head.S"
+
+       .text
+
+__kvm_hyp_code_start:
+       .globl __kvm_hyp_code_start
+
+/********************************************************************
+ * Flush per-VMID TLBs
+ *
+ * void __kvm_tlb_flush_vmid(struct kvm *kvm);
+ *
+ * We rely on the hardware to broadcast the TLB invalidation to all CPUs
+ * inside the inner-shareable domain (which is the case for all v7
+ * implementations).  If we come across a non-IS SMP implementation, we'll
+ * have to use an IPI based mechanism. Until then, we stick to the simple
+ * hardware assisted version.
+ */
+ENTRY(__kvm_tlb_flush_vmid)
+       push    {r2, r3}
+
+       add     r0, r0, #KVM_VTTBR
+       ldrd    r2, r3, [r0]
+       mcrr    p15, 6, r2, r3, c2      @ Write VTTBR
+       isb
+       mcr     p15, 0, r0, c8, c3, 0   @ TLBIALLIS (rt ignored)
+       dsb
+       isb
+       mov     r2, #0
+       mov     r3, #0
+       mcrr    p15, 6, r2, r3, c2      @ Back to VMID #0
+       isb                             @ Not necessary if followed by eret
+
+       pop     {r2, r3}
+       bx      lr
+ENDPROC(__kvm_tlb_flush_vmid)
+
+/********************************************************************
+ * Flush TLBs and instruction caches of all CPUs inside the inner-shareable
+ * domain, for all VMIDs
+ *
+ * void __kvm_flush_vm_context(void);
+ */
+ENTRY(__kvm_flush_vm_context)
+       mov     r0, #0                  @ rn parameter for c15 flushes is SBZ
+
+       /* Invalidate NS Non-Hyp TLB Inner Shareable (TLBIALLNSNHIS) */
+       mcr     p15, 4, r0, c8, c3, 4
+       /* Invalidate instruction caches Inner Shareable (ICIALLUIS) */
+       mcr     p15, 0, r0, c7, c1, 0
+       dsb
+       isb                             @ Not necessary if followed by eret
+
+       bx      lr
+ENDPROC(__kvm_flush_vm_context)
+
+
+/********************************************************************
+ *  Hypervisor world-switch code
+ *
+ *
+ * int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
+ */
+ENTRY(__kvm_vcpu_run)
+       @ Save the vcpu pointer
+       mcr     p15, 4, vcpu, c13, c0, 2        @ HTPIDR
+
+       save_host_regs
+
+       @ Store hardware CP15 state and load guest state
+       read_cp15_state store_to_vcpu = 0
+       write_cp15_state read_from_vcpu = 1
+
+       @ If the host kernel has not been configured with VFPv3 support,
+       @ then it is safer if we deny guests from using it as well.
+#ifdef CONFIG_VFPv3
+       @ Set FPEXC_EN so the guest doesn't trap floating point instructions
+       VFPFMRX r2, FPEXC               @ VMRS
+       push    {r2}
+       orr     r2, r2, #FPEXC_EN
+       VFPFMXR FPEXC, r2               @ VMSR
+#endif
+
+       @ Configure Hyp-role
+       configure_hyp_role vmentry
+
+       @ Trap coprocessor CRx accesses
+       set_hstr vmentry
+       set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
+       set_hdcr vmentry
+
+       @ Write configured ID register into MIDR alias
+       ldr     r1, [vcpu, #VCPU_MIDR]
+       mcr     p15, 4, r1, c0, c0, 0
+
+       @ Write guest view of MPIDR into VMPIDR
+       ldr     r1, [vcpu, #CP15_OFFSET(c0_MPIDR)]
+       mcr     p15, 4, r1, c0, c0, 5
+
+       @ Set up guest memory translation
+       ldr     r1, [vcpu, #VCPU_KVM]
+       add     r1, r1, #KVM_VTTBR
+       ldrd    r2, r3, [r1]
+       mcrr    p15, 6, r2, r3, c2      @ Write VTTBR
+
+       @ We're all done, just restore the GPRs and go to the guest
+       restore_guest_regs
+       clrex                           @ Clear exclusive monitor
+       eret
+
+__kvm_vcpu_return:
+       /*
+        * return convention:
+        * guest r0, r1, r2 saved on the stack
+        * r0: vcpu pointer
+        * r1: exception code
+        */
+       save_guest_regs
+
+       @ Set VMID == 0
+       mov     r2, #0
+       mov     r3, #0
+       mcrr    p15, 6, r2, r3, c2      @ Write VTTBR
+
+       @ Don't trap coprocessor accesses for host kernel
+       set_hstr vmexit
+       set_hdcr vmexit
+       set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
+
+#ifdef CONFIG_VFPv3
+       @ Save floating point registers we if let guest use them.
+       tst     r2, #(HCPTR_TCP(10) | HCPTR_TCP(11))
+       bne     after_vfp_restore
+
+       @ Switch VFP/NEON hardware state to the host's
+       add     r7, vcpu, #VCPU_VFP_GUEST
+       store_vfp_state r7
+       add     r7, vcpu, #VCPU_VFP_HOST
+       ldr     r7, [r7]
+       restore_vfp_state r7
+
+after_vfp_restore:
+       @ Restore FPEXC_EN which we clobbered on entry
+       pop     {r2}
+       VFPFMXR FPEXC, r2
+#endif
+
+       @ Reset Hyp-role
+       configure_hyp_role vmexit
+
+       @ Let host read hardware MIDR
+       mrc     p15, 0, r2, c0, c0, 0
+       mcr     p15, 4, r2, c0, c0, 0
+
+       @ Back to hardware MPIDR
+       mrc     p15, 0, r2, c0, c0, 5
+       mcr     p15, 4, r2, c0, c0, 5
+
+       @ Store guest CP15 state and restore host state
+       read_cp15_state store_to_vcpu = 1
+       write_cp15_state read_from_vcpu = 0
+
+       restore_host_regs
+       clrex                           @ Clear exclusive monitor
+       mov     r0, r1                  @ Return the return code
+       mov     r1, #0                  @ Clear upper bits in return value
+       bx      lr                      @ return to IOCTL
+
+/********************************************************************
+ *  Call function in Hyp mode
+ *
+ *
+ * u64 kvm_call_hyp(void *hypfn, ...);
+ *
+ * This is not really a variadic function in the classic C-way and care must
+ * be taken when calling this to ensure parameters are passed in registers
+ * only, since the stack will change between the caller and the callee.
+ *
+ * Call the function with the first argument containing a pointer to the
+ * function you wish to call in Hyp mode, and subsequent arguments will be
+ * passed as r0, r1, and r2 (a maximum of 3 arguments in addition to the
+ * function pointer can be passed).  The function being called must be mapped
+ * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
+ * passed in r0 and r1.
+ *
+ * The calling convention follows the standard AAPCS:
+ *   r0 - r3: caller save
+ *   r12:     caller save
+ *   rest:    callee save
+ */
+ENTRY(kvm_call_hyp)
+       hvc     #0
+       bx      lr
+
+/********************************************************************
+ * Hypervisor exception vector and handlers
+ *
+ *
+ * The KVM/ARM Hypervisor ABI is defined as follows:
+ *
+ * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
+ * instruction is issued since all traps are disabled when running the host
+ * kernel as per the Hyp-mode initialization at boot time.
+ *
+ * HVC instructions cause a trap to the vector page + offset 0x18 (see hyp_hvc
+ * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
+ * host kernel) and they cause a trap to the vector page + offset 0xc when HVC
+ * instructions are called from within Hyp-mode.
+ *
+ * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
+ *    Switching to Hyp mode is done through a simple HVC #0 instruction. The
+ *    exception vector code will check that the HVC comes from VMID==0 and if
+ *    so will push the necessary state (SPSR, lr_usr) on the Hyp stack.
+ *    - r0 contains a pointer to a HYP function
+ *    - r1, r2, and r3 contain arguments to the above function.
+ *    - The HYP function will be called with its arguments in r0, r1 and r2.
+ *    On HYP function return, we return directly to SVC.
+ *
+ * Note that the above is used to execute code in Hyp-mode from a host-kernel
+ * point of view, and is a different concept from performing a world-switch and
+ * executing guest code SVC mode (with a VMID != 0).
+ */
+
+/* Handle undef, svc, pabt, or dabt by crashing with a user notice */
+.macro bad_exception exception_code, panic_str
+       push    {r0-r2}
+       mrrc    p15, 6, r0, r1, c2      @ Read VTTBR
+       lsr     r1, r1, #16
+       ands    r1, r1, #0xff
+       beq     99f
+
+       load_vcpu                       @ Load VCPU pointer
+       .if \exception_code == ARM_EXCEPTION_DATA_ABORT
+       mrc     p15, 4, r2, c5, c2, 0   @ HSR
+       mrc     p15, 4, r1, c6, c0, 0   @ HDFAR
+       str     r2, [vcpu, #VCPU_HSR]
+       str     r1, [vcpu, #VCPU_HxFAR]
+       .endif
+       .if \exception_code == ARM_EXCEPTION_PREF_ABORT
+       mrc     p15, 4, r2, c5, c2, 0   @ HSR
+       mrc     p15, 4, r1, c6, c0, 2   @ HIFAR
+       str     r2, [vcpu, #VCPU_HSR]
+       str     r1, [vcpu, #VCPU_HxFAR]
+       .endif
+       mov     r1, #\exception_code
+       b       __kvm_vcpu_return
+
+       @ We were in the host already. Let's craft a panic-ing return to SVC.
+99:    mrs     r2, cpsr
+       bic     r2, r2, #MODE_MASK
+       orr     r2, r2, #SVC_MODE
+THUMB( orr     r2, r2, #PSR_T_BIT      )
+       msr     spsr_cxsf, r2
+       mrs     r1, ELR_hyp
+       ldr     r2, =BSYM(panic)
+       msr     ELR_hyp, r2
+       ldr     r0, =\panic_str
+       eret
+.endm
+
+       .text
+
+       .align 5
+__kvm_hyp_vector:
+       .globl __kvm_hyp_vector
+
+       @ Hyp-mode exception vector
+       W(b)    hyp_reset
+       W(b)    hyp_undef
+       W(b)    hyp_svc
+       W(b)    hyp_pabt
+       W(b)    hyp_dabt
+       W(b)    hyp_hvc
+       W(b)    hyp_irq
+       W(b)    hyp_fiq
+
+       .align
+hyp_reset:
+       b       hyp_reset
+
+       .align
+hyp_undef:
+       bad_exception ARM_EXCEPTION_UNDEFINED, und_die_str
+
+       .align
+hyp_svc:
+       bad_exception ARM_EXCEPTION_HVC, svc_die_str
+
+       .align
+hyp_pabt:
+       bad_exception ARM_EXCEPTION_PREF_ABORT, pabt_die_str
+
+       .align
+hyp_dabt:
+       bad_exception ARM_EXCEPTION_DATA_ABORT, dabt_die_str
+
+       .align
+hyp_hvc:
+       /*
+        * Getting here is either becuase of a trap from a guest or from calling
+        * HVC from the host kernel, which means "switch to Hyp mode".
+        */
+       push    {r0, r1, r2}
+
+       @ Check syndrome register
+       mrc     p15, 4, r1, c5, c2, 0   @ HSR
+       lsr     r0, r1, #HSR_EC_SHIFT
+#ifdef CONFIG_VFPv3
+       cmp     r0, #HSR_EC_CP_0_13
+       beq     switch_to_guest_vfp
+#endif
+       cmp     r0, #HSR_EC_HVC
+       bne     guest_trap              @ Not HVC instr.
+
+       /*
+        * Let's check if the HVC came from VMID 0 and allow simple
+        * switch to Hyp mode
+        */
+       mrrc    p15, 6, r0, r2, c2
+       lsr     r2, r2, #16
+       and     r2, r2, #0xff
+       cmp     r2, #0
+       bne     guest_trap              @ Guest called HVC
+
+host_switch_to_hyp:
+       pop     {r0, r1, r2}
+
+       push    {lr}
+       mrs     lr, SPSR
+       push    {lr}
+
+       mov     lr, r0
+       mov     r0, r1
+       mov     r1, r2
+       mov     r2, r3
+
+THUMB( orr     lr, #1)
+       blx     lr                      @ Call the HYP function
+
+       pop     {lr}
+       msr     SPSR_csxf, lr
+       pop     {lr}
+       eret
+
+guest_trap:
+       load_vcpu                       @ Load VCPU pointer to r0
+       str     r1, [vcpu, #VCPU_HSR]
+
+       @ Check if we need the fault information
+       lsr     r1, r1, #HSR_EC_SHIFT
+       cmp     r1, #HSR_EC_IABT
+       mrceq   p15, 4, r2, c6, c0, 2   @ HIFAR
+       beq     2f
+       cmp     r1, #HSR_EC_DABT
+       bne     1f
+       mrc     p15, 4, r2, c6, c0, 0   @ HDFAR
+
+2:     str     r2, [vcpu, #VCPU_HxFAR]
+
+       /*
+        * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
+        *
+        * Abort on the stage 2 translation for a memory access from a
+        * Non-secure PL1 or PL0 mode:
+        *
+        * For any Access flag fault or Translation fault, and also for any
+        * Permission fault on the stage 2 translation of a memory access
+        * made as part of a translation table walk for a stage 1 translation,
+        * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
+        * is UNKNOWN.
+        */
+
+       /* Check for permission fault, and S1PTW */
+       mrc     p15, 4, r1, c5, c2, 0   @ HSR
+       and     r0, r1, #HSR_FSC_TYPE
+       cmp     r0, #FSC_PERM
+       tsteq   r1, #(1 << 7)           @ S1PTW
+       mrcne   p15, 4, r2, c6, c0, 4   @ HPFAR
+       bne     3f
+
+       /* Resolve IPA using the xFAR */
+       mcr     p15, 0, r2, c7, c8, 0   @ ATS1CPR
+       isb
+       mrrc    p15, 0, r0, r1, c7      @ PAR
+       tst     r0, #1
+       bne     4f                      @ Failed translation
+       ubfx    r2, r0, #12, #20
+       lsl     r2, r2, #4
+       orr     r2, r2, r1, lsl #24
+
+3:     load_vcpu                       @ Load VCPU pointer to r0
+       str     r2, [r0, #VCPU_HPFAR]
+
+1:     mov     r1, #ARM_EXCEPTION_HVC
+       b       __kvm_vcpu_return
+
+4:     pop     {r0, r1, r2}            @ Failed translation, return to guest
+       eret
+
+/*
+ * If VFPv3 support is not available, then we will not switch the VFP
+ * registers; however cp10 and cp11 accesses will still trap and fallback
+ * to the regular coprocessor emulation code, which currently will
+ * inject an undefined exception to the guest.
+ */
+#ifdef CONFIG_VFPv3
+switch_to_guest_vfp:
+       load_vcpu                       @ Load VCPU pointer to r0
+       push    {r3-r7}
+
+       @ NEON/VFP used.  Turn on VFP access.
+       set_hcptr vmexit, (HCPTR_TCP(10) | HCPTR_TCP(11))
+
+       @ Switch VFP/NEON hardware state to the guest's
+       add     r7, r0, #VCPU_VFP_HOST
+       ldr     r7, [r7]
+       store_vfp_state r7
+       add     r7, r0, #VCPU_VFP_GUEST
+       restore_vfp_state r7
+
+       pop     {r3-r7}
+       pop     {r0-r2}
+       eret
+#endif
+
+       .align
+hyp_irq:
+       push    {r0, r1, r2}
+       mov     r1, #ARM_EXCEPTION_IRQ
+       load_vcpu                       @ Load VCPU pointer to r0
+       b       __kvm_vcpu_return
+
+       .align
+hyp_fiq:
+       b       hyp_fiq
+
+       .ltorg
+
+__kvm_hyp_code_end:
+       .globl  __kvm_hyp_code_end
+
+       .section ".rodata"
+
+und_die_str:
+       .ascii  "unexpected undefined exception in Hyp mode at: %#08x"
+pabt_die_str:
+       .ascii  "unexpected prefetch abort in Hyp mode at: %#08x"
+dabt_die_str:
+       .ascii  "unexpected data abort in Hyp mode at: %#08x"
+svc_die_str:
+       .ascii  "unexpected HVC/SVC trap in Hyp mode at: %#08x"
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
new file mode 100644 (file)
index 0000000..6a95d34
--- /dev/null
@@ -0,0 +1,441 @@
+#define VCPU_USR_REG(_reg_nr)  (VCPU_USR_REGS + (_reg_nr * 4))
+#define VCPU_USR_SP            (VCPU_USR_REG(13))
+#define VCPU_USR_LR            (VCPU_USR_REG(14))
+#define CP15_OFFSET(_cp15_reg_idx) (VCPU_CP15 + (_cp15_reg_idx * 4))
+
+/*
+ * Many of these macros need to access the VCPU structure, which is always
+ * held in r0. These macros should never clobber r1, as it is used to hold the
+ * exception code on the return path (except of course the macro that switches
+ * all the registers before the final jump to the VM).
+ */
+vcpu   .req    r0              @ vcpu pointer always in r0
+
+/* Clobbers {r2-r6} */
+.macro store_vfp_state vfp_base
+       @ The VFPFMRX and VFPFMXR macros are the VMRS and VMSR instructions
+       VFPFMRX r2, FPEXC
+       @ Make sure VFP is enabled so we can touch the registers.
+       orr     r6, r2, #FPEXC_EN
+       VFPFMXR FPEXC, r6
+
+       VFPFMRX r3, FPSCR
+       tst     r2, #FPEXC_EX           @ Check for VFP Subarchitecture
+       beq     1f
+       @ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
+       @ we only need to save them if FPEXC_EX is set.
+       VFPFMRX r4, FPINST
+       tst     r2, #FPEXC_FP2V
+       VFPFMRX r5, FPINST2, ne         @ vmrsne
+       bic     r6, r2, #FPEXC_EX       @ FPEXC_EX disable
+       VFPFMXR FPEXC, r6
+1:
+       VFPFSTMIA \vfp_base, r6         @ Save VFP registers
+       stm     \vfp_base, {r2-r5}      @ Save FPEXC, FPSCR, FPINST, FPINST2
+.endm
+
+/* Assume FPEXC_EN is on and FPEXC_EX is off, clobbers {r2-r6} */
+.macro restore_vfp_state vfp_base
+       VFPFLDMIA \vfp_base, r6         @ Load VFP registers
+       ldm     \vfp_base, {r2-r5}      @ Load FPEXC, FPSCR, FPINST, FPINST2
+
+       VFPFMXR FPSCR, r3
+       tst     r2, #FPEXC_EX           @ Check for VFP Subarchitecture
+       beq     1f
+       VFPFMXR FPINST, r4
+       tst     r2, #FPEXC_FP2V
+       VFPFMXR FPINST2, r5, ne
+1:
+       VFPFMXR FPEXC, r2       @ FPEXC (last, in case !EN)
+.endm
+
+/* These are simply for the macros to work - value don't have meaning */
+.equ usr, 0
+.equ svc, 1
+.equ abt, 2
+.equ und, 3
+.equ irq, 4
+.equ fiq, 5
+
+.macro push_host_regs_mode mode
+       mrs     r2, SP_\mode
+       mrs     r3, LR_\mode
+       mrs     r4, SPSR_\mode
+       push    {r2, r3, r4}
+.endm
+
+/*
+ * Store all host persistent registers on the stack.
+ * Clobbers all registers, in all modes, except r0 and r1.
+ */
+.macro save_host_regs
+       /* Hyp regs. Only ELR_hyp (SPSR_hyp already saved) */
+       mrs     r2, ELR_hyp
+       push    {r2}
+
+       /* usr regs */
+       push    {r4-r12}        @ r0-r3 are always clobbered
+       mrs     r2, SP_usr
+       mov     r3, lr
+       push    {r2, r3}
+
+       push_host_regs_mode svc
+       push_host_regs_mode abt
+       push_host_regs_mode und
+       push_host_regs_mode irq
+
+       /* fiq regs */
+       mrs     r2, r8_fiq
+       mrs     r3, r9_fiq
+       mrs     r4, r10_fiq
+       mrs     r5, r11_fiq
+       mrs     r6, r12_fiq
+       mrs     r7, SP_fiq
+       mrs     r8, LR_fiq
+       mrs     r9, SPSR_fiq
+       push    {r2-r9}
+.endm
+
+.macro pop_host_regs_mode mode
+       pop     {r2, r3, r4}
+       msr     SP_\mode, r2
+       msr     LR_\mode, r3
+       msr     SPSR_\mode, r4
+.endm
+
+/*
+ * Restore all host registers from the stack.
+ * Clobbers all registers, in all modes, except r0 and r1.
+ */
+.macro restore_host_regs
+       pop     {r2-r9}
+       msr     r8_fiq, r2
+       msr     r9_fiq, r3
+       msr     r10_fiq, r4
+       msr     r11_fiq, r5
+       msr     r12_fiq, r6
+       msr     SP_fiq, r7
+       msr     LR_fiq, r8
+       msr     SPSR_fiq, r9
+
+       pop_host_regs_mode irq
+       pop_host_regs_mode und
+       pop_host_regs_mode abt
+       pop_host_regs_mode svc
+
+       pop     {r2, r3}
+       msr     SP_usr, r2
+       mov     lr, r3
+       pop     {r4-r12}
+
+       pop     {r2}
+       msr     ELR_hyp, r2
+.endm
+
+/*
+ * Restore SP, LR and SPSR for a given mode. offset is the offset of
+ * this mode's registers from the VCPU base.
+ *
+ * Assumes vcpu pointer in vcpu reg
+ *
+ * Clobbers r1, r2, r3, r4.
+ */
+.macro restore_guest_regs_mode mode, offset
+       add     r1, vcpu, \offset
+       ldm     r1, {r2, r3, r4}
+       msr     SP_\mode, r2
+       msr     LR_\mode, r3
+       msr     SPSR_\mode, r4
+.endm
+
+/*
+ * Restore all guest registers from the vcpu struct.
+ *
+ * Assumes vcpu pointer in vcpu reg
+ *
+ * Clobbers *all* registers.
+ */
+.macro restore_guest_regs
+       restore_guest_regs_mode svc, #VCPU_SVC_REGS
+       restore_guest_regs_mode abt, #VCPU_ABT_REGS
+       restore_guest_regs_mode und, #VCPU_UND_REGS
+       restore_guest_regs_mode irq, #VCPU_IRQ_REGS
+
+       add     r1, vcpu, #VCPU_FIQ_REGS
+       ldm     r1, {r2-r9}
+       msr     r8_fiq, r2
+       msr     r9_fiq, r3
+       msr     r10_fiq, r4
+       msr     r11_fiq, r5
+       msr     r12_fiq, r6
+       msr     SP_fiq, r7
+       msr     LR_fiq, r8
+       msr     SPSR_fiq, r9
+
+       @ Load return state
+       ldr     r2, [vcpu, #VCPU_PC]
+       ldr     r3, [vcpu, #VCPU_CPSR]
+       msr     ELR_hyp, r2
+       msr     SPSR_cxsf, r3
+
+       @ Load user registers
+       ldr     r2, [vcpu, #VCPU_USR_SP]
+       ldr     r3, [vcpu, #VCPU_USR_LR]
+       msr     SP_usr, r2
+       mov     lr, r3
+       add     vcpu, vcpu, #(VCPU_USR_REGS)
+       ldm     vcpu, {r0-r12}
+.endm
+
+/*
+ * Save SP, LR and SPSR for a given mode. offset is the offset of
+ * this mode's registers from the VCPU base.
+ *
+ * Assumes vcpu pointer in vcpu reg
+ *
+ * Clobbers r2, r3, r4, r5.
+ */
+.macro save_guest_regs_mode mode, offset
+       add     r2, vcpu, \offset
+       mrs     r3, SP_\mode
+       mrs     r4, LR_\mode
+       mrs     r5, SPSR_\mode
+       stm     r2, {r3, r4, r5}
+.endm
+
+/*
+ * Save all guest registers to the vcpu struct
+ * Expects guest's r0, r1, r2 on the stack.
+ *
+ * Assumes vcpu pointer in vcpu reg
+ *
+ * Clobbers r2, r3, r4, r5.
+ */
+.macro save_guest_regs
+       @ Store usr registers
+       add     r2, vcpu, #VCPU_USR_REG(3)
+       stm     r2, {r3-r12}
+       add     r2, vcpu, #VCPU_USR_REG(0)
+       pop     {r3, r4, r5}            @ r0, r1, r2
+       stm     r2, {r3, r4, r5}
+       mrs     r2, SP_usr
+       mov     r3, lr
+       str     r2, [vcpu, #VCPU_USR_SP]
+       str     r3, [vcpu, #VCPU_USR_LR]
+
+       @ Store return state
+       mrs     r2, ELR_hyp
+       mrs     r3, spsr
+       str     r2, [vcpu, #VCPU_PC]
+       str     r3, [vcpu, #VCPU_CPSR]
+
+       @ Store other guest registers
+       save_guest_regs_mode svc, #VCPU_SVC_REGS
+       save_guest_regs_mode abt, #VCPU_ABT_REGS
+       save_guest_regs_mode und, #VCPU_UND_REGS
+       save_guest_regs_mode irq, #VCPU_IRQ_REGS
+.endm
+
+/* Reads cp15 registers from hardware and stores them in memory
+ * @store_to_vcpu: If 0, registers are written in-order to the stack,
+ *                otherwise to the VCPU struct pointed to by vcpup
+ *
+ * Assumes vcpu pointer in vcpu reg
+ *
+ * Clobbers r2 - r12
+ */
+.macro read_cp15_state store_to_vcpu
+       mrc     p15, 0, r2, c1, c0, 0   @ SCTLR
+       mrc     p15, 0, r3, c1, c0, 2   @ CPACR
+       mrc     p15, 0, r4, c2, c0, 2   @ TTBCR
+       mrc     p15, 0, r5, c3, c0, 0   @ DACR
+       mrrc    p15, 0, r6, r7, c2      @ TTBR 0
+       mrrc    p15, 1, r8, r9, c2      @ TTBR 1
+       mrc     p15, 0, r10, c10, c2, 0 @ PRRR
+       mrc     p15, 0, r11, c10, c2, 1 @ NMRR
+       mrc     p15, 2, r12, c0, c0, 0  @ CSSELR
+
+       .if \store_to_vcpu == 0
+       push    {r2-r12}                @ Push CP15 registers
+       .else
+       str     r2, [vcpu, #CP15_OFFSET(c1_SCTLR)]
+       str     r3, [vcpu, #CP15_OFFSET(c1_CPACR)]
+       str     r4, [vcpu, #CP15_OFFSET(c2_TTBCR)]
+       str     r5, [vcpu, #CP15_OFFSET(c3_DACR)]
+       add     r2, vcpu, #CP15_OFFSET(c2_TTBR0)
+       strd    r6, r7, [r2]
+       add     r2, vcpu, #CP15_OFFSET(c2_TTBR1)
+       strd    r8, r9, [r2]
+       str     r10, [vcpu, #CP15_OFFSET(c10_PRRR)]
+       str     r11, [vcpu, #CP15_OFFSET(c10_NMRR)]
+       str     r12, [vcpu, #CP15_OFFSET(c0_CSSELR)]
+       .endif
+
+       mrc     p15, 0, r2, c13, c0, 1  @ CID
+       mrc     p15, 0, r3, c13, c0, 2  @ TID_URW
+       mrc     p15, 0, r4, c13, c0, 3  @ TID_URO
+       mrc     p15, 0, r5, c13, c0, 4  @ TID_PRIV
+       mrc     p15, 0, r6, c5, c0, 0   @ DFSR
+       mrc     p15, 0, r7, c5, c0, 1   @ IFSR
+       mrc     p15, 0, r8, c5, c1, 0   @ ADFSR
+       mrc     p15, 0, r9, c5, c1, 1   @ AIFSR
+       mrc     p15, 0, r10, c6, c0, 0  @ DFAR
+       mrc     p15, 0, r11, c6, c0, 2  @ IFAR
+       mrc     p15, 0, r12, c12, c0, 0 @ VBAR
+
+       .if \store_to_vcpu == 0
+       push    {r2-r12}                @ Push CP15 registers
+       .else
+       str     r2, [vcpu, #CP15_OFFSET(c13_CID)]
+       str     r3, [vcpu, #CP15_OFFSET(c13_TID_URW)]
+       str     r4, [vcpu, #CP15_OFFSET(c13_TID_URO)]
+       str     r5, [vcpu, #CP15_OFFSET(c13_TID_PRIV)]
+       str     r6, [vcpu, #CP15_OFFSET(c5_DFSR)]
+       str     r7, [vcpu, #CP15_OFFSET(c5_IFSR)]
+       str     r8, [vcpu, #CP15_OFFSET(c5_ADFSR)]
+       str     r9, [vcpu, #CP15_OFFSET(c5_AIFSR)]
+       str     r10, [vcpu, #CP15_OFFSET(c6_DFAR)]
+       str     r11, [vcpu, #CP15_OFFSET(c6_IFAR)]
+       str     r12, [vcpu, #CP15_OFFSET(c12_VBAR)]
+       .endif
+.endm
+
+/*
+ * Reads cp15 registers from memory and writes them to hardware
+ * @read_from_vcpu: If 0, registers are read in-order from the stack,
+ *                 otherwise from the VCPU struct pointed to by vcpup
+ *
+ * Assumes vcpu pointer in vcpu reg
+ */
+.macro write_cp15_state read_from_vcpu
+       .if \read_from_vcpu == 0
+       pop     {r2-r12}
+       .else
+       ldr     r2, [vcpu, #CP15_OFFSET(c13_CID)]
+       ldr     r3, [vcpu, #CP15_OFFSET(c13_TID_URW)]
+       ldr     r4, [vcpu, #CP15_OFFSET(c13_TID_URO)]
+       ldr     r5, [vcpu, #CP15_OFFSET(c13_TID_PRIV)]
+       ldr     r6, [vcpu, #CP15_OFFSET(c5_DFSR)]
+       ldr     r7, [vcpu, #CP15_OFFSET(c5_IFSR)]
+       ldr     r8, [vcpu, #CP15_OFFSET(c5_ADFSR)]
+       ldr     r9, [vcpu, #CP15_OFFSET(c5_AIFSR)]
+       ldr     r10, [vcpu, #CP15_OFFSET(c6_DFAR)]
+       ldr     r11, [vcpu, #CP15_OFFSET(c6_IFAR)]
+       ldr     r12, [vcpu, #CP15_OFFSET(c12_VBAR)]
+       .endif
+
+       mcr     p15, 0, r2, c13, c0, 1  @ CID
+       mcr     p15, 0, r3, c13, c0, 2  @ TID_URW
+       mcr     p15, 0, r4, c13, c0, 3  @ TID_URO
+       mcr     p15, 0, r5, c13, c0, 4  @ TID_PRIV
+       mcr     p15, 0, r6, c5, c0, 0   @ DFSR
+       mcr     p15, 0, r7, c5, c0, 1   @ IFSR
+       mcr     p15, 0, r8, c5, c1, 0   @ ADFSR
+       mcr     p15, 0, r9, c5, c1, 1   @ AIFSR
+       mcr     p15, 0, r10, c6, c0, 0  @ DFAR
+       mcr     p15, 0, r11, c6, c0, 2  @ IFAR
+       mcr     p15, 0, r12, c12, c0, 0 @ VBAR
+
+       .if \read_from_vcpu == 0
+       pop     {r2-r12}
+       .else
+       ldr     r2, [vcpu, #CP15_OFFSET(c1_SCTLR)]
+       ldr     r3, [vcpu, #CP15_OFFSET(c1_CPACR)]
+       ldr     r4, [vcpu, #CP15_OFFSET(c2_TTBCR)]
+       ldr     r5, [vcpu, #CP15_OFFSET(c3_DACR)]
+       add     r12, vcpu, #CP15_OFFSET(c2_TTBR0)
+       ldrd    r6, r7, [r12]
+       add     r12, vcpu, #CP15_OFFSET(c2_TTBR1)
+       ldrd    r8, r9, [r12]
+       ldr     r10, [vcpu, #CP15_OFFSET(c10_PRRR)]
+       ldr     r11, [vcpu, #CP15_OFFSET(c10_NMRR)]
+       ldr     r12, [vcpu, #CP15_OFFSET(c0_CSSELR)]
+       .endif
+
+       mcr     p15, 0, r2, c1, c0, 0   @ SCTLR
+       mcr     p15, 0, r3, c1, c0, 2   @ CPACR
+       mcr     p15, 0, r4, c2, c0, 2   @ TTBCR
+       mcr     p15, 0, r5, c3, c0, 0   @ DACR
+       mcrr    p15, 0, r6, r7, c2      @ TTBR 0
+       mcrr    p15, 1, r8, r9, c2      @ TTBR 1
+       mcr     p15, 0, r10, c10, c2, 0 @ PRRR
+       mcr     p15, 0, r11, c10, c2, 1 @ NMRR
+       mcr     p15, 2, r12, c0, c0, 0  @ CSSELR
+.endm
+
+/*
+ * Save the VGIC CPU state into memory
+ *
+ * Assumes vcpu pointer in vcpu reg
+ */
+.macro save_vgic_state
+.endm
+
+/*
+ * Restore the VGIC CPU state from memory
+ *
+ * Assumes vcpu pointer in vcpu reg
+ */
+.macro restore_vgic_state
+.endm
+
+.equ vmentry,  0
+.equ vmexit,   1
+
+/* Configures the HSTR (Hyp System Trap Register) on entry/return
+ * (hardware reset value is 0) */
+.macro set_hstr operation
+       mrc     p15, 4, r2, c1, c1, 3
+       ldr     r3, =HSTR_T(15)
+       .if \operation == vmentry
+       orr     r2, r2, r3              @ Trap CR{15}
+       .else
+       bic     r2, r2, r3              @ Don't trap any CRx accesses
+       .endif
+       mcr     p15, 4, r2, c1, c1, 3
+.endm
+
+/* Configures the HCPTR (Hyp Coprocessor Trap Register) on entry/return
+ * (hardware reset value is 0). Keep previous value in r2. */
+.macro set_hcptr operation, mask
+       mrc     p15, 4, r2, c1, c1, 2
+       ldr     r3, =\mask
+       .if \operation == vmentry
+       orr     r3, r2, r3              @ Trap coproc-accesses defined in mask
+       .else
+       bic     r3, r2, r3              @ Don't trap defined coproc-accesses
+       .endif
+       mcr     p15, 4, r3, c1, c1, 2
+.endm
+
+/* Configures the HDCR (Hyp Debug Configuration Register) on entry/return
+ * (hardware reset value is 0) */
+.macro set_hdcr operation
+       mrc     p15, 4, r2, c1, c1, 1
+       ldr     r3, =(HDCR_TPM|HDCR_TPMCR)
+       .if \operation == vmentry
+       orr     r2, r2, r3              @ Trap some perfmon accesses
+       .else
+       bic     r2, r2, r3              @ Don't trap any perfmon accesses
+       .endif
+       mcr     p15, 4, r2, c1, c1, 1
+.endm
+
+/* Enable/Disable: stage-2 trans., trap interrupts, trap wfi, trap smc */
+.macro configure_hyp_role operation
+       mrc     p15, 4, r2, c1, c1, 0   @ HCR
+       bic     r2, r2, #HCR_VIRT_EXCP_MASK
+       ldr     r3, =HCR_GUEST_MASK
+       .if \operation == vmentry
+       orr     r2, r2, r3
+       ldr     r3, [vcpu, #VCPU_IRQ_LINES]
+       orr     r2, r2, r3
+       .else
+       bic     r2, r2, r3
+       .endif
+       mcr     p15, 4, r2, c1, c1, 0
+.endm
+
+.macro load_vcpu
+       mrc     p15, 4, vcpu, c13, c0, 2        @ HTPIDR
+.endm
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
new file mode 100644 (file)
index 0000000..0144baf
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_mmio.h>
+#include <asm/kvm_emulate.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+/**
+ * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ * @vcpu: The VCPU pointer
+ * @run:  The VCPU run struct containing the mmio data
+ *
+ * This should only be called after returning from userspace for MMIO load
+ * emulation.
+ */
+int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       __u32 *dest;
+       unsigned int len;
+       int mask;
+
+       if (!run->mmio.is_write) {
+               dest = vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt);
+               memset(dest, 0, sizeof(int));
+
+               len = run->mmio.len;
+               if (len > 4)
+                       return -EINVAL;
+
+               memcpy(dest, run->mmio.data, len);
+
+               trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
+                               *((u64 *)run->mmio.data));
+
+               if (vcpu->arch.mmio_decode.sign_extend && len < 4) {
+                       mask = 1U << ((len * 8) - 1);
+                       *dest = (*dest ^ mask) - mask;
+               }
+       }
+
+       return 0;
+}
+
+static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+                     struct kvm_exit_mmio *mmio)
+{
+       unsigned long rt, len;
+       bool is_write, sign_extend;
+
+       if ((vcpu->arch.hsr >> 8) & 1) {
+               /* cache operation on I/O addr, tell guest unsupported */
+               kvm_inject_dabt(vcpu, vcpu->arch.hxfar);
+               return 1;
+       }
+
+       if ((vcpu->arch.hsr >> 7) & 1) {
+               /* page table accesses IO mem: tell guest to fix its TTBR */
+               kvm_inject_dabt(vcpu, vcpu->arch.hxfar);
+               return 1;
+       }
+
+       switch ((vcpu->arch.hsr >> 22) & 0x3) {
+       case 0:
+               len = 1;
+               break;
+       case 1:
+               len = 2;
+               break;
+       case 2:
+               len = 4;
+               break;
+       default:
+               kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
+               return -EFAULT;
+       }
+
+       is_write = vcpu->arch.hsr & HSR_WNR;
+       sign_extend = vcpu->arch.hsr & HSR_SSE;
+       rt = (vcpu->arch.hsr & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
+
+       if (kvm_vcpu_reg_is_pc(vcpu, rt)) {
+               /* IO memory trying to read/write pc */
+               kvm_inject_pabt(vcpu, vcpu->arch.hxfar);
+               return 1;
+       }
+
+       mmio->is_write = is_write;
+       mmio->phys_addr = fault_ipa;
+       mmio->len = len;
+       vcpu->arch.mmio_decode.sign_extend = sign_extend;
+       vcpu->arch.mmio_decode.rt = rt;
+
+       /*
+        * The MMIO instruction is emulated and should not be re-executed
+        * in the guest.
+        */
+       kvm_skip_instr(vcpu, (vcpu->arch.hsr >> 25) & 1);
+       return 0;
+}
+
+int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
+                phys_addr_t fault_ipa)
+{
+       struct kvm_exit_mmio mmio;
+       unsigned long rt;
+       int ret;
+
+       /*
+        * Prepare MMIO operation. First stash it in a private
+        * structure that we can use for in-kernel emulation. If the
+        * kernel can't handle it, copy it into run->mmio and let user
+        * space do its magic.
+        */
+
+       if (vcpu->arch.hsr & HSR_ISV) {
+               ret = decode_hsr(vcpu, fault_ipa, &mmio);
+               if (ret)
+                       return ret;
+       } else {
+               kvm_err("load/store instruction decoding not implemented\n");
+               return -ENOSYS;
+       }
+
+       rt = vcpu->arch.mmio_decode.rt;
+       trace_kvm_mmio((mmio.is_write) ? KVM_TRACE_MMIO_WRITE :
+                                        KVM_TRACE_MMIO_READ_UNSATISFIED,
+                       mmio.len, fault_ipa,
+                       (mmio.is_write) ? *vcpu_reg(vcpu, rt) : 0);
+
+       if (mmio.is_write)
+               memcpy(mmio.data, vcpu_reg(vcpu, rt), mmio.len);
+
+       kvm_prepare_mmio(run, &mmio);
+       return 0;
+}
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
new file mode 100644 (file)
index 0000000..f30e131
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/mman.h>
+#include <linux/kvm_host.h>
+#include <linux/io.h>
+#include <trace/events/kvm.h>
+#include <asm/idmap.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_mmio.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_emulate.h>
+#include <asm/mach/map.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+extern char  __hyp_idmap_text_start[], __hyp_idmap_text_end[];
+
+static DEFINE_MUTEX(kvm_hyp_pgd_mutex);
+
+static void kvm_tlb_flush_vmid(struct kvm *kvm)
+{
+       kvm_call_hyp(__kvm_tlb_flush_vmid, kvm);
+}
+
+static void kvm_set_pte(pte_t *pte, pte_t new_pte)
+{
+       pte_val(*pte) = new_pte;
+       /*
+        * flush_pmd_entry just takes a void pointer and cleans the necessary
+        * cache entries, so we can reuse the function for ptes.
+        */
+       flush_pmd_entry(pte);
+}
+
+static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
+                                 int min, int max)
+{
+       void *page;
+
+       BUG_ON(max > KVM_NR_MEM_OBJS);
+       if (cache->nobjs >= min)
+               return 0;
+       while (cache->nobjs < max) {
+               page = (void *)__get_free_page(PGALLOC_GFP);
+               if (!page)
+                       return -ENOMEM;
+               cache->objects[cache->nobjs++] = page;
+       }
+       return 0;
+}
+
+static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc)
+{
+       while (mc->nobjs)
+               free_page((unsigned long)mc->objects[--mc->nobjs]);
+}
+
+static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
+{
+       void *p;
+
+       BUG_ON(!mc || !mc->nobjs);
+       p = mc->objects[--mc->nobjs];
+       return p;
+}
+
+static void free_ptes(pmd_t *pmd, unsigned long addr)
+{
+       pte_t *pte;
+       unsigned int i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++, addr += PMD_SIZE) {
+               if (!pmd_none(*pmd) && pmd_table(*pmd)) {
+                       pte = pte_offset_kernel(pmd, addr);
+                       pte_free_kernel(NULL, pte);
+               }
+               pmd++;
+       }
+}
+
+/**
+ * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables
+ *
+ * Assumes this is a page table used strictly in Hyp-mode and therefore contains
+ * only mappings in the kernel memory area, which is above PAGE_OFFSET.
+ */
+void free_hyp_pmds(void)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       unsigned long addr;
+
+       mutex_lock(&kvm_hyp_pgd_mutex);
+       for (addr = PAGE_OFFSET; addr != 0; addr += PGDIR_SIZE) {
+               pgd = hyp_pgd + pgd_index(addr);
+               pud = pud_offset(pgd, addr);
+
+               if (pud_none(*pud))
+                       continue;
+               BUG_ON(pud_bad(*pud));
+
+               pmd = pmd_offset(pud, addr);
+               free_ptes(pmd, addr);
+               pmd_free(NULL, pmd);
+               pud_clear(pud);
+       }
+       mutex_unlock(&kvm_hyp_pgd_mutex);
+}
+
+static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start,
+                                   unsigned long end)
+{
+       pte_t *pte;
+       unsigned long addr;
+       struct page *page;
+
+       for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
+               pte = pte_offset_kernel(pmd, addr);
+               BUG_ON(!virt_addr_valid(addr));
+               page = virt_to_page(addr);
+               kvm_set_pte(pte, mk_pte(page, PAGE_HYP));
+       }
+}
+
+static void create_hyp_io_pte_mappings(pmd_t *pmd, unsigned long start,
+                                      unsigned long end,
+                                      unsigned long *pfn_base)
+{
+       pte_t *pte;
+       unsigned long addr;
+
+       for (addr = start & PAGE_MASK; addr < end; addr += PAGE_SIZE) {
+               pte = pte_offset_kernel(pmd, addr);
+               BUG_ON(pfn_valid(*pfn_base));
+               kvm_set_pte(pte, pfn_pte(*pfn_base, PAGE_HYP_DEVICE));
+               (*pfn_base)++;
+       }
+}
+
+static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
+                                  unsigned long end, unsigned long *pfn_base)
+{
+       pmd_t *pmd;
+       pte_t *pte;
+       unsigned long addr, next;
+
+       for (addr = start; addr < end; addr = next) {
+               pmd = pmd_offset(pud, addr);
+
+               BUG_ON(pmd_sect(*pmd));
+
+               if (pmd_none(*pmd)) {
+                       pte = pte_alloc_one_kernel(NULL, addr);
+                       if (!pte) {
+                               kvm_err("Cannot allocate Hyp pte\n");
+                               return -ENOMEM;
+                       }
+                       pmd_populate_kernel(NULL, pmd, pte);
+               }
+
+               next = pmd_addr_end(addr, end);
+
+               /*
+                * If pfn_base is NULL, we map kernel pages into HYP with the
+                * virtual address. Otherwise, this is considered an I/O
+                * mapping and we map the physical region starting at
+                * *pfn_base to [start, end[.
+                */
+               if (!pfn_base)
+                       create_hyp_pte_mappings(pmd, addr, next);
+               else
+                       create_hyp_io_pte_mappings(pmd, addr, next, pfn_base);
+       }
+
+       return 0;
+}
+
+static int __create_hyp_mappings(void *from, void *to, unsigned long *pfn_base)
+{
+       unsigned long start = (unsigned long)from;
+       unsigned long end = (unsigned long)to;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       unsigned long addr, next;
+       int err = 0;
+
+       BUG_ON(start > end);
+       if (start < PAGE_OFFSET)
+               return -EINVAL;
+
+       mutex_lock(&kvm_hyp_pgd_mutex);
+       for (addr = start; addr < end; addr = next) {
+               pgd = hyp_pgd + pgd_index(addr);
+               pud = pud_offset(pgd, addr);
+
+               if (pud_none_or_clear_bad(pud)) {
+                       pmd = pmd_alloc_one(NULL, addr);
+                       if (!pmd) {
+                               kvm_err("Cannot allocate Hyp pmd\n");
+                               err = -ENOMEM;
+                               goto out;
+                       }
+                       pud_populate(NULL, pud, pmd);
+               }
+
+               next = pgd_addr_end(addr, end);
+               err = create_hyp_pmd_mappings(pud, addr, next, pfn_base);
+               if (err)
+                       goto out;
+       }
+out:
+       mutex_unlock(&kvm_hyp_pgd_mutex);
+       return err;
+}
+
+/**
+ * create_hyp_mappings - map a kernel virtual address range in Hyp mode
+ * @from:      The virtual kernel start address of the range
+ * @to:                The virtual kernel end address of the range (exclusive)
+ *
+ * The same virtual address as the kernel virtual address is also used in
+ * Hyp-mode mapping to the same underlying physical pages.
+ *
+ * Note: Wrapping around zero in the "to" address is not supported.
+ */
+int create_hyp_mappings(void *from, void *to)
+{
+       return __create_hyp_mappings(from, to, NULL);
+}
+
+/**
+ * create_hyp_io_mappings - map a physical IO range in Hyp mode
+ * @from:      The virtual HYP start address of the range
+ * @to:                The virtual HYP end address of the range (exclusive)
+ * @addr:      The physical start address which gets mapped
+ */
+int create_hyp_io_mappings(void *from, void *to, phys_addr_t addr)
+{
+       unsigned long pfn = __phys_to_pfn(addr);
+       return __create_hyp_mappings(from, to, &pfn);
+}
+
+/**
+ * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
+ * @kvm:       The KVM struct pointer for the VM.
+ *
+ * Allocates the 1st level table only of size defined by S2_PGD_ORDER (can
+ * support either full 40-bit input addresses or limited to 32-bit input
+ * addresses). Clears the allocated pages.
+ *
+ * Note we don't need locking here as this is only called when the VM is
+ * created, which can only be done once.
+ */
+int kvm_alloc_stage2_pgd(struct kvm *kvm)
+{
+       pgd_t *pgd;
+
+       if (kvm->arch.pgd != NULL) {
+               kvm_err("kvm_arch already initialized?\n");
+               return -EINVAL;
+       }
+
+       pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, S2_PGD_ORDER);
+       if (!pgd)
+               return -ENOMEM;
+
+       /* stage-2 pgd must be aligned to its size */
+       VM_BUG_ON((unsigned long)pgd & (S2_PGD_SIZE - 1));
+
+       memset(pgd, 0, PTRS_PER_S2_PGD * sizeof(pgd_t));
+       clean_dcache_area(pgd, PTRS_PER_S2_PGD * sizeof(pgd_t));
+       kvm->arch.pgd = pgd;
+
+       return 0;
+}
+
+static void clear_pud_entry(pud_t *pud)
+{
+       pmd_t *pmd_table = pmd_offset(pud, 0);
+       pud_clear(pud);
+       pmd_free(NULL, pmd_table);
+       put_page(virt_to_page(pud));
+}
+
+static void clear_pmd_entry(pmd_t *pmd)
+{
+       pte_t *pte_table = pte_offset_kernel(pmd, 0);
+       pmd_clear(pmd);
+       pte_free_kernel(NULL, pte_table);
+       put_page(virt_to_page(pmd));
+}
+
+static bool pmd_empty(pmd_t *pmd)
+{
+       struct page *pmd_page = virt_to_page(pmd);
+       return page_count(pmd_page) == 1;
+}
+
+static void clear_pte_entry(pte_t *pte)
+{
+       if (pte_present(*pte)) {
+               kvm_set_pte(pte, __pte(0));
+               put_page(virt_to_page(pte));
+       }
+}
+
+static bool pte_empty(pte_t *pte)
+{
+       struct page *pte_page = virt_to_page(pte);
+       return page_count(pte_page) == 1;
+}
+
+/**
+ * unmap_stage2_range -- Clear stage2 page table entries to unmap a range
+ * @kvm:   The VM pointer
+ * @start: The intermediate physical base address of the range to unmap
+ * @size:  The size of the area to unmap
+ *
+ * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
+ * be called while holding mmu_lock (unless for freeing the stage2 pgd before
+ * destroying the VM), otherwise another faulting VCPU may come in and mess
+ * with things behind our backs.
+ */
+static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       phys_addr_t addr = start, end = start + size;
+       u64 range;
+
+       while (addr < end) {
+               pgd = kvm->arch.pgd + pgd_index(addr);
+               pud = pud_offset(pgd, addr);
+               if (pud_none(*pud)) {
+                       addr += PUD_SIZE;
+                       continue;
+               }
+
+               pmd = pmd_offset(pud, addr);
+               if (pmd_none(*pmd)) {
+                       addr += PMD_SIZE;
+                       continue;
+               }
+
+               pte = pte_offset_kernel(pmd, addr);
+               clear_pte_entry(pte);
+               range = PAGE_SIZE;
+
+               /* If we emptied the pte, walk back up the ladder */
+               if (pte_empty(pte)) {
+                       clear_pmd_entry(pmd);
+                       range = PMD_SIZE;
+                       if (pmd_empty(pmd)) {
+                               clear_pud_entry(pud);
+                               range = PUD_SIZE;
+                       }
+               }
+
+               addr += range;
+       }
+}
+
+/**
+ * kvm_free_stage2_pgd - free all stage-2 tables
+ * @kvm:       The KVM struct pointer for the VM.
+ *
+ * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
+ * underlying level-2 and level-3 tables before freeing the actual level-1 table
+ * and setting the struct pointer to NULL.
+ *
+ * Note we don't need locking here as this is only called when the VM is
+ * destroyed, which can only be done once.
+ */
+void kvm_free_stage2_pgd(struct kvm *kvm)
+{
+       if (kvm->arch.pgd == NULL)
+               return;
+
+       unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+       free_pages((unsigned long)kvm->arch.pgd, S2_PGD_ORDER);
+       kvm->arch.pgd = NULL;
+}
+
+
+static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+                         phys_addr_t addr, const pte_t *new_pte, bool iomap)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte, old_pte;
+
+       /* Create 2nd stage page table mapping - Level 1 */
+       pgd = kvm->arch.pgd + pgd_index(addr);
+       pud = pud_offset(pgd, addr);
+       if (pud_none(*pud)) {
+               if (!cache)
+                       return 0; /* ignore calls from kvm_set_spte_hva */
+               pmd = mmu_memory_cache_alloc(cache);
+               pud_populate(NULL, pud, pmd);
+               pmd += pmd_index(addr);
+               get_page(virt_to_page(pud));
+       } else
+               pmd = pmd_offset(pud, addr);
+
+       /* Create 2nd stage page table mapping - Level 2 */
+       if (pmd_none(*pmd)) {
+               if (!cache)
+                       return 0; /* ignore calls from kvm_set_spte_hva */
+               pte = mmu_memory_cache_alloc(cache);
+               clean_pte_table(pte);
+               pmd_populate_kernel(NULL, pmd, pte);
+               pte += pte_index(addr);
+               get_page(virt_to_page(pmd));
+       } else
+               pte = pte_offset_kernel(pmd, addr);
+
+       if (iomap && pte_present(*pte))
+               return -EFAULT;
+
+       /* Create 2nd stage page table mapping - Level 3 */
+       old_pte = *pte;
+       kvm_set_pte(pte, *new_pte);
+       if (pte_present(old_pte))
+               kvm_tlb_flush_vmid(kvm);
+       else
+               get_page(virt_to_page(pte));
+
+       return 0;
+}
+
+/**
+ * kvm_phys_addr_ioremap - map a device range to guest IPA
+ *
+ * @kvm:       The KVM pointer
+ * @guest_ipa: The IPA at which to insert the mapping
+ * @pa:                The physical address of the device
+ * @size:      The size of the mapping
+ */
+int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
+                         phys_addr_t pa, unsigned long size)
+{
+       phys_addr_t addr, end;
+       int ret = 0;
+       unsigned long pfn;
+       struct kvm_mmu_memory_cache cache = { 0, };
+
+       end = (guest_ipa + size + PAGE_SIZE - 1) & PAGE_MASK;
+       pfn = __phys_to_pfn(pa);
+
+       for (addr = guest_ipa; addr < end; addr += PAGE_SIZE) {
+               pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE | L_PTE_S2_RDWR);
+
+               ret = mmu_topup_memory_cache(&cache, 2, 2);
+               if (ret)
+                       goto out;
+               spin_lock(&kvm->mmu_lock);
+               ret = stage2_set_pte(kvm, &cache, addr, &pte, true);
+               spin_unlock(&kvm->mmu_lock);
+               if (ret)
+                       goto out;
+
+               pfn++;
+       }
+
+out:
+       mmu_free_memory_cache(&cache);
+       return ret;
+}
+
+static void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn)
+{
+       /*
+        * If we are going to insert an instruction page and the icache is
+        * either VIPT or PIPT, there is a potential problem where the host
+        * (or another VM) may have used the same page as this guest, and we
+        * read incorrect data from the icache.  If we're using a PIPT cache,
+        * we can invalidate just that page, but if we are using a VIPT cache
+        * we need to invalidate the entire icache - damn shame - as written
+        * in the ARM ARM (DDI 0406C.b - Page B3-1393).
+        *
+        * VIVT caches are tagged using both the ASID and the VMID and doesn't
+        * need any kind of flushing (DDI 0406C.b - Page B3-1392).
+        */
+       if (icache_is_pipt()) {
+               unsigned long hva = gfn_to_hva(kvm, gfn);
+               __cpuc_coherent_user_range(hva, hva + PAGE_SIZE);
+       } else if (!icache_is_vivt_asid_tagged()) {
+               /* any kind of VIPT cache */
+               __flush_icache_all();
+       }
+}
+
+static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+                         gfn_t gfn, struct kvm_memory_slot *memslot,
+                         unsigned long fault_status)
+{
+       pte_t new_pte;
+       pfn_t pfn;
+       int ret;
+       bool write_fault, writable;
+       unsigned long mmu_seq;
+       struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
+
+       write_fault = kvm_is_write_fault(vcpu->arch.hsr);
+       if (fault_status == FSC_PERM && !write_fault) {
+               kvm_err("Unexpected L2 read permission error\n");
+               return -EFAULT;
+       }
+
+       /* We need minimum second+third level pages */
+       ret = mmu_topup_memory_cache(memcache, 2, KVM_NR_MEM_OBJS);
+       if (ret)
+               return ret;
+
+       mmu_seq = vcpu->kvm->mmu_notifier_seq;
+       /*
+        * Ensure the read of mmu_notifier_seq happens before we call
+        * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk
+        * the page we just got a reference to gets unmapped before we have a
+        * chance to grab the mmu_lock, which ensure that if the page gets
+        * unmapped afterwards, the call to kvm_unmap_hva will take it away
+        * from us again properly. This smp_rmb() interacts with the smp_wmb()
+        * in kvm_mmu_notifier_invalidate_<page|range_end>.
+        */
+       smp_rmb();
+
+       pfn = gfn_to_pfn_prot(vcpu->kvm, gfn, write_fault, &writable);
+       if (is_error_pfn(pfn))
+               return -EFAULT;
+
+       new_pte = pfn_pte(pfn, PAGE_S2);
+       coherent_icache_guest_page(vcpu->kvm, gfn);
+
+       spin_lock(&vcpu->kvm->mmu_lock);
+       if (mmu_notifier_retry(vcpu->kvm, mmu_seq))
+               goto out_unlock;
+       if (writable) {
+               pte_val(new_pte) |= L_PTE_S2_RDWR;
+               kvm_set_pfn_dirty(pfn);
+       }
+       stage2_set_pte(vcpu->kvm, memcache, fault_ipa, &new_pte, false);
+
+out_unlock:
+       spin_unlock(&vcpu->kvm->mmu_lock);
+       kvm_release_pfn_clean(pfn);
+       return 0;
+}
+
+/**
+ * kvm_handle_guest_abort - handles all 2nd stage aborts
+ * @vcpu:      the VCPU pointer
+ * @run:       the kvm_run structure
+ *
+ * Any abort that gets to the host is almost guaranteed to be caused by a
+ * missing second stage translation table entry, which can mean that either the
+ * guest simply needs more memory and we must allocate an appropriate page or it
+ * can mean that the guest tried to access I/O memory, which is emulated by user
+ * space. The distinction is based on the IPA causing the fault and whether this
+ * memory region has been registered as standard RAM by user space.
+ */
+int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       unsigned long hsr_ec;
+       unsigned long fault_status;
+       phys_addr_t fault_ipa;
+       struct kvm_memory_slot *memslot;
+       bool is_iabt;
+       gfn_t gfn;
+       int ret, idx;
+
+       hsr_ec = vcpu->arch.hsr >> HSR_EC_SHIFT;
+       is_iabt = (hsr_ec == HSR_EC_IABT);
+       fault_ipa = ((phys_addr_t)vcpu->arch.hpfar & HPFAR_MASK) << 8;
+
+       trace_kvm_guest_fault(*vcpu_pc(vcpu), vcpu->arch.hsr,
+                             vcpu->arch.hxfar, fault_ipa);
+
+       /* Check the stage-2 fault is trans. fault or write fault */
+       fault_status = (vcpu->arch.hsr & HSR_FSC_TYPE);
+       if (fault_status != FSC_FAULT && fault_status != FSC_PERM) {
+               kvm_err("Unsupported fault status: EC=%#lx DFCS=%#lx\n",
+                       hsr_ec, fault_status);
+               return -EFAULT;
+       }
+
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+       gfn = fault_ipa >> PAGE_SHIFT;
+       if (!kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+               if (is_iabt) {
+                       /* Prefetch Abort on I/O address */
+                       kvm_inject_pabt(vcpu, vcpu->arch.hxfar);
+                       ret = 1;
+                       goto out_unlock;
+               }
+
+               if (fault_status != FSC_FAULT) {
+                       kvm_err("Unsupported fault status on io memory: %#lx\n",
+                               fault_status);
+                       ret = -EFAULT;
+                       goto out_unlock;
+               }
+
+               /* Adjust page offset */
+               fault_ipa |= vcpu->arch.hxfar & ~PAGE_MASK;
+               ret = io_mem_abort(vcpu, run, fault_ipa);
+               goto out_unlock;
+       }
+
+       memslot = gfn_to_memslot(vcpu->kvm, gfn);
+       if (!memslot->user_alloc) {
+               kvm_err("non user-alloc memslots not supported\n");
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
+       ret = user_mem_abort(vcpu, fault_ipa, gfn, memslot, fault_status);
+       if (ret == 0)
+               ret = 1;
+out_unlock:
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
+       return ret;
+}
+
+static void handle_hva_to_gpa(struct kvm *kvm,
+                             unsigned long start,
+                             unsigned long end,
+                             void (*handler)(struct kvm *kvm,
+                                             gpa_t gpa, void *data),
+                             void *data)
+{
+       struct kvm_memslots *slots;
+       struct kvm_memory_slot *memslot;
+
+       slots = kvm_memslots(kvm);
+
+       /* we only care about the pages that the guest sees */
+       kvm_for_each_memslot(memslot, slots) {
+               unsigned long hva_start, hva_end;
+               gfn_t gfn, gfn_end;
+
+               hva_start = max(start, memslot->userspace_addr);
+               hva_end = min(end, memslot->userspace_addr +
+                                       (memslot->npages << PAGE_SHIFT));
+               if (hva_start >= hva_end)
+                       continue;
+
+               /*
+                * {gfn(page) | page intersects with [hva_start, hva_end)} =
+                * {gfn_start, gfn_start+1, ..., gfn_end-1}.
+                */
+               gfn = hva_to_gfn_memslot(hva_start, memslot);
+               gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot);
+
+               for (; gfn < gfn_end; ++gfn) {
+                       gpa_t gpa = gfn << PAGE_SHIFT;
+                       handler(kvm, gpa, data);
+               }
+       }
+}
+
+static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
+{
+       unmap_stage2_range(kvm, gpa, PAGE_SIZE);
+       kvm_tlb_flush_vmid(kvm);
+}
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+       unsigned long end = hva + PAGE_SIZE;
+
+       if (!kvm->arch.pgd)
+               return 0;
+
+       trace_kvm_unmap_hva(hva);
+       handle_hva_to_gpa(kvm, hva, end, &kvm_unmap_hva_handler, NULL);
+       return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm,
+                       unsigned long start, unsigned long end)
+{
+       if (!kvm->arch.pgd)
+               return 0;
+
+       trace_kvm_unmap_hva_range(start, end);
+       handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL);
+       return 0;
+}
+
+static void kvm_set_spte_handler(struct kvm *kvm, gpa_t gpa, void *data)
+{
+       pte_t *pte = (pte_t *)data;
+
+       stage2_set_pte(kvm, NULL, gpa, pte, false);
+}
+
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+       unsigned long end = hva + PAGE_SIZE;
+       pte_t stage2_pte;
+
+       if (!kvm->arch.pgd)
+               return;
+
+       trace_kvm_set_spte_hva(hva);
+       stage2_pte = pfn_pte(pte_pfn(pte), PAGE_S2);
+       handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte);
+}
+
+void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu)
+{
+       mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
+}
+
+phys_addr_t kvm_mmu_get_httbr(void)
+{
+       VM_BUG_ON(!virt_addr_valid(hyp_pgd));
+       return virt_to_phys(hyp_pgd);
+}
+
+int kvm_mmu_init(void)
+{
+       if (!hyp_pgd) {
+               kvm_err("Hyp mode PGD not allocated\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/**
+ * kvm_clear_idmap - remove all idmaps from the hyp pgd
+ *
+ * Free the underlying pmds for all pgds in range and clear the pgds (but
+ * don't free them) afterwards.
+ */
+void kvm_clear_hyp_idmap(void)
+{
+       unsigned long addr, end;
+       unsigned long next;
+       pgd_t *pgd = hyp_pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+
+       addr = virt_to_phys(__hyp_idmap_text_start);
+       end = virt_to_phys(__hyp_idmap_text_end);
+
+       pgd += pgd_index(addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               if (pgd_none_or_clear_bad(pgd))
+                       continue;
+               pud = pud_offset(pgd, addr);
+               pmd = pmd_offset(pud, addr);
+
+               pud_clear(pud);
+               clean_pmd_entry(pmd);
+               pmd_free(NULL, (pmd_t *)((unsigned long)pmd & PAGE_MASK));
+       } while (pgd++, addr = next, addr < end);
+}
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
new file mode 100644 (file)
index 0000000..7ee5bb7
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/wait.h>
+
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_psci.h>
+
+/*
+ * This is an implementation of the Power State Coordination Interface
+ * as described in ARM document number ARM DEN 0022A.
+ */
+
+static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.pause = true;
+}
+
+static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
+{
+       struct kvm *kvm = source_vcpu->kvm;
+       struct kvm_vcpu *vcpu;
+       wait_queue_head_t *wq;
+       unsigned long cpu_id;
+       phys_addr_t target_pc;
+
+       cpu_id = *vcpu_reg(source_vcpu, 1);
+       if (vcpu_mode_is_32bit(source_vcpu))
+               cpu_id &= ~((u32) 0);
+
+       if (cpu_id >= atomic_read(&kvm->online_vcpus))
+               return KVM_PSCI_RET_INVAL;
+
+       target_pc = *vcpu_reg(source_vcpu, 2);
+
+       vcpu = kvm_get_vcpu(kvm, cpu_id);
+
+       wq = kvm_arch_vcpu_wq(vcpu);
+       if (!waitqueue_active(wq))
+               return KVM_PSCI_RET_INVAL;
+
+       kvm_reset_vcpu(vcpu);
+
+       /* Gracefully handle Thumb2 entry point */
+       if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
+               target_pc &= ~((phys_addr_t) 1);
+               vcpu_set_thumb(vcpu);
+       }
+
+       *vcpu_pc(vcpu) = target_pc;
+       vcpu->arch.pause = false;
+       smp_mb();               /* Make sure the above is visible */
+
+       wake_up_interruptible(wq);
+
+       return KVM_PSCI_RET_SUCCESS;
+}
+
+/**
+ * kvm_psci_call - handle PSCI call if r0 value is in range
+ * @vcpu: Pointer to the VCPU struct
+ *
+ * Handle PSCI calls from guests through traps from HVC or SMC instructions.
+ * The calling convention is similar to SMC calls to the secure world where
+ * the function number is placed in r0 and this function returns true if the
+ * function number specified in r0 is withing the PSCI range, and false
+ * otherwise.
+ */
+bool kvm_psci_call(struct kvm_vcpu *vcpu)
+{
+       unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
+       unsigned long val;
+
+       switch (psci_fn) {
+       case KVM_PSCI_FN_CPU_OFF:
+               kvm_psci_vcpu_off(vcpu);
+               val = KVM_PSCI_RET_SUCCESS;
+               break;
+       case KVM_PSCI_FN_CPU_ON:
+               val = kvm_psci_vcpu_on(vcpu);
+               break;
+       case KVM_PSCI_FN_CPU_SUSPEND:
+       case KVM_PSCI_FN_MIGRATE:
+               val = KVM_PSCI_RET_NI;
+               break;
+
+       default:
+               return false;
+       }
+
+       *vcpu_reg(vcpu, 0) = val;
+       return true;
+}
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
new file mode 100644 (file)
index 0000000..b80256b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+
+#include <asm/unified.h>
+#include <asm/ptrace.h>
+#include <asm/cputype.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_coproc.h>
+
+/******************************************************************************
+ * Cortex-A15 Reset Values
+ */
+
+static const int a15_max_cpu_idx = 3;
+
+static struct kvm_regs a15_regs_reset = {
+       .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
+};
+
+
+/*******************************************************************************
+ * Exported reset function
+ */
+
+/**
+ * kvm_reset_vcpu - sets core registers and cp15 registers to reset value
+ * @vcpu: The VCPU pointer
+ *
+ * This function finds the right table above and sets the registers on the
+ * virtual CPU struct to their architectually defined reset values.
+ */
+int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+{
+       struct kvm_regs *cpu_reset;
+
+       switch (vcpu->arch.target) {
+       case KVM_ARM_TARGET_CORTEX_A15:
+               if (vcpu->vcpu_id > a15_max_cpu_idx)
+                       return -EINVAL;
+               cpu_reset = &a15_regs_reset;
+               vcpu->arch.midr = read_cpuid_id();
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       /* Reset core registers */
+       memcpy(&vcpu->arch.regs, cpu_reset, sizeof(vcpu->arch.regs));
+
+       /* Reset CP15 registers */
+       kvm_reset_coprocs(vcpu);
+
+       return 0;
+}
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
new file mode 100644 (file)
index 0000000..a8e73ed
--- /dev/null
@@ -0,0 +1,235 @@
+#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KVM_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+
+/*
+ * Tracepoints for entry/exit to guest
+ */
+TRACE_EVENT(kvm_entry,
+       TP_PROTO(unsigned long vcpu_pc),
+       TP_ARGS(vcpu_pc),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+       ),
+
+       TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_exit,
+       TP_PROTO(unsigned long vcpu_pc),
+       TP_ARGS(vcpu_pc),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+       ),
+
+       TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_guest_fault,
+       TP_PROTO(unsigned long vcpu_pc, unsigned long hsr,
+                unsigned long hxfar,
+                unsigned long long ipa),
+       TP_ARGS(vcpu_pc, hsr, hxfar, ipa),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+               __field(        unsigned long,  hsr             )
+               __field(        unsigned long,  hxfar           )
+               __field(   unsigned long long,  ipa             )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+               __entry->hsr                    = hsr;
+               __entry->hxfar                  = hxfar;
+               __entry->ipa                    = ipa;
+       ),
+
+       TP_printk("guest fault at PC %#08lx (hxfar %#08lx, "
+                 "ipa %#16llx, hsr %#08lx",
+                 __entry->vcpu_pc, __entry->hxfar,
+                 __entry->ipa, __entry->hsr)
+);
+
+TRACE_EVENT(kvm_irq_line,
+       TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
+       TP_ARGS(type, vcpu_idx, irq_num, level),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   type            )
+               __field(        int,            vcpu_idx        )
+               __field(        int,            irq_num         )
+               __field(        int,            level           )
+       ),
+
+       TP_fast_assign(
+               __entry->type           = type;
+               __entry->vcpu_idx       = vcpu_idx;
+               __entry->irq_num        = irq_num;
+               __entry->level          = level;
+       ),
+
+       TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d",
+                 (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" :
+                 (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" :
+                 (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN",
+                 __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level)
+);
+
+TRACE_EVENT(kvm_mmio_emulate,
+       TP_PROTO(unsigned long vcpu_pc, unsigned long instr,
+                unsigned long cpsr),
+       TP_ARGS(vcpu_pc, instr, cpsr),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+               __field(        unsigned long,  instr           )
+               __field(        unsigned long,  cpsr            )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+               __entry->instr                  = instr;
+               __entry->cpsr                   = cpsr;
+       ),
+
+       TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)",
+                 __entry->vcpu_pc, __entry->instr, __entry->cpsr)
+);
+
+/* Architecturally implementation defined CP15 register access */
+TRACE_EVENT(kvm_emulate_cp15_imp,
+       TP_PROTO(unsigned long Op1, unsigned long Rt1, unsigned long CRn,
+                unsigned long CRm, unsigned long Op2, bool is_write),
+       TP_ARGS(Op1, Rt1, CRn, CRm, Op2, is_write),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   Op1             )
+               __field(        unsigned int,   Rt1             )
+               __field(        unsigned int,   CRn             )
+               __field(        unsigned int,   CRm             )
+               __field(        unsigned int,   Op2             )
+               __field(        bool,           is_write        )
+       ),
+
+       TP_fast_assign(
+               __entry->is_write               = is_write;
+               __entry->Op1                    = Op1;
+               __entry->Rt1                    = Rt1;
+               __entry->CRn                    = CRn;
+               __entry->CRm                    = CRm;
+               __entry->Op2                    = Op2;
+       ),
+
+       TP_printk("Implementation defined CP15: %s\tp15, %u, r%u, c%u, c%u, %u",
+                       (__entry->is_write) ? "mcr" : "mrc",
+                       __entry->Op1, __entry->Rt1, __entry->CRn,
+                       __entry->CRm, __entry->Op2)
+);
+
+TRACE_EVENT(kvm_wfi,
+       TP_PROTO(unsigned long vcpu_pc),
+       TP_ARGS(vcpu_pc),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+       ),
+
+       TP_printk("guest executed wfi at: 0x%08lx", __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier unmap hva: %#08lx", __entry->hva)
+);
+
+TRACE_EVENT(kvm_unmap_hva_range,
+       TP_PROTO(unsigned long start, unsigned long end),
+       TP_ARGS(start, end),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+       ),
+
+       TP_fast_assign(
+               __entry->start          = start;
+               __entry->end            = end;
+       ),
+
+       TP_printk("mmu notifier unmap range: %#08lx -- %#08lx",
+                 __entry->start, __entry->end)
+);
+
+TRACE_EVENT(kvm_set_spte_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
+);
+
+TRACE_EVENT(kvm_hvc,
+       TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
+       TP_ARGS(vcpu_pc, r0, imm),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+               __field(        unsigned long,  r0              )
+               __field(        unsigned long,  imm             )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+               __entry->r0             = r0;
+               __entry->imm            = imm;
+       ),
+
+       TP_printk("HVC at 0x%08lx (r0: 0x%08lx, imm: 0x%lx",
+                 __entry->vcpu_pc, __entry->r0, __entry->imm)
+);
+
+#endif /* _TRACE_KVM_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH arch/arm/kvm
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index cafe988..2acdff4 100644 (file)
@@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@ -265,17 +264,10 @@ void __init at91rm9200_timer_init(void)
        at91_st_write(AT91_ST_RTMR, 1);
 
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
-       clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
-       clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
-       clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&clkevt);
+       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+                                       2, AT91_ST_ALMV);
 
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
 }
-
-struct sys_timer at91rm9200_timer = {
-       .init           = at91rm9200_timer_init,
-};
-
index 358412f..3a4bc2e 100644 (file)
@@ -104,12 +104,38 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
        }
 }
 
+static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
+{
+       /* Disable timer */
+       pit_write(AT91_PIT_MR, 0);
+}
+
+static void at91sam926x_pit_reset(void)
+{
+       /* Disable timer and irqs */
+       pit_write(AT91_PIT_MR, 0);
+
+       /* Clear any pending interrupts, wait for PIT to stop counting */
+       while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
+               cpu_relax();
+
+       /* Start PIT but don't enable IRQ */
+       pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+}
+
+static void at91sam926x_pit_resume(struct clock_event_device *cedev)
+{
+       at91sam926x_pit_reset();
+}
+
 static struct clock_event_device pit_clkevt = {
        .name           = "pit",
        .features       = CLOCK_EVT_FEAT_PERIODIC,
        .shift          = 32,
        .rating         = 100,
        .set_mode       = pit_clkevt_mode,
+       .suspend        = at91sam926x_pit_suspend,
+       .resume         = at91sam926x_pit_resume,
 };
 
 
@@ -150,19 +176,6 @@ static struct irqaction at91sam926x_pit_irq = {
        .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
-static void at91sam926x_pit_reset(void)
-{
-       /* Disable timer and irqs */
-       pit_write(AT91_PIT_MR, 0);
-
-       /* Clear any pending interrupts, wait for PIT to stop counting */
-       while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
-               cpu_relax();
-
-       /* Start PIT but don't enable IRQ */
-       pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
-}
-
 #ifdef CONFIG_OF
 static struct of_device_id pit_timer_ids[] = {
        { .compatible = "atmel,at91sam9260-pit" },
@@ -211,7 +224,7 @@ static int __init of_at91sam926x_pit_init(void)
 /*
  * Set up both clocksource and clockevent support.
  */
-static void __init at91sam926x_pit_init(void)
+void __init at91sam926x_pit_init(void)
 {
        unsigned long   pit_rate;
        unsigned        bits;
@@ -250,12 +263,6 @@ static void __init at91sam926x_pit_init(void)
        clockevents_register_device(&pit_clkevt);
 }
 
-static void at91sam926x_pit_suspend(void)
-{
-       /* Disable timer */
-       pit_write(AT91_PIT_MR, 0);
-}
-
 void __init at91sam926x_ioremap_pit(u32 addr)
 {
 #if defined(CONFIG_OF)
@@ -272,9 +279,3 @@ void __init at91sam926x_ioremap_pit(u32 addr)
        if (!pit_base_addr)
                panic("Impossible to ioremap PIT\n");
 }
-
-struct sys_timer at91sam926x_timer = {
-       .init           = at91sam926x_pit_init,
-       .suspend        = at91sam926x_pit_suspend,
-       .resume         = at91sam926x_pit_reset,
-};
index 0e57e44..0c07a44 100644 (file)
 #define        AT91_TC_CLK1BASE        0x40
 #define        AT91_TC_CLK2BASE        0x80
 
-static unsigned long at91x40_gettimeoffset(void)
+static u32 at91x40_gettimeoffset(void)
 {
-       return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128));
+       return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 /
+               (AT91X40_MASTER_CLOCK / 128)) * 1000;
 }
 
 static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
@@ -64,6 +65,8 @@ void __init at91x40_timer_init(void)
 {
        unsigned int v;
 
+       arch_gettimeoffset = at91x40_gettimeoffset;
+
        at91_tc_write(AT91_TC_BCR, 0);
        v = at91_tc_read(AT91_TC_BMR);
        v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE;
@@ -79,9 +82,3 @@ void __init at91x40_timer_init(void)
 
        at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN));
 }
-
-struct sys_timer at91x40_timer = {
-       .init   = at91x40_timer_init,
-       .offset = at91x40_gettimeoffset,
-};
-
index b99b575..35ab632 100644 (file)
@@ -90,7 +90,7 @@ static void __init onearm_board_init(void)
 
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = onearm_init_early,
index 854b979..f95e31c 100644 (file)
@@ -210,7 +210,7 @@ static void __init afeb9260_board_init(void)
 
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
        /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = afeb9260_init_early,
index 28a18ce..ade948b 100644 (file)
@@ -187,7 +187,7 @@ static void __init cam60_board_init(void)
 
 MACHINE_START(CAM60, "KwikByte CAM60")
        /* Maintainer: KwikByte */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = cam60_init_early,
index c17bb53..9298305 100644 (file)
@@ -157,7 +157,7 @@ static void __init carmeva_board_init(void)
 
 MACHINE_START(CARMEVA, "Carmeva")
        /* Maintainer: Conitec Datasystems */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = carmeva_init_early,
index 8474324..008527e 100644 (file)
@@ -374,7 +374,7 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260")
 MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
        /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = cpu9krea_init_early,
index 2a7af78..42f1353 100644 (file)
@@ -178,7 +178,7 @@ static void __init cpuat91_board_init(void)
 
 MACHINE_START(CPUAT91, "Eukrea")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = cpuat91_init_early,
index 48a531e..e5fde21 100644 (file)
@@ -251,7 +251,7 @@ static void __init csb337_board_init(void)
 
 MACHINE_START(CSB337, "Cogent CSB337")
        /* Maintainer: Bill Gatliff */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = csb337_init_early,
index ec0f3ab..fdf1106 100644 (file)
@@ -132,7 +132,7 @@ static void __init csb637_board_init(void)
 
 MACHINE_START(CSB637, "Cogent CSB637")
        /* Maintainer: Bill Gatliff */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = csb637_init_early,
index 881170c..8db3013 100644 (file)
@@ -49,7 +49,7 @@ static const char *at91_dt_board_compat[] __initdata = {
 
 DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91_dt_initialize,
index b489388..becf0a6 100644 (file)
@@ -44,7 +44,7 @@ static void __init at91eb01_init_early(void)
 
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
        /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
-       .timer          = &at91x40_timer,
+       .init_time      = at91x40_timer_init,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91eb01_init_early,
        .init_irq       = at91eb01_init_irq,
index 9f5e71c..f9be816 100644 (file)
@@ -116,7 +116,7 @@ static void __init eb9200_board_init(void)
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = eb9200_init_early,
index ef69e0e..b2fcd71 100644 (file)
@@ -181,7 +181,7 @@ static void __init ecb_at91board_init(void)
 
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
        /* Maintainer: emQbit.com */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ecb_at91init_early,
index 50f3d37..77de410 100644 (file)
@@ -149,7 +149,7 @@ static void __init eco920_board_init(void)
 
 MACHINE_START(ECO920, "eco920")
        /* Maintainer: Sascha Hauer */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = eco920_init_early,
index 5d44eba..737c085 100644 (file)
@@ -159,7 +159,7 @@ static void __init flexibity_board_init(void)
 
 MACHINE_START(FLEXIBITY, "Flexibity Connect")
        /* Maintainer: Maxim Osipov */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = flexibity_init_early,
index 191d37c..2ea7059 100644 (file)
@@ -261,7 +261,7 @@ static void __init foxg20_board_init(void)
 
 MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
        /* Maintainer: Sergio Tanzilli */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = foxg20_init_early,
index 23a2fa1..c1d61d2 100644 (file)
@@ -574,7 +574,7 @@ static void __init gsia18s_board_init(void)
 }
 
 MACHINE_START(GSIA18S, "GS_IA18_S")
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = gsia18s_init_early,
index 9a43d1e..88e2f5d 100644 (file)
@@ -103,7 +103,7 @@ static void __init kafa_board_init(void)
 
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
        /* Maintainer: Sergei Sharonov */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = kafa_init_early,
index f168bec..0c519d9 100644 (file)
@@ -149,7 +149,7 @@ static void __init kb9202_board_init(void)
 
 MACHINE_START(KB9200, "KB920x")
        /* Maintainer: KwikByte, Inc. */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = kb9202_init_early,
index bc7a1c4..5b4760f 100644 (file)
@@ -378,7 +378,7 @@ static void __init neocore926_board_init(void)
 
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
        /* Maintainer: ADENEO */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = neocore926_init_early,
index 0299554..65c0d6b 100644 (file)
@@ -217,7 +217,7 @@ static void __init pcontrol_g20_board_init(void)
 
 MACHINE_START(PCONTROL_G20, "PControl G20")
        /* Maintainer: pgsellmann@portner-elektronik.at */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = pcontrol_g20_init_early,
index 4938f1c..ab2b2ec 100644 (file)
@@ -119,7 +119,7 @@ static void __init picotux200_board_init(void)
 
 MACHINE_START(PICOTUX2XX, "picotux 200")
        /* Maintainer: Kleinhenz Elektronik GmbH */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = picotux200_init_early,
index 33b1628..aa3bc9b 100644 (file)
@@ -257,7 +257,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
        /* Maintainer: calao-systems */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 5f9ce3d..3fcb662 100644 (file)
@@ -47,7 +47,7 @@ static const char *at91rm9200_dt_board_compat[] __initdata = {
 };
 
 DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91rm9200_dt_initialize,
index 9e5061b..690541b 100644 (file)
@@ -219,7 +219,7 @@ static void __init dk_board_init(void)
 
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
        /* Maintainer: SAN People/Atmel */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = dk_init_early,
index 58277db..8b17dad 100644 (file)
@@ -186,7 +186,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
        /* Maintainer: SAN People/Atmel */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 2e8b833..f6d7f19 100644 (file)
@@ -222,7 +222,7 @@ static void __init rsi_ews_board_init(void)
 
 MACHINE_START(RSI_EWS, "RSI EWS")
        /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = rsi_ews_init_early,
index b75fbf6..43ee4dc 100644 (file)
@@ -218,7 +218,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
        /* Maintainer: Olimex */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index f0135cd..0b153c8 100644 (file)
@@ -343,7 +343,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 13ebaa8..b446645 100644 (file)
@@ -612,7 +612,7 @@ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
 MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 89b9608..3284df0 100644 (file)
@@ -443,7 +443,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 1b7dd9f..f9cd1f2 100644 (file)
@@ -409,7 +409,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
@@ -419,7 +419,7 @@ MACHINE_END
 
 MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index e4cc375..2a94896 100644 (file)
@@ -502,7 +502,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 377a109..aa265dc 100644 (file)
@@ -320,7 +320,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
        /* Maintainer: Atmel */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 9877150..3aaa978 100644 (file)
@@ -177,7 +177,7 @@ static void __init snapper9260_board_init(void)
 }
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = snapper9260_init_early,
index 48a962b..a033b8d 100644 (file)
@@ -272,7 +272,7 @@ static void __init stamp9g20evb_board_init(void)
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
        /* Maintainer: taskit GmbH */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = stamp9g20_init_early,
@@ -282,7 +282,7 @@ MACHINE_END
 
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = stamp9g20_init_early,
index c1060f9..2487d94 100644 (file)
@@ -355,7 +355,7 @@ static void __init ek_board_init(void)
 
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
        /* Maintainer: calao-systems */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
@@ -365,7 +365,7 @@ MACHINE_END
 
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
        /* Maintainer: calao-systems */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
@@ -375,7 +375,7 @@ MACHINE_END
 
 MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
        /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
-       .timer          = &at91sam926x_timer,
+       .init_time      = at91sam926x_pit_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
index 8673aeb..be08377 100644 (file)
@@ -587,7 +587,7 @@ static void __init yl9200_board_init(void)
 
 MACHINE_START(YL9200, "uCdragon YL-9200")
        /* Maintainer: S.Birtles */
-       .timer          = &at91rm9200_timer,
+       .init_time      = at91rm9200_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = yl9200_init_early,
index fc593d6..78ab065 100644 (file)
@@ -36,12 +36,11 @@ extern int  __init at91_aic5_of_init(struct device_node *node,
 
 
  /* Timer */
-struct sys_timer;
 extern void at91rm9200_ioremap_st(u32 addr);
-extern struct sys_timer at91rm9200_timer;
+extern void at91rm9200_timer_init(void);
 extern void at91sam926x_ioremap_pit(u32 addr);
-extern struct sys_timer at91sam926x_timer;
-extern struct sys_timer at91x40_timer;
+extern void at91sam926x_pit_init(void);
+extern void at91x40_timer_init(void);
 
  /* Clocks */
 #ifdef CONFIG_AT91_PMC_UNIT
index 5c920bd..f0f9aba 100644 (file)
@@ -24,9 +24,6 @@ static void timer_init(void)
 {
 }
 
-static struct sys_timer timer = {
-       .init = timer_init,
-};
 
 static void __init board_init(void)
 {
@@ -38,7 +35,7 @@ static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, };
 
 DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
        .init_irq = irqchip_init,
-       .timer = &timer,
+       .init_time = timer_init,
        .init_machine = board_init,
        .dt_compat = bcm11351_dt_compat,
 MACHINE_END
index f0d739f..176d2d2 100644 (file)
@@ -104,7 +104,7 @@ DT_MACHINE_START(BCM2835, "BCM2835")
        .init_irq = bcm2835_init_irq,
        .handle_irq = bcm2835_handle_irq,
        .init_machine = bcm2835_init,
-       .timer = &bcm2835_timer,
+       .init_time = bcm2835_timer_init,
        .restart = bcm2835_restart,
        .dt_compat = bcm2835_compat
 MACHINE_END
index 3fbf43f..f385847 100644 (file)
@@ -170,7 +170,7 @@ MACHINE_START(AUTCPU12, "autronix autcpu12")
        .nr_irqs        = CLPS711X_NR_IRQS,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .init_machine   = autcpu12_init,
        .init_late      = autcpu12_init_late,
        .handle_irq     = clps711x_handle_irq,
index 60900dd..baab7da 100644 (file)
@@ -140,7 +140,7 @@ MACHINE_START(CDB89712, "Cirrus-CDB89712")
        .nr_irqs        = CLPS711X_NR_IRQS,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .init_machine   = cdb89712_init,
        .handle_irq     = clps711x_handle_irq,
        .restart        = clps711x_restart,
index 0b32a48..014aa3c 100644 (file)
@@ -40,7 +40,7 @@ MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
        .fixup          = fixup_clep7312,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .handle_irq     = clps711x_handle_irq,
        .restart        = clps711x_restart,
 MACHINE_END
index 71aa5cf..5f928e9 100644 (file)
@@ -173,7 +173,7 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
        .reserve        = edb7211_reserve,
        .map_io         = edb7211_map_io,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .init_machine   = edb7211_init,
        .handle_irq     = clps711x_handle_irq,
        .restart        = clps711x_restart,
index 7d01255..c5675ef 100644 (file)
@@ -78,7 +78,7 @@ MACHINE_START(FORTUNET, "ARM-FortuNet")
        .fixup          = fortunet_fixup,
        .map_io         = clps711x_map_io,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .handle_irq     = clps711x_handle_irq,
        .restart        = clps711x_restart,
 MACHINE_END
index 1518fc8..8d3ee67 100644 (file)
@@ -224,7 +224,7 @@ MACHINE_START(P720T, "ARM-Prospector720T")
        .map_io         = p720t_map_io,
        .init_early     = p720t_init_early,
        .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
+       .init_time      = clps711x_timer_init,
        .init_machine   = p720t_init,
        .init_late      = p720t_init_late,
        .handle_irq     = clps711x_handle_irq,
index e046439..20ff50f 100644 (file)
@@ -282,7 +282,7 @@ static void add_fixed_clk(struct clk *clk, const char *name, int rate)
        clk_register_clkdev(clk, name, NULL);
 }
 
-static void __init clps711x_timer_init(void)
+void __init clps711x_timer_init(void)
 {
        int osc, ext, pll, cpu, bus, timl, timh, uart, spi;
        u32 tmp;
@@ -345,10 +345,6 @@ static void __init clps711x_timer_init(void)
        setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
 }
 
-struct sys_timer clps711x_timer = {
-       .init           = clps711x_timer_init,
-};
-
 void clps711x_restart(char mode, const char *cmd)
 {
        soft_restart(0);
index b7c0c75..f84a729 100644 (file)
@@ -8,10 +8,8 @@
 #define CLPS711X_NR_GPIO       (4 * 8 + 3)
 #define CLPS711X_GPIO(prt, bit)        ((prt) * 8 + (bit))
 
-struct sys_timer;
-
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
+extern void clps711x_timer_init(void);
 extern void clps711x_handle_irq(struct pt_regs *regs);
 extern void clps711x_restart(char mode, const char *cmd);
-extern struct sys_timer clps711x_timer;
index 26f36d7..a71867e 100644 (file)
@@ -249,7 +249,7 @@ MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board")
        .atag_offset    = 0x100,
        .map_io         = cns3420_map_io,
        .init_irq       = cns3xxx_init_irq,
-       .timer          = &cns3xxx_timer,
+       .init_time      = cns3xxx_timer_init,
        .init_machine   = cns3420_init,
        .restart        = cns3xxx_restart,
 MACHINE_END
index db3806c..e698f26 100644 (file)
@@ -134,7 +134,6 @@ static int cns3xxx_timer_set_next_event(unsigned long evt,
 
 static struct clock_event_device cns3xxx_tmr1_clockevent = {
        .name           = "cns3xxx timer1",
-       .shift          = 8,
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode       = cns3xxx_timer_set_mode,
        .set_next_event = cns3xxx_timer_set_next_event,
@@ -145,15 +144,9 @@ static struct clock_event_device cns3xxx_tmr1_clockevent = {
 static void __init cns3xxx_clockevents_init(unsigned int timer_irq)
 {
        cns3xxx_tmr1_clockevent.irq = timer_irq;
-       cns3xxx_tmr1_clockevent.mult =
-               div_sc((cns3xxx_cpu_clock() >> 3) * 1000000, NSEC_PER_SEC,
-                      cns3xxx_tmr1_clockevent.shift);
-       cns3xxx_tmr1_clockevent.max_delta_ns =
-               clockevent_delta2ns(0xffffffff, &cns3xxx_tmr1_clockevent);
-       cns3xxx_tmr1_clockevent.min_delta_ns =
-               clockevent_delta2ns(0xf, &cns3xxx_tmr1_clockevent);
-
-       clockevents_register_device(&cns3xxx_tmr1_clockevent);
+       clockevents_config_and_register(&cns3xxx_tmr1_clockevent,
+                                       (cns3xxx_cpu_clock() >> 3) * 1000000,
+                                       0xf, 0xffffffff);
 }
 
 /*
@@ -235,17 +228,13 @@ static void __init __cns3xxx_timer_init(unsigned int timer_irq)
        cns3xxx_clockevents_init(timer_irq);
 }
 
-static void __init cns3xxx_timer_init(void)
+void __init cns3xxx_timer_init(void)
 {
        cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
 
        __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
 }
 
-struct sys_timer cns3xxx_timer = {
-       .init = cns3xxx_timer_init,
-};
-
 #ifdef CONFIG_CACHE_L2X0
 
 void __init cns3xxx_l2x0_init(void)
index 4894b8c..b23b17b 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef __CNS3XXX_CORE_H
 #define __CNS3XXX_CORE_H
 
-extern struct sys_timer cns3xxx_timer;
+extern void cns3xxx_timer_init(void);
 
 #ifdef CONFIG_CACHE_L2X0
 void __init cns3xxx_l2x0_init(void);
index 95b5e10..e374271 100644 (file)
@@ -679,7 +679,7 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
        .atag_offset    = 0x100,
        .map_io         = da830_evm_map_io,
        .init_irq       = cp_intc_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = da830_evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 0299915..3b33560 100644 (file)
@@ -1599,7 +1599,7 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
        .atag_offset    = 0x100,
        .map_io         = da850_evm_map_io,
        .init_irq       = cp_intc_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = da850_evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index cdf8d07..147b8e1 100644 (file)
@@ -355,7 +355,7 @@ MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
        .atag_offset  = 0x100,
        .map_io       = dm355_evm_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = dm355_evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index d419545..dff4ddc 100644 (file)
@@ -274,7 +274,7 @@ MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard")
        .atag_offset  = 0x100,
        .map_io       = dm355_leopard_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = dm355_leopard_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 5d49c75..c2d4958 100644 (file)
@@ -616,7 +616,7 @@ MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM")
        .atag_offset    = 0x100,
        .map_io         = dm365_evm_map_io,
        .init_irq       = davinci_irq_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = dm365_evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index f5e018d..e4a16f9 100644 (file)
@@ -825,7 +825,7 @@ MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
        .atag_offset  = 0x100,
        .map_io       = davinci_evm_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = davinci_evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 6e2f163..de7adff 100644 (file)
@@ -818,7 +818,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
        .atag_offset  = 0x100,
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
@@ -829,7 +829,7 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
        .atag_offset  = 0x100,
        .map_io       = davinci_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = evm_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 43e4a0d..b0df578 100644 (file)
@@ -570,7 +570,7 @@ MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
        .atag_offset    = 0x100,
        .map_io         = mityomapl138_map_io,
        .init_irq       = cp_intc_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = mityomapl138_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 3e3e3af..1c98107 100644 (file)
@@ -237,7 +237,7 @@ MACHINE_START(NEUROS_OSD2, "Neuros OSD2")
        .atag_offset    = 0x100,
        .map_io          = davinci_ntosd2_map_io,
        .init_irq       = davinci_irq_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = davinci_ntosd2_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index dc1208e..deb3922 100644 (file)
@@ -341,7 +341,7 @@ MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
        .atag_offset    = 0x100,
        .map_io         = omapl138_hawk_map_io,
        .init_irq       = cp_intc_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = omapl138_hawk_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 6957787..739be7e 100644 (file)
@@ -155,7 +155,7 @@ MACHINE_START(SFFSDR, "Lyrtech SFFSDR")
        .atag_offset  = 0x100,
        .map_io       = davinci_sffsdr_map_io,
        .init_irq     = davinci_irq_init,
-       .timer        = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine = davinci_sffsdr_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index be30997..4f41602 100644 (file)
@@ -280,7 +280,7 @@ MACHINE_START(TNETV107X, "TNETV107X EVM")
        .atag_offset    = 0x100,
        .map_io         = tnetv107x_init,
        .init_irq       = cp_intc_init,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = tnetv107x_evm_board_init,
        .init_late      = davinci_init_late,
        .dma_zone_size  = SZ_128M,
index 37c27af..9a7c76e 100644 (file)
@@ -56,7 +56,7 @@ static const char *da850_boards_compat[] __initdata = {
 DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
        .map_io         = da850_init,
        .init_irq       = da8xx_init_irq,
-       .timer          = &davinci_timer,
+       .init_time      = davinci_timer_init,
        .init_machine   = da850_init_machine,
        .dt_compat      = da850_boards_compat,
        .init_late      = davinci_init_late,
index 046c723..b124b77 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 
-struct sys_timer;
-
-extern struct sys_timer davinci_timer;
+extern void davinci_timer_init(void);
 
 extern void davinci_irq_init(void);
 extern void __iomem *davinci_intc_base;
index 9847938..bad361e 100644 (file)
@@ -337,7 +337,7 @@ static struct clock_event_device clockevent_davinci = {
 };
 
 
-static void __init davinci_timer_init(void)
+void __init davinci_timer_init(void)
 {
        struct clk *timer_clk;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
@@ -410,11 +410,6 @@ static void __init davinci_timer_init(void)
                timer32_config(&timers[i]);
 }
 
-struct sys_timer davinci_timer = {
-       .init   = davinci_timer_init,
-};
-
-
 /* reset board using watchdog timer */
 void davinci_watchdog_reset(struct platform_device *pdev)
 {
index 792b4e2..0dc39cf 100644 (file)
@@ -92,6 +92,6 @@ MACHINE_START(CM_A510, "Compulab CM-A510 Board")
        .map_io         = dove_map_io,
        .init_early     = dove_init_early,
        .init_irq       = dove_init_irq,
-       .timer          = &dove_timer,
+       .init_time      = dove_timer_init,
        .restart        = dove_restart,
 MACHINE_END
index 89f4f99..0c7911b 100644 (file)
@@ -242,17 +242,13 @@ static int __init dove_find_tclk(void)
        return 166666667;
 }
 
-static void __init dove_timer_init(void)
+void __init dove_timer_init(void)
 {
        dove_tclk = dove_find_tclk();
        orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
                        IRQ_DOVE_BRIDGE, dove_tclk);
 }
 
-struct sys_timer dove_timer = {
-       .init = dove_timer_init,
-};
-
 /*****************************************************************************
  * Cryptographic Engines and Security Accelerator (CESA)
  ****************************************************************************/
@@ -454,7 +450,7 @@ DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
        .map_io         = dove_map_io,
        .init_early     = dove_init_early,
        .init_irq       = orion_dt_init_irq,
-       .timer          = &dove_timer,
+       .init_time      = dove_timer_init,
        .init_machine   = dove_dt_init,
        .restart        = dove_restart,
        .dt_compat      = dove_dt_board_compat,
index 1a23340..ee59fba 100644 (file)
@@ -14,7 +14,7 @@
 struct mv643xx_eth_platform_data;
 struct mv_sata_platform_data;
 
-extern struct sys_timer dove_timer;
+extern void dove_timer_init(void);
 
 /*
  * Basic Dove init functions used early by machine-setup.
index bc2867f..76e26f9 100644 (file)
@@ -98,6 +98,6 @@ MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
        .map_io         = dove_map_io,
        .init_early     = dove_init_early,
        .init_irq       = dove_init_irq,
-       .timer          = &dove_timer,
+       .init_time      = dove_timer_init,
        .restart        = dove_restart,
 MACHINE_END
index f0fe6b5..b13cc74 100644 (file)
@@ -158,7 +158,7 @@ static void __init ebsa110_init_early(void)
  * interrupt, then the PIT counter will roll over (ie, be negative).
  * This actually works out to be convenient.
  */
-static unsigned long ebsa110_gettimeoffset(void)
+static u32 ebsa110_gettimeoffset(void)
 {
        unsigned long offset, count;
 
@@ -181,7 +181,7 @@ static unsigned long ebsa110_gettimeoffset(void)
         */
        offset = offset * (1000000 / HZ) / COUNT;
 
-       return offset;
+       return offset * 1000;
 }
 
 static irqreturn_t
@@ -213,8 +213,10 @@ static struct irqaction ebsa110_timer_irq = {
 /*
  * Set up timer interrupt.
  */
-static void __init ebsa110_timer_init(void)
+void __init ebsa110_timer_init(void)
 {
+       arch_gettimeoffset = ebsa110_gettimeoffset;
+
        /*
         * Timer 1, mode 2, LSB/MSB
         */
@@ -225,11 +227,6 @@ static void __init ebsa110_timer_init(void)
        setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq);
 }
 
-static struct sys_timer ebsa110_timer = {
-       .init           = ebsa110_timer_init,
-       .offset         = ebsa110_gettimeoffset,
-};
-
 static struct plat_serial8250_port serial_platform_data[] = {
        {
                .iobase         = 0x3f8,
@@ -328,6 +325,6 @@ MACHINE_START(EBSA110, "EBSA110")
        .map_io         = ebsa110_map_io,
        .init_early     = ebsa110_init_early,
        .init_irq       = ebsa110_init_irq,
-       .timer          = &ebsa110_timer,
+       .init_time      = ebsa110_timer_init,
        .restart        = ebsa110_restart,
 MACHINE_END
index 19332bf..bda6c3a 100644 (file)
@@ -38,7 +38,7 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = adssphere_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index c533f37..c49ed3d 100644 (file)
@@ -139,11 +139,29 @@ static struct irqaction ep93xx_timer_irq = {
        .handler        = ep93xx_timer_interrupt,
 };
 
-static void __init ep93xx_timer_init(void)
+static u32 ep93xx_gettimeoffset(void)
+{
+       int offset;
+
+       offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
+
+       /*
+        * Timer 4 is based on a 983.04 kHz reference clock,
+        * so dividing by 983040 gives the fraction of a second,
+        * so dividing by 0.983040 converts to uS.
+        * Refactor the calculation to avoid overflow.
+        * Finally, multiply by 1000 to give nS.
+        */
+       return (offset + (53 * offset / 3072)) * 1000;
+}
+
+void __init ep93xx_timer_init(void)
 {
        u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
                    EP93XX_TIMER123_CONTROL_CLKSEL;
 
+       arch_gettimeoffset = ep93xx_gettimeoffset;
+
        /* Enable periodic HZ timer.  */
        __raw_writel(tmode, EP93XX_TIMER1_CONTROL);
        __raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD);
@@ -157,21 +175,6 @@ static void __init ep93xx_timer_init(void)
        setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
 }
 
-static unsigned long ep93xx_gettimeoffset(void)
-{
-       int offset;
-
-       offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
-
-       /* Calculate (1000000 / 983040) * offset.  */
-       return offset + (53 * offset / 3072);
-}
-
-struct sys_timer ep93xx_timer = {
-       .init           = ep93xx_timer_init,
-       .offset         = ep93xx_gettimeoffset,
-};
-
 
 /*************************************************************************
  * EP93xx IRQ handling
index 5abf2cb..27b14ae 100644 (file)
@@ -275,7 +275,7 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -288,7 +288,7 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -301,7 +301,7 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -314,7 +314,7 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -327,7 +327,7 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -340,7 +340,7 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -353,7 +353,7 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -366,7 +366,7 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = edb93xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index 2a7375b..0cca5b1 100644 (file)
@@ -38,7 +38,7 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = gesbc9312_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index 33a5122..a14e1b3 100644 (file)
@@ -53,7 +53,7 @@ int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
 void ep93xx_ide_release_gpio(struct platform_device *pdev);
 
 void ep93xx_init_devices(void);
-extern struct sys_timer ep93xx_timer;
+extern void ep93xx_timer_init(void);
 
 void ep93xx_restart(char, const char *);
 void ep93xx_init_late(void);
index 723c0d3..373583c 100644 (file)
@@ -81,7 +81,7 @@ MACHINE_START(MICRO9, "Contec Micro9-High")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = micro9_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -94,7 +94,7 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = micro9_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -107,7 +107,7 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = micro9_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
@@ -120,7 +120,7 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = micro9_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index 651a7db..36f22c1 100644 (file)
@@ -82,7 +82,7 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = simone_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index b4389d3..aa86f86 100644 (file)
@@ -175,7 +175,7 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
        .atag_offset    = 0x100,
        .map_io         = ep93xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = snappercl15_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index 1eeee09..61f4b5d 100644 (file)
@@ -245,7 +245,7 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
        .atag_offset    = 0x100,
        .map_io         = ts72xx_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = ts72xx_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index 723d048..605956f 100644 (file)
@@ -363,7 +363,7 @@ MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
        .atag_offset    = 0x100,
        .map_io         = vision_map_io,
        .init_irq       = ep93xx_init_irq,
-       .timer          = &ep93xx_timer,
+       .init_time      = ep93xx_timer_init,
        .init_machine   = vision_init_machine,
        .init_late      = ep93xx_init_late,
        .restart        = ep93xx_restart,
index e103c29..85afb03 100644 (file)
@@ -414,7 +414,7 @@ config MACH_EXYNOS4_DT
        select CPU_EXYNOS4210
        select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
        select PINCTRL
-       select PINCTRL_EXYNOS4
+       select PINCTRL_EXYNOS
        select USE_OF
        help
          Machine support for Samsung Exynos4 machine with device tree enabled.
index 04744f9..12f2f11 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-extern struct sys_timer exynos4_timer;
+extern void exynos4_timer_init(void);
 
 struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
index a11a36f..685f291 100644 (file)
@@ -202,6 +202,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
        .map_io         = armlex4210_map_io,
        .init_machine   = armlex4210_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .restart        = exynos4_restart,
 MACHINE_END
index 34c45b6..112d10e 100644 (file)
@@ -108,7 +108,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        .map_io         = exynos4_dt_map_io,
        .init_machine   = exynos4_dt_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .dt_compat      = exynos4_dt_compat,
        .restart        = exynos4_restart,
 MACHINE_END
index 3a3bee4..0deeecf 100644 (file)
@@ -180,7 +180,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
        .map_io         = exynos5_dt_map_io,
        .init_machine   = exynos5_dt_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .dt_compat      = exynos5_dt_compat,
        .restart        = exynos5_restart,
        .reserve        = exynos5_reserve,
index 55f8183..b8b3fbf 100644 (file)
@@ -1380,7 +1380,7 @@ MACHINE_START(NURI, "NURI")
        .map_io         = nuri_map_io,
        .init_machine   = nuri_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .reserve        = &nuri_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index 45cda36..579d2d1 100644 (file)
@@ -815,7 +815,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
        .map_io         = origen_map_io,
        .init_machine   = origen_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .reserve        = &origen_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index d5dbd51..fe61496 100644 (file)
@@ -376,7 +376,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
        .init_irq       = exynos4_init_irq,
        .map_io         = smdk4x12_map_io,
        .init_machine   = smdk4x12_machine_init,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .restart        = exynos4_restart,
        .reserve        = &smdk4x12_reserve,
 MACHINE_END
@@ -390,7 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
        .map_io         = smdk4x12_map_io,
        .init_machine   = smdk4x12_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .restart        = exynos4_restart,
        .reserve        = &smdk4x12_reserve,
 MACHINE_END
index b095964..d716729 100644 (file)
@@ -423,7 +423,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
        .init_irq       = exynos4_init_irq,
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
@@ -436,7 +436,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &exynos4_timer,
+       .init_time      = exynos4_timer_init,
        .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index be37775..c9d33a4 100644 (file)
@@ -1152,7 +1152,7 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        .map_io         = universal_map_io,
        .init_machine   = universal_machine_init,
        .init_late      = exynos_init_late,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .reserve        = &universal_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index baefe9b..c9d6650 100644 (file)
@@ -254,13 +254,9 @@ static struct irqaction mct_comp_event_irq = {
 
 static void exynos4_clockevent_init(void)
 {
-       clockevents_calc_mult_shift(&mct_comp_device, clk_rate, 5);
-       mct_comp_device.max_delta_ns =
-               clockevent_delta2ns(0xffffffff, &mct_comp_device);
-       mct_comp_device.min_delta_ns =
-               clockevent_delta2ns(0xf, &mct_comp_device);
        mct_comp_device.cpumask = cpumask_of(0);
-       clockevents_register_device(&mct_comp_device);
+       clockevents_config_and_register(&mct_comp_device, clk_rate,
+                                       0xf, 0xffffffff);
 
        if (soc_is_exynos5250())
                setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
@@ -403,14 +399,8 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
        evt->set_mode = exynos4_tick_set_mode;
        evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
        evt->rating = 450;
-
-       clockevents_calc_mult_shift(evt, clk_rate / (TICK_BASE_CNT + 1), 5);
-       evt->max_delta_ns =
-               clockevent_delta2ns(0x7fffffff, evt);
-       evt->min_delta_ns =
-               clockevent_delta2ns(0xf, evt);
-
-       clockevents_register_device(evt);
+       clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1),
+                                       0xf, 0x7fffffff);
 
        exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
 
@@ -477,7 +467,7 @@ static void __init exynos4_timer_resources(void)
 #endif /* CONFIG_LOCAL_TIMERS */
 }
 
-static void __init exynos_timer_init(void)
+void __init exynos4_timer_init(void)
 {
        if (soc_is_exynos5440()) {
                arch_timer_of_register();
@@ -493,7 +483,3 @@ static void __init exynos_timer_init(void)
        exynos4_clocksource_init();
        exynos4_clockevent_init();
 }
-
-struct sys_timer exynos4_timer = {
-       .init           = exynos_timer_init,
-};
index 25b4536..6987a09 100644 (file)
@@ -90,6 +90,6 @@ MACHINE_START(CATS, "Chalice-CATS")
        .fixup          = fixup_cats,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
-       .timer          = &isa_timer,
+       .init_time      = isa_timer_init,
        .restart        = footbridge_restart,
 MACHINE_END
index c9767b8..a846e50 100644 (file)
@@ -1,6 +1,6 @@
 
-extern struct sys_timer footbridge_timer;
-extern struct sys_timer isa_timer;
+extern void footbridge_timer_init(void);
+extern void isa_timer_init(void);
 
 extern void isa_rtc_init(void);
 
index 3b54196..9ee78f7 100644 (file)
@@ -93,7 +93,7 @@ static struct irqaction footbridge_timer_irq = {
 /*
  * Set up timer interrupt.
  */
-static void __init footbridge_timer_init(void)
+void __init footbridge_timer_init(void)
 {
        struct clock_event_device *ce = &ckevt_dc21285;
 
@@ -101,14 +101,6 @@ static void __init footbridge_timer_init(void)
 
        setup_irq(ce->irq, &footbridge_timer_irq);
 
-       clockevents_calc_mult_shift(ce, mem_fclk_21285, 5);
-       ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce);
-       ce->min_delta_ns = clockevent_delta2ns(0x000004, ce);
        ce->cpumask = cpumask_of(smp_processor_id());
-
-       clockevents_register_device(ce);
+       clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
 }
-
-struct sys_timer footbridge_timer = {
-       .init           = footbridge_timer_init,
-};
index b09551e..b082435 100644 (file)
@@ -101,7 +101,7 @@ MACHINE_START(EBSA285, "EBSA285")
        .video_end      = 0x000bffff,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
-       .timer          = &footbridge_timer,
+       .init_time      = footbridge_timer_init,
        .restart        = footbridge_restart,
 MACHINE_END
 
index c40bb41..d9301dd 100644 (file)
@@ -31,14 +31,10 @@ static struct irqaction pit_timer_irq = {
        .dev_id         = &i8253_clockevent,
 };
 
-static void __init isa_timer_init(void)
+void __init isa_timer_init(void)
 {
        clocksource_i8253_init();
 
        setup_irq(i8253_clockevent.irq, &pit_timer_irq);
        clockevent_i8253_init(false);
 }
-
-struct sys_timer isa_timer = {
-       .init           = isa_timer_init,
-};
index d2d1433..90ea23f 100644 (file)
@@ -766,6 +766,6 @@ MACHINE_START(NETWINDER, "Rebel-NetWinder")
        .fixup          = fixup_netwinder,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
-       .timer          = &isa_timer,
+       .init_time      = isa_timer_init,
        .restart        = netwinder_restart,
 MACHINE_END
index e1e9990..7bdeabd 100644 (file)
@@ -18,7 +18,7 @@ MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
        .atag_offset    = 0x100,
        .map_io         = footbridge_map_io,
        .init_irq       = footbridge_init_irq,
-       .timer          = &footbridge_timer,
+       .init_time      = footbridge_timer_init,
        .restart        = footbridge_restart,
 MACHINE_END
 
index 5927d3c..08bd650 100644 (file)
 
 #include "common.h"
 
-static struct sys_timer ib4220b_timer = {
-       .init   = gemini_timer_init,
-};
-
 static struct gpio_led ib4220b_leds[] = {
        {
                .name                   = "nas4220b:orange:hdd",
@@ -105,6 +101,6 @@ MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
        .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
-       .timer          = &ib4220b_timer,
+       .init_time      = gemini_timer_init,
        .init_machine   = ib4220b_init,
 MACHINE_END
index cd7437a..fa0a363 100644 (file)
@@ -71,10 +71,6 @@ static struct platform_device rut1xx_leds = {
        },
 };
 
-static struct sys_timer rut1xx_timer = {
-       .init   = gemini_timer_init,
-};
-
 static void __init rut1xx_init(void)
 {
        gemini_gpio_init();
@@ -89,6 +85,6 @@ MACHINE_START(RUT100, "Teltonika RUT100")
        .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
-       .timer          = &rut1xx_timer,
+       .init_time      = gemini_timer_init,
        .init_machine   = rut1xx_init,
 MACHINE_END
index a367880..3321cd6 100644 (file)
@@ -80,10 +80,6 @@ static struct platform_device wbd111_leds_device = {
        },
 };
 
-static struct sys_timer wbd111_timer = {
-       .init   = gemini_timer_init,
-};
-
 static struct mtd_partition wbd111_partitions[] = {
        {
                .name           = "RedBoot",
@@ -132,6 +128,6 @@ MACHINE_START(WBD111, "Wiliboard WBD-111")
        .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
-       .timer          = &wbd111_timer,
+       .init_time      = gemini_timer_init,
        .init_machine   = wbd111_init,
 MACHINE_END
index f382811..fe33c82 100644 (file)
@@ -80,10 +80,6 @@ static struct platform_device wbd222_leds_device = {
        },
 };
 
-static struct sys_timer wbd222_timer = {
-       .init   = gemini_timer_init,
-};
-
 static struct mtd_partition wbd222_partitions[] = {
        {
                .name           = "RedBoot",
@@ -132,6 +128,6 @@ MACHINE_START(WBD222, "Wiliboard WBD-222")
        .atag_offset    = 0x100,
        .map_io         = gemini_map_io,
        .init_irq       = gemini_init_irq,
-       .timer          = &wbd222_timer,
+       .init_time      = gemini_timer_init,
        .init_machine   = wbd222_init,
 MACHINE_END
index aa1331e..17ef91f 100644 (file)
@@ -42,12 +42,12 @@ void __init arch_dma_init(dma_t *dma)
 }
 
 /*
- * Return usecs since last timer reload
+ * Return nsecs since last timer reload
  * (timercount * (usecs perjiffie)) / (ticks per jiffie)
  */
-unsigned long h720x_gettimeoffset(void)
+u32 h720x_gettimeoffset(void)
 {
-       return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH;
+       return ((CPU_REG(TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH) * 1000;
 }
 
 /*
index 2489537..7e73841 100644 (file)
  *
  */
 
-extern unsigned long h720x_gettimeoffset(void);
+extern u32 h720x_gettimeoffset(void);
 extern void __init h720x_init_irq(void);
 extern void __init h720x_map_io(void);
 extern void h720x_restart(char, const char *);
 
 #ifdef CONFIG_ARCH_H7202
-extern struct sys_timer h7202_timer;
+extern void h7202_timer_init(void);
 extern void __init init_hw_h7202(void);
 extern void __init h7202_init_irq(void);
 extern void __init h7202_init_time(void);
 #endif
 
 #ifdef CONFIG_ARCH_H7201
-extern struct sys_timer h7201_timer;
+extern void h7201_timer_init(void);
 #endif
index 24df2a3..13c7412 100644 (file)
@@ -44,8 +44,10 @@ static struct irqaction h7201_timer_irq = {
 /*
  * Setup TIMER0 as system timer
  */
-void __init h7201_init_time(void)
+void __init h7201_timer_init(void)
 {
+       arch_gettimeoffset = h720x_gettimeoffset;
+
        CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -53,8 +55,3 @@ void __init h7201_init_time(void)
 
        setup_irq(IRQ_TIMER0, &h7201_timer_irq);
 }
-
-struct sys_timer h7201_timer = {
-       .init           = h7201_init_time,
-       .offset         = h720x_gettimeoffset,
-};
index c37d570..e2ae7e8 100644 (file)
@@ -178,8 +178,10 @@ static struct irqaction h7202_timer_irq = {
 /*
  * Setup TIMER0 as system timer
  */
-void __init h7202_init_time(void)
+void __init h7202_timer_init(void)
 {
+       arch_gettimeoffset = h720x_gettimeoffset;
+
        CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -188,11 +190,6 @@ void __init h7202_init_time(void)
        setup_irq(IRQ_TIMER0, &h7202_timer_irq);
 }
 
-struct sys_timer h7202_timer = {
-       .init           = h7202_init_time,
-       .offset         = h720x_gettimeoffset,
-};
-
 void __init h7202_init_irq (void)
 {
        int     irq;
index 5fdb20c..4fdeb68 100644 (file)
@@ -32,7 +32,7 @@ MACHINE_START(H7201, "Hynix GMS30C7201")
        .atag_offset    = 0x1000,
        .map_io         = h720x_map_io,
        .init_irq       = h720x_init_irq,
-       .timer          = &h7201_timer,
+       .init_time      = h7201_timer_init,
        .dma_zone_size  = SZ_256M,
        .restart        = h720x_restart,
 MACHINE_END
index 1696730..f68e967 100644 (file)
@@ -74,7 +74,7 @@ MACHINE_START(H7202, "Hynix HMS30C7202")
        .atag_offset    = 0x100,
        .map_io         = h720x_map_io,
        .init_irq       = h7202_init_irq,
-       .timer          = &h7202_timer,
+       .init_time      = h7202_timer_init,
        .init_machine   = init_eval_h7202,
        .dma_zone_size  = SZ_256M,
        .restart        = h720x_restart,
index f9191ea..fd630bc 100644 (file)
@@ -123,10 +123,6 @@ static void __init highbank_timer_init(void)
        arch_timer_sched_clock_init();
 }
 
-static struct sys_timer highbank_timer = {
-       .init = highbank_timer_init,
-};
-
 static void highbank_power_off(void)
 {
        highbank_set_pwr_shutdown();
@@ -203,7 +199,7 @@ DT_MACHINE_START(HIGHBANK, "Highbank")
        .smp            = smp_ops(highbank_smp_ops),
        .map_io         = debug_ll_io_init,
        .init_irq       = highbank_init_irq,
-       .timer          = &highbank_timer,
+       .init_time      = highbank_timer_init,
        .init_machine   = highbank_init,
        .dt_compat      = highbank_match,
        .restart        = highbank_restart,
index 04a5961..e02de18 100644 (file)
@@ -178,7 +178,6 @@ static struct irqaction epit_timer_irq = {
 static struct clock_event_device clockevent_epit = {
        .name           = "epit",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .set_mode       = epit_set_mode,
        .set_next_event = epit_set_next_event,
        .rating         = 200,
@@ -186,18 +185,10 @@ static struct clock_event_device clockevent_epit = {
 
 static int __init epit_clockevent_init(struct clk *timer_clk)
 {
-       unsigned int c = clk_get_rate(timer_clk);
-
-       clockevent_epit.mult = div_sc(c, NSEC_PER_SEC,
-                                       clockevent_epit.shift);
-       clockevent_epit.max_delta_ns =
-                       clockevent_delta2ns(0xfffffffe, &clockevent_epit);
-       clockevent_epit.min_delta_ns =
-                       clockevent_delta2ns(0x800, &clockevent_epit);
-
        clockevent_epit.cpumask = cpumask_of(0);
-
-       clockevents_register_device(&clockevent_epit);
+       clockevents_config_and_register(&clockevent_epit,
+                                       clk_get_rate(timer_clk),
+                                       0x800, 0xfffffffe);
 
        return 0;
 }
index e17dfbc..03b65e5 100644 (file)
@@ -22,15 +22,6 @@ static void __init imx25_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx25_timer_init(void)
-{
-       mx25_clocks_init_dt();
-}
-
-static struct sys_timer imx25_timer = {
-       .init = imx25_timer_init,
-};
-
 static const char * const imx25_dt_board_compat[] __initconst = {
        "fsl,imx25",
        NULL
@@ -41,7 +32,7 @@ DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
        .init_early     = imx25_init_early,
        .init_irq       = mx25_init_irq,
        .handle_irq     = imx25_handle_irq,
-       .timer          = &imx25_timer,
+       .init_time      = imx25_timer_init,
        .init_machine   = imx25_dt_init,
        .dt_compat      = imx25_dt_board_compat,
        .restart        = mxc_restart,
index ebfae96..c915a49 100644 (file)
@@ -39,26 +39,22 @@ static void __init imx27_dt_init(void)
                             imx27_auxdata_lookup, NULL);
 }
 
-static void __init imx27_timer_init(void)
-{
-       mx27_clocks_init_dt();
-}
-
-static struct sys_timer imx27_timer = {
-       .init = imx27_timer_init,
-};
-
 static const char * const imx27_dt_board_compat[] __initconst = {
        "fsl,imx27",
        NULL
 };
 
+static void __init imx27_timer_init(void)
+{
+       mx27_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
        .map_io         = mx27_map_io,
        .init_early     = imx27_init_early,
        .init_irq       = mx27_init_irq,
        .handle_irq     = imx27_handle_irq,
-       .timer          = &imx27_timer,
+       .init_time      = imx27_timer_init,
        .init_machine   = imx27_dt_init,
        .dt_compat      = imx27_dt_board_compat,
        .restart        = mxc_restart,
index af476de..f9a6909 100644 (file)
@@ -38,15 +38,6 @@ static void __init imx31_dt_init(void)
                             imx31_auxdata_lookup, NULL);
 }
 
-static void __init imx31_timer_init(void)
-{
-       mx31_clocks_init_dt();
-}
-
-static struct sys_timer imx31_timer = {
-       .init = imx31_timer_init,
-};
-
 static const char *imx31_dt_board_compat[] __initdata = {
        "fsl,imx31",
        NULL
@@ -57,7 +48,7 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
        .init_early     = imx31_init_early,
        .init_irq       = mx31_init_irq,
        .handle_irq     = imx31_handle_irq,
-       .timer          = &imx31_timer,
+       .init_time      = mx31_clocks_init_dt,
        .init_machine   = imx31_dt_init,
        .dt_compat      = imx31_dt_board_compat,
        .restart        = mxc_restart,
index 5ffa40c..e2926a8 100644 (file)
@@ -24,26 +24,22 @@ static void __init imx51_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx51_timer_init(void)
-{
-       mx51_clocks_init_dt();
-}
-
-static struct sys_timer imx51_timer = {
-       .init = imx51_timer_init,
-};
-
 static const char *imx51_dt_board_compat[] __initdata = {
        "fsl,imx51",
        NULL
 };
 
+static void __init imx51_timer_init(void)
+{
+       mx51_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
        .map_io         = mx51_map_io,
        .init_early     = imx51_init_early,
        .init_irq       = mx51_init_irq,
        .handle_irq     = imx51_handle_irq,
-       .timer          = &imx51_timer,
+       .init_time      = imx51_timer_init,
        .init_machine   = imx51_dt_init,
        .init_late      = imx51_init_late,
        .dt_compat      = imx51_dt_board_compat,
index 5c9bd2c..067580b 100644 (file)
@@ -137,17 +137,13 @@ static void __init apf9328_timer_init(void)
        mx1_clocks_init(32768);
 }
 
-static struct sys_timer apf9328_timer = {
-       .init   = apf9328_timer_init,
-};
-
 MACHINE_START(APF9328, "Armadeus APF9328")
        /* Maintainer: Gwenhael Goavec-Merou, ARMadeus Systems */
        .map_io       = mx1_map_io,
        .init_early   = imx1_init_early,
        .init_irq     = mx1_init_irq,
        .handle_irq   = imx1_handle_irq,
-       .timer        = &apf9328_timer,
+       .init_time      = apf9328_timer_init,
        .init_machine = apf9328_init,
        .restart        = mxc_restart,
 MACHINE_END
index 59bd6b0..368a6e3 100644 (file)
@@ -557,10 +557,6 @@ static void __init armadillo5x0_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer armadillo5x0_timer = {
-       .init   = armadillo5x0_timer_init,
-};
-
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
        /* Maintainer: Alberto Panizzo  */
        .atag_offset = 0x100,
@@ -568,7 +564,7 @@ MACHINE_START(ARMADILLO5X0, "Armadillo-500")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &armadillo5x0_timer,
+       .init_time      = armadillo5x0_timer_init,
        .init_machine = armadillo5x0_init,
        .restart        = mxc_restart,
 MACHINE_END
index 3a39d5a..2d00476 100644 (file)
@@ -53,16 +53,12 @@ static void __init bug_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer bug_timer = {
-       .init = bug_timer_init,
-};
-
 MACHINE_START(BUG, "BugLabs BUGBase")
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &bug_timer,
+       .init_time      = bug_timer_init,
        .init_machine = bug_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index 12a3706..1465593 100644 (file)
@@ -309,17 +309,13 @@ static void __init eukrea_cpuimx27_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer eukrea_cpuimx27_timer = {
-       .init = eukrea_cpuimx27_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
        .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &eukrea_cpuimx27_timer,
+       .init_time      = eukrea_cpuimx27_timer_init,
        .init_machine = eukrea_cpuimx27_init,
        .restart        = mxc_restart,
 MACHINE_END
index 5a31bf8..771362d 100644 (file)
@@ -193,10 +193,6 @@ static void __init eukrea_cpuimx35_timer_init(void)
        mx35_clocks_init();
 }
 
-static struct sys_timer eukrea_cpuimx35_timer = {
-       .init   = eukrea_cpuimx35_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
        /* Maintainer: Eukrea Electromatique */
        .atag_offset = 0x100,
@@ -204,7 +200,7 @@ MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
        .handle_irq = imx35_handle_irq,
-       .timer = &eukrea_cpuimx35_timer,
+       .init_time      = eukrea_cpuimx35_timer_init,
        .init_machine = eukrea_cpuimx35_init,
        .restart        = mxc_restart,
 MACHINE_END
index b727de0..9b73932 100644 (file)
@@ -355,10 +355,6 @@ static void __init eukrea_cpuimx51sd_timer_init(void)
        mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-       .init   = eukrea_cpuimx51sd_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
        /* Maintainer: Eric Bénard <eric@eukrea.com> */
        .atag_offset = 0x100,
@@ -366,7 +362,7 @@ MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
        .handle_irq = imx51_handle_irq,
-       .timer = &mxc_timer,
+       .init_time      = eukrea_cpuimx51sd_timer_init,
        .init_machine = eukrea_cpuimx51sd_init,
        .init_late      = imx51_init_late,
        .restart        = mxc_restart,
index 75027a5..4bf4544 100644 (file)
@@ -159,10 +159,6 @@ static void __init eukrea_cpuimx25_timer_init(void)
        mx25_clocks_init();
 }
 
-static struct sys_timer eukrea_cpuimx25_timer = {
-       .init   = eukrea_cpuimx25_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
        /* Maintainer: Eukrea Electromatique */
        .atag_offset = 0x100,
@@ -170,7 +166,7 @@ MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
        .init_early = imx25_init_early,
        .init_irq = mx25_init_irq,
        .handle_irq = imx25_handle_irq,
-       .timer = &eukrea_cpuimx25_timer,
+       .init_time = eukrea_cpuimx25_timer_init,
        .init_machine = eukrea_cpuimx25_init,
        .restart        = mxc_restart,
 MACHINE_END
index 318bd8d..29ac8ee 100644 (file)
@@ -598,10 +598,6 @@ static void __init visstrim_m10_timer_init(void)
        mx27_clocks_init((unsigned long)25000000);
 }
 
-static struct sys_timer visstrim_m10_timer = {
-       .init   = visstrim_m10_timer_init,
-};
-
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
        .atag_offset = 0x100,
        .reserve = visstrim_reserve,
@@ -609,7 +605,7 @@ MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &visstrim_m10_timer,
+       .init_time      = visstrim_m10_timer_init,
        .init_machine = visstrim_m10_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index 53a8601..1a851ae 100644 (file)
@@ -65,10 +65,6 @@ static void __init mx27ipcam_timer_init(void)
        mx27_clocks_init(25000000);
 }
 
-static struct sys_timer mx27ipcam_timer = {
-       .init   = mx27ipcam_timer_init,
-};
-
 MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
        /* maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -76,7 +72,7 @@ MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &mx27ipcam_timer,
+       .init_time      = mx27ipcam_timer_init,
        .init_machine = mx27ipcam_init,
        .restart        = mxc_restart,
 MACHINE_END
index fc8dce9..3da2e3e 100644 (file)
@@ -72,17 +72,13 @@ static void __init mx27lite_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mx27lite_timer = {
-       .init   = mx27lite_timer_init,
-};
-
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
        .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &mx27lite_timer,
+       .init_time      = mx27lite_timer_init,
        .init_machine = mx27lite_init,
        .restart        = mxc_restart,
 MACHINE_END
index 860284d..f579c61 100644 (file)
@@ -44,26 +44,22 @@ static void __init imx53_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx53_timer_init(void)
-{
-       mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
-       .init = imx53_timer_init,
-};
-
 static const char *imx53_dt_board_compat[] __initdata = {
        "fsl,imx53",
        NULL
 };
 
+static void __init imx53_timer_init(void)
+{
+       mx53_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
        .map_io         = mx53_map_io,
        .init_early     = imx53_init_early,
        .init_irq       = mx53_init_irq,
        .handle_irq     = imx53_handle_irq,
-       .timer          = &imx53_timer,
+       .init_time      = imx53_timer_init,
        .init_machine   = imx53_dt_init,
        .init_late      = imx53_init_late,
        .dt_compat      = imx53_dt_board_compat,
index 724bfeb..8d3d06e 100644 (file)
@@ -236,10 +236,6 @@ static void __init imx6q_timer_init(void)
        imx_print_silicon_rev("i.MX6Q", imx6q_revision());
 }
 
-static struct sys_timer imx6q_timer = {
-       .init = imx6q_timer_init,
-};
-
 static const char *imx6q_dt_compat[] __initdata = {
        "fsl,imx6q",
        NULL,
@@ -249,7 +245,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
        .smp            = smp_ops(imx_smp_ops),
        .map_io         = imx6q_map_io,
        .init_irq       = imx6q_init_irq,
-       .timer          = &imx6q_timer,
+       .init_time      = imx6q_timer_init,
        .init_machine   = imx6q_init_machine,
        .init_late      = imx6q_init_late,
        .dt_compat      = imx6q_dt_compat,
index 2e536ea..c7bc41d 100644 (file)
@@ -284,17 +284,13 @@ static void __init kzm_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer kzm_timer = {
-       .init = kzm_timer_init,
-};
-
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
        .atag_offset = 0x100,
        .map_io = kzm_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &kzm_timer,
+       .init_time      = kzm_timer_init,
        .init_machine = kzm_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index 06b4837..9f883e4 100644 (file)
@@ -132,10 +132,6 @@ static void __init mx1ads_timer_init(void)
        mx1_clocks_init(32000);
 }
 
-static struct sys_timer mx1ads_timer = {
-       .init   = mx1ads_timer_init,
-};
-
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
        /* Maintainer: Sascha Hauer, Pengutronix */
        .atag_offset = 0x100,
@@ -143,7 +139,7 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS")
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
        .handle_irq = imx1_handle_irq,
-       .timer = &mx1ads_timer,
+       .init_time      = mx1ads_timer_init,
        .init_machine = mx1ads_init,
        .restart        = mxc_restart,
 MACHINE_END
@@ -154,7 +150,7 @@ MACHINE_START(MXLADS, "Freescale MXLADS")
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
        .handle_irq = imx1_handle_irq,
-       .timer = &mx1ads_timer,
+       .init_time      = mx1ads_timer_init,
        .init_machine = mx1ads_init,
        .restart        = mxc_restart,
 MACHINE_END
index 6adb313..a06aa4d 100644 (file)
@@ -318,10 +318,6 @@ static void __init mx21ads_timer_init(void)
        mx21_clocks_init(32768, 26000000);
 }
 
-static struct sys_timer mx21ads_timer = {
-       .init   = mx21ads_timer_init,
-};
-
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
        /* maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -329,7 +325,7 @@ MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
        .init_early = imx21_init_early,
        .init_irq = mx21_init_irq,
        .handle_irq = imx21_handle_irq,
-       .timer = &mx21ads_timer,
+       .init_time      = mx21ads_timer_init,
        .init_machine = mx21ads_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index b1b03aa..8bcda68 100644 (file)
@@ -257,10 +257,6 @@ static void __init mx25pdk_timer_init(void)
        mx25_clocks_init();
 }
 
-static struct sys_timer mx25pdk_timer = {
-       .init   = mx25pdk_timer_init,
-};
-
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
        /* Maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -268,7 +264,7 @@ MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
        .init_early = imx25_init_early,
        .init_irq = mx25_init_irq,
        .handle_irq = imx25_handle_irq,
-       .timer = &mx25pdk_timer,
+       .init_time      = mx25pdk_timer_init,
        .init_machine = mx25pdk_init,
        .restart        = mxc_restart,
 MACHINE_END
index d0e547f..25b3e4c 100644 (file)
@@ -538,10 +538,6 @@ static void __init mx27pdk_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mx27pdk_timer = {
-       .init   = mx27pdk_timer_init,
-};
-
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
        /* maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -549,7 +545,7 @@ MACHINE_START(MX27_3DS, "Freescale MX27PDK")
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &mx27pdk_timer,
+       .init_time      = mx27pdk_timer_init,
        .init_machine = mx27pdk_init,
        .restart        = mxc_restart,
 MACHINE_END
index 3d036f5..9821b82 100644 (file)
@@ -323,10 +323,6 @@ static void __init mx27ads_timer_init(void)
        mx27_clocks_init(fref);
 }
 
-static struct sys_timer mx27ads_timer = {
-       .init   = mx27ads_timer_init,
-};
-
 static struct map_desc mx27ads_io_desc[] __initdata = {
        {
                .virtual = PBC_BASE_ADDRESS,
@@ -349,7 +345,7 @@ MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &mx27ads_timer,
+       .init_time      = mx27ads_timer_init,
        .init_machine = mx27ads_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index bc301be..1ed9161 100644 (file)
@@ -762,10 +762,6 @@ static void __init mx31_3ds_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31_3ds_timer = {
-       .init   = mx31_3ds_timer_init,
-};
-
 static void __init mx31_3ds_reserve(void)
 {
        /* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
@@ -780,7 +776,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &mx31_3ds_timer,
+       .init_time      = mx31_3ds_timer_init,
        .init_machine = mx31_3ds_init,
        .reserve = mx31_3ds_reserve,
        .restart        = mxc_restart,
index 8b56f88..daf8889 100644 (file)
@@ -576,10 +576,6 @@ static void __init mx31ads_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31ads_timer = {
-       .init   = mx31ads_timer_init,
-};
-
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
        /* Maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -587,7 +583,7 @@ MACHINE_START(MX31ADS, "Freescale MX31ADS")
        .init_early = imx31_init_early,
        .init_irq = mx31ads_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &mx31ads_timer,
+       .init_time      = mx31ads_timer_init,
        .init_machine = mx31ads_init,
        .restart        = mxc_restart,
 MACHINE_END
index 08b9965..832b1e2 100644 (file)
@@ -303,17 +303,13 @@ static void __init mx31lilly_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31lilly_timer = {
-       .init   = mx31lilly_timer_init,
-};
-
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
        .atag_offset = 0x100,
        .map_io = mx31_map_io,
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &mx31lilly_timer,
+       .init_time      = mx31lilly_timer_init,
        .init_machine = mx31lilly_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index bdcd92e..bea0729 100644 (file)
@@ -285,10 +285,6 @@ static void __init mx31lite_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31lite_timer = {
-       .init   = mx31lite_timer_init,
-};
-
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
        /* Maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -296,7 +292,7 @@ MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &mx31lite_timer,
+       .init_time      = mx31lite_timer_init,
        .init_machine = mx31lite_init,
        .restart        = mxc_restart,
 MACHINE_END
index 2517cfa..dae4cd7 100644 (file)
@@ -596,10 +596,6 @@ static void __init mx31moboard_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31moboard_timer = {
-       .init   = mx31moboard_timer_init,
-};
-
 static void __init mx31moboard_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
@@ -615,7 +611,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &mx31moboard_timer,
+       .init_time      = mx31moboard_timer_init,
        .init_machine = mx31moboard_init,
        .restart        = mxc_restart,
 MACHINE_END
index 5277da4..a42f4f0 100644 (file)
@@ -602,10 +602,6 @@ static void __init mx35pdk_timer_init(void)
        mx35_clocks_init();
 }
 
-static struct sys_timer mx35pdk_timer = {
-       .init   = mx35pdk_timer_init,
-};
-
 static void __init mx35_3ds_reserve(void)
 {
        /* reserve MX35_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
@@ -620,7 +616,7 @@ MACHINE_START(MX35_3DS, "Freescale MX35PDK")
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
        .handle_irq = imx35_handle_irq,
-       .timer = &mx35pdk_timer,
+       .init_time      = mx35pdk_timer_init,
        .init_machine = mx35_3ds_init,
        .reserve = mx35_3ds_reserve,
        .restart        = mxc_restart,
index 0c1f88a..8937902 100644 (file)
@@ -210,16 +210,12 @@ static void __init mx50_rdp_timer_init(void)
        mx50_clocks_init(32768, 24000000, 22579200);
 }
 
-static struct sys_timer mx50_rdp_timer = {
-       .init   = mx50_rdp_timer_init,
-};
-
 MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
        .map_io = mx50_map_io,
        .init_early = imx50_init_early,
        .init_irq = mx50_init_irq,
        .handle_irq = imx50_handle_irq,
-       .timer = &mx50_rdp_timer,
+       .init_time      = mx50_rdp_timer_init,
        .init_machine = mx50_rdp_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index abc25bd..2d23651 100644 (file)
@@ -160,10 +160,6 @@ static void __init mx51_3ds_timer_init(void)
        mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mx51_3ds_timer = {
-       .init = mx51_3ds_timer_init,
-};
-
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
        /* Maintainer: Freescale Semiconductor, Inc. */
        .atag_offset = 0x100,
@@ -171,7 +167,7 @@ MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
        .handle_irq = imx51_handle_irq,
-       .timer = &mx51_3ds_timer,
+       .init_time      = mx51_3ds_timer_init,
        .init_machine = mx51_3ds_init,
        .init_late      = imx51_init_late,
        .restart        = mxc_restart,
index d9a84ca..6c4d7fe 100644 (file)
@@ -418,10 +418,6 @@ static void __init mx51_babbage_timer_init(void)
        mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mx51_babbage_timer = {
-       .init = mx51_babbage_timer_init,
-};
-
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
        /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
        .atag_offset = 0x100,
@@ -429,7 +425,7 @@ MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
        .init_early = imx51_init_early,
        .init_irq = mx51_init_irq,
        .handle_irq = imx51_handle_irq,
-       .timer = &mx51_babbage_timer,
+       .init_time      = mx51_babbage_timer_init,
        .init_machine = mx51_babbage_init,
        .init_late      = imx51_init_late,
        .restart        = mxc_restart,
index f4a8c7e..a27faab 100644 (file)
@@ -261,10 +261,6 @@ static void __init mxt_td60_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mxt_td60_timer = {
-       .init   = mxt_td60_timer_init,
-};
-
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
        /* maintainer: Maxtrack Industrial */
        .atag_offset = 0x100,
@@ -272,7 +268,7 @@ MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &mxt_td60_timer,
+       .init_time      = mxt_td60_timer_init,
        .init_machine = mxt_td60_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index eee369f..b8b15bb 100644 (file)
@@ -416,10 +416,6 @@ static void __init pca100_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer pca100_timer = {
-       .init = pca100_timer_init,
-};
-
 MACHINE_START(PCA100, "phyCARD-i.MX27")
        .atag_offset = 0x100,
        .map_io = mx27_map_io,
@@ -427,6 +423,6 @@ MACHINE_START(PCA100, "phyCARD-i.MX27")
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
        .init_machine = pca100_init,
-       .timer = &pca100_timer,
+       .init_time      = pca100_timer_init,
        .restart        = mxc_restart,
 MACHINE_END
index 547fef1..bc0261e 100644 (file)
@@ -685,10 +685,6 @@ static void __init pcm037_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer pcm037_timer = {
-       .init   = pcm037_timer_init,
-};
-
 static void __init pcm037_reserve(void)
 {
        /* reserve 4 MiB for mx3-camera */
@@ -709,7 +705,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &pcm037_timer,
+       .init_time      = pcm037_timer_init,
        .init_machine = pcm037_init,
        .init_late = pcm037_init_late,
        .restart        = mxc_restart,
index 4aa0d07..e805ac2 100644 (file)
@@ -346,17 +346,13 @@ static void __init pcm038_timer_init(void)
        mx27_clocks_init(26000000);
 }
 
-static struct sys_timer pcm038_timer = {
-       .init = pcm038_timer_init,
-};
-
 MACHINE_START(PCM038, "phyCORE-i.MX27")
        .atag_offset = 0x100,
        .map_io = mx27_map_io,
        .init_early = imx27_init_early,
        .init_irq = mx27_init_irq,
        .handle_irq = imx27_handle_irq,
-       .timer = &pcm038_timer,
+       .init_time      = pcm038_timer_init,
        .init_machine = pcm038_init,
        .restart        = mxc_restart,
 MACHINE_END
index 9244544..8ed533f 100644 (file)
@@ -394,10 +394,6 @@ static void __init pcm043_timer_init(void)
        mx35_clocks_init();
 }
 
-static struct sys_timer pcm043_timer = {
-       .init   = pcm043_timer_init,
-};
-
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
        /* Maintainer: Pengutronix */
        .atag_offset = 0x100,
@@ -405,7 +401,7 @@ MACHINE_START(PCM043, "Phytec Phycore pcm043")
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
        .handle_irq = imx35_handle_irq,
-       .timer = &pcm043_timer,
+       .init_time = pcm043_timer_init,
        .init_machine = pcm043_init,
        .restart        = mxc_restart,
 MACHINE_END
index 96d9a91..22af27e 100644 (file)
@@ -260,10 +260,6 @@ static void __init qong_timer_init(void)
        mx31_clocks_init(26000000);
 }
 
-static struct sys_timer qong_timer = {
-       .init   = qong_timer_init,
-};
-
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
        /* Maintainer: DENX Software Engineering GmbH */
        .atag_offset = 0x100,
@@ -271,7 +267,7 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
        .init_early = imx31_init_early,
        .init_irq = mx31_init_irq,
        .handle_irq = imx31_handle_irq,
-       .timer = &qong_timer,
+       .init_time      = qong_timer_init,
        .init_machine = qong_init,
        .restart        = mxc_restart,
 MACHINE_END
index fc97040..b0fa10d 100644 (file)
@@ -131,10 +131,6 @@ static void __init scb9328_timer_init(void)
        mx1_clocks_init(32000);
 }
 
-static struct sys_timer scb9328_timer = {
-       .init   = scb9328_timer_init,
-};
-
 MACHINE_START(SCB9328, "Synertronixx scb9328")
        /* Sascha Hauer */
        .atag_offset = 100,
@@ -142,7 +138,7 @@ MACHINE_START(SCB9328, "Synertronixx scb9328")
        .init_early = imx1_init_early,
        .init_irq = mx1_init_irq,
        .handle_irq = imx1_handle_irq,
-       .timer = &scb9328_timer,
+       .init_time      = scb9328_timer_init,
        .init_machine = scb9328_init,
        .restart        = mxc_restart,
 MACHINE_END
index 3aecf91..0910761 100644 (file)
@@ -305,17 +305,13 @@ static void __init vpr200_timer_init(void)
        mx35_clocks_init();
 }
 
-static struct sys_timer vpr200_timer = {
-       .init   = vpr200_timer_init,
-};
-
 MACHINE_START(VPR200, "VPR200")
        /* Maintainer: Creative Product Design */
        .map_io = mx35_map_io,
        .init_early = imx35_init_early,
        .init_irq = mx35_init_irq,
        .handle_irq = imx35_handle_irq,
-       .timer = &vpr200_timer,
+       .init_time = vpr200_timer_init,
        .init_machine = vpr200_board_init,
        .restart        = mxc_restart,
 MACHINE_END
index f017302..62769df 100644 (file)
@@ -256,7 +256,6 @@ static struct irqaction mxc_timer_irq = {
 static struct clock_event_device clockevent_mxc = {
        .name           = "mxc_timer1",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .set_mode       = mxc_set_mode,
        .set_next_event = mx1_2_set_next_event,
        .rating         = 200,
@@ -264,21 +263,13 @@ static struct clock_event_device clockevent_mxc = {
 
 static int __init mxc_clockevent_init(struct clk *timer_clk)
 {
-       unsigned int c = clk_get_rate(timer_clk);
-
        if (timer_is_v2())
                clockevent_mxc.set_next_event = v2_set_next_event;
 
-       clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
-                                       clockevent_mxc.shift);
-       clockevent_mxc.max_delta_ns =
-                       clockevent_delta2ns(0xfffffffe, &clockevent_mxc);
-       clockevent_mxc.min_delta_ns =
-                       clockevent_delta2ns(0xff, &clockevent_mxc);
-
        clockevent_mxc.cpumask = cpumask_of(0);
-
-       clockevents_register_device(&clockevent_mxc);
+       clockevents_config_and_register(&clockevent_mxc,
+                                       clk_get_rate(timer_clk),
+                                       0xff, 0xfffffffe);
 
        return 0;
 }
index 11e2a41..78f1b38 100644 (file)
@@ -425,7 +425,7 @@ void __init ap_init_early(void)
 
 #ifdef CONFIG_OF
 
-static void __init ap_init_timer_of(void)
+static void __init ap_of_timer_init(void)
 {
        struct device_node *node;
        const char *path;
@@ -464,10 +464,6 @@ static void __init ap_init_timer_of(void)
        integrator_clockevent_init(rate, base, irq);
 }
 
-static struct sys_timer ap_of_timer = {
-       .init           = ap_init_timer_of,
-};
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
@@ -586,7 +582,7 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
        .init_early     = ap_init_early,
        .init_irq       = ap_init_irq_of,
        .handle_irq     = fpga_handle_irq,
-       .timer          = &ap_of_timer,
+       .init_time      = ap_of_timer_init,
        .init_machine   = ap_init_of,
        .restart        = integrator_restart,
        .dt_compat      = ap_dt_board_compat,
@@ -638,7 +634,7 @@ static struct platform_device cfi_flash_device = {
        .resource       = &cfi_flash_resource,
 };
 
-static void __init ap_init_timer(void)
+static void __init ap_timer_init(void)
 {
        struct clk *clk;
        unsigned long rate;
@@ -657,10 +653,6 @@ static void __init ap_init_timer(void)
                                IRQ_TIMERINT1);
 }
 
-static struct sys_timer ap_timer = {
-       .init           = ap_init_timer,
-};
-
 #define INTEGRATOR_SC_VALID_INT        0x003fffff
 
 static void __init ap_init_irq(void)
@@ -716,7 +708,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
        .init_early     = ap_init_early,
        .init_irq       = ap_init_irq,
        .handle_irq     = fpga_handle_irq,
-       .timer          = &ap_timer,
+       .init_time      = ap_timer_init,
        .init_machine   = ap_init,
        .restart        = integrator_restart,
 MACHINE_END
index 7322838..4cef9a0 100644 (file)
@@ -251,7 +251,7 @@ static void __init intcp_init_early(void)
 
 #ifdef CONFIG_OF
 
-static void __init intcp_timer_init_of(void)
+static void __init cp_of_timer_init(void)
 {
        struct device_node *node;
        const char *path;
@@ -283,10 +283,6 @@ static void __init intcp_timer_init_of(void)
        sp804_clockevents_init(base, irq, node->name);
 }
 
-static struct sys_timer cp_of_timer = {
-       .init           = intcp_timer_init_of,
-};
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
@@ -390,7 +386,7 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq_of,
        .handle_irq     = fpga_handle_irq,
-       .timer          = &cp_of_timer,
+       .init_time      = cp_of_timer_init,
        .init_machine   = intcp_init_of,
        .restart        = integrator_restart,
        .dt_compat      = intcp_dt_board_compat,
@@ -512,7 +508,7 @@ static void __init intcp_init_irq(void)
 #define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
 #define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
 
-static void __init intcp_timer_init(void)
+static void __init cp_timer_init(void)
 {
        writel(0, TIMER0_VA_BASE + TIMER_CTRL);
        writel(0, TIMER1_VA_BASE + TIMER_CTRL);
@@ -522,10 +518,6 @@ static void __init intcp_timer_init(void)
        sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
 }
 
-static struct sys_timer cp_timer = {
-       .init           = intcp_timer_init,
-};
-
 #define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
 #define INTEGRATOR_CP_AACI_IRQS        { IRQ_CP_AACIINT }
 
@@ -565,7 +557,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq,
        .handle_irq     = fpga_handle_irq,
-       .timer          = &cp_timer,
+       .init_time      = cp_timer_init,
        .init_machine   = intcp_init,
        .restart        = integrator_restart,
 MACHINE_END
index e3f3e7d..02a8228 100644 (file)
@@ -84,17 +84,13 @@ static void __init iq81340mc_timer_init(void)
        iop_init_time(bus_freq);
 }
 
-static struct sys_timer iq81340mc_timer = {
-       .init       = iq81340mc_timer_init,
-};
-
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
        .atag_offset    = 0x100,
        .init_early     = iop13xx_init_early,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
-       .timer          = &iq81340mc_timer,
+       .init_time      = iq81340mc_timer_init,
        .init_machine   = iq81340mc_init,
        .restart        = iop13xx_restart,
 MACHINE_END
index e947441..1b80f10 100644 (file)
@@ -86,17 +86,13 @@ static void __init iq81340sc_timer_init(void)
        iop_init_time(bus_freq);
 }
 
-static struct sys_timer iq81340sc_timer = {
-       .init       = iq81340sc_timer_init,
-};
-
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
        /* Maintainer: Dan Williams <dan.j.williams@intel.com> */
        .atag_offset    = 0x100,
        .init_early     = iop13xx_init_early,
        .map_io         = iop13xx_map_io,
        .init_irq       = iop13xx_init_irq,
-       .timer          = &iq81340sc_timer,
+       .init_time      = iq81340sc_timer_init,
        .init_machine   = iq81340sc_init,
        .restart        = iop13xx_restart,
 MACHINE_END
index 9f369f0..31fbb6c 100644 (file)
@@ -40,10 +40,6 @@ static void __init em7210_timer_init(void)
        iop_init_time(200000000);
 }
 
-static struct sys_timer em7210_timer = {
-       .init           = em7210_timer_init,
-};
-
 /*
  * EM7210 RTC
  */
@@ -205,7 +201,7 @@ MACHINE_START(EM7210, "Lanner EM7210")
        .atag_offset    = 0x100,
        .map_io         = em7210_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &em7210_timer,
+       .init_time      = em7210_timer_init,
        .init_machine   = em7210_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index 02e20c3..ac30470 100644 (file)
@@ -44,10 +44,6 @@ static void __init glantank_timer_init(void)
        iop_init_time(200000000);
 }
 
-static struct sys_timer glantank_timer = {
-       .init           = glantank_timer_init,
-};
-
 
 /*
  * GLAN Tank I/O.
@@ -209,7 +205,7 @@ MACHINE_START(GLANTANK, "GLAN Tank")
        .atag_offset    = 0x100,
        .map_io         = glantank_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &glantank_timer,
+       .init_time      = glantank_timer_init,
        .init_machine   = glantank_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index ddd1c7e..f2cd296 100644 (file)
@@ -75,10 +75,6 @@ static void __init iq31244_timer_init(void)
        }
 }
 
-static struct sys_timer iq31244_timer = {
-       .init           = iq31244_timer_init,
-};
-
 
 /*
  * IQ31244 I/O.
@@ -314,7 +310,7 @@ MACHINE_START(IQ31244, "Intel IQ31244")
        .atag_offset    = 0x100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &iq31244_timer,
+       .init_time      = iq31244_timer_init,
        .init_machine   = iq31244_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
@@ -329,7 +325,7 @@ MACHINE_START(EP80219, "Intel EP80219")
        .atag_offset    = 0x100,
        .map_io         = iq31244_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &iq31244_timer,
+       .init_time      = iq31244_timer_init,
        .init_machine   = iq31244_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index bf155e6..015435d 100644 (file)
@@ -43,10 +43,6 @@ static void __init iq80321_timer_init(void)
        iop_init_time(200000000);
 }
 
-static struct sys_timer iq80321_timer = {
-       .init           = iq80321_timer_init,
-};
-
 
 /*
  * IQ80321 I/O.
@@ -188,7 +184,7 @@ MACHINE_START(IQ80321, "Intel IQ80321")
        .atag_offset    = 0x100,
        .map_io         = iq80321_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &iq80321_timer,
+       .init_time      = iq80321_timer_init,
        .init_machine   = iq80321_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index 5a7ae91..ea0984a 100644 (file)
@@ -50,10 +50,6 @@ static void __init n2100_timer_init(void)
        iop_init_time(198000000);
 }
 
-static struct sys_timer n2100_timer = {
-       .init           = n2100_timer_init,
-};
-
 
 /*
  * N2100 I/O.
@@ -337,7 +333,7 @@ MACHINE_START(N2100, "Thecus N2100")
        .atag_offset    = 0x100,
        .map_io         = n2100_map_io,
        .init_irq       = iop32x_init_irq,
-       .timer          = &n2100_timer,
+       .init_time      = n2100_timer_init,
        .init_machine   = n2100_init_machine,
        .restart        = n2100_restart,
 MACHINE_END
index e74a7de..c43304a 100644 (file)
@@ -45,10 +45,6 @@ static void __init iq80331_timer_init(void)
                iop_init_time(266000000);
 }
 
-static struct sys_timer iq80331_timer = {
-       .init           = iq80331_timer_init,
-};
-
 
 /*
  * IQ80331 PCI.
@@ -143,7 +139,7 @@ MACHINE_START(IQ80331, "Intel IQ80331")
        .atag_offset    = 0x100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
-       .timer          = &iq80331_timer,
+       .init_time      = iq80331_timer_init,
        .init_machine   = iq80331_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index e2f5bee..8192987 100644 (file)
@@ -45,10 +45,6 @@ static void __init iq80332_timer_init(void)
                iop_init_time(266000000);
 }
 
-static struct sys_timer iq80332_timer = {
-       .init           = iq80332_timer_init,
-};
-
 
 /*
  * IQ80332 PCI.
@@ -143,7 +139,7 @@ MACHINE_START(IQ80332, "Intel IQ80332")
        .atag_offset    = 0x100,
        .map_io         = iop3xx_map_io,
        .init_irq       = iop33x_init_irq,
-       .timer          = &iq80332_timer,
+       .init_time      = iq80332_timer_init,
        .init_machine   = iq80332_init_machine,
        .restart        = iop3xx_restart,
 MACHINE_END
index 90e42e9..6beec15 100644 (file)
@@ -167,7 +167,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = avila_init,
 #if defined(CONFIG_PCI)
@@ -187,7 +187,7 @@ MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = avila_init,
 #if defined(CONFIG_PCI)
index 8c0c0e2..1dbeb7c 100644 (file)
@@ -307,10 +307,6 @@ void __init ixp4xx_timer_init(void)
        ixp4xx_clockevent_init();
 }
 
-struct sys_timer ixp4xx_timer = {
-       .init           = ixp4xx_timer_init,
-};
-
 static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
 
 void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
@@ -523,22 +519,15 @@ static struct clock_event_device clockevent_ixp4xx = {
        .name           = "ixp4xx timer1",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .rating         = 200,
-       .shift          = 24,
        .set_mode       = ixp4xx_set_mode,
        .set_next_event = ixp4xx_set_next_event,
 };
 
 static void __init ixp4xx_clockevent_init(void)
 {
-       clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC,
-                                       clockevent_ixp4xx.shift);
-       clockevent_ixp4xx.max_delta_ns =
-               clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
-       clockevent_ixp4xx.min_delta_ns =
-               clockevent_delta2ns(0xf, &clockevent_ixp4xx);
        clockevent_ixp4xx.cpumask = cpumask_of(0);
-
-       clockevents_register_device(&clockevent_ixp4xx);
+       clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
+                                       0xf, 0xfffffffe);
 }
 
 void ixp4xx_restart(char mode, const char *cmd)
index 1b83110..820cae8 100644 (file)
@@ -112,7 +112,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = coyote_init,
 #if defined(CONFIG_PCI)
@@ -132,7 +132,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = coyote_init,
        .restart        = ixp4xx_restart,
index 97a0af8..5d413f8 100644 (file)
@@ -226,10 +226,6 @@ static void __init dsmg600_timer_init(void)
     ixp4xx_timer_init();
 }
 
-static struct sys_timer dsmg600_timer = {
-    .init   = dsmg600_timer_init,
-};
-
 static void __init dsmg600_init(void)
 {
        ixp4xx_sys_init();
@@ -282,7 +278,7 @@ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &dsmg600_timer,
+       .init_time      = dsmg600_timer_init,
        .init_machine   = dsmg600_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 9175a25..429966b 100644 (file)
@@ -272,7 +272,7 @@ MACHINE_START(FSG, "Freecom FSG-3")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = fsg_init,
 #if defined(CONFIG_PCI)
index 033c717..3d24b3f 100644 (file)
@@ -99,7 +99,7 @@ MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = gateway7001_init,
 #if defined(CONFIG_PCI)
index 53b8348..e54ff49 100644 (file)
@@ -498,7 +498,7 @@ MACHINE_START(GORAMO_MLR, "MultiLink")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = gmlr_init,
 #if defined(CONFIG_PCI)
index 18ebc6b..16a1299 100644 (file)
@@ -167,7 +167,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = gtwx5715_init,
 #if defined(CONFIG_PCI)
index 5bce94a..db5afb6 100644 (file)
@@ -89,8 +89,6 @@ struct ixp4xx_pata_data {
        void __iomem    *cs1;
 };
 
-struct sys_timer;
-
 #define IXP4XX_ETH_NPEA                0x00
 #define IXP4XX_ETH_NPEB                0x10
 #define IXP4XX_ETH_NPEC                0x20
@@ -125,7 +123,6 @@ extern void ixp4xx_init_early(void);
 extern void ixp4xx_init_irq(void);
 extern void ixp4xx_sys_init(void);
 extern void ixp4xx_timer_init(void);
-extern struct sys_timer ixp4xx_timer;
 extern void ixp4xx_restart(char, const char *);
 extern void ixp4xx_pci_preinit(void);
 struct pci_sys_data;
index 108a9d3..22d688b 100644 (file)
@@ -252,7 +252,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -268,7 +268,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -283,7 +283,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -298,7 +298,7 @@ MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = ixdp425_init,
 #if defined(CONFIG_PCI)
index 33cb095..ed667ce 100644 (file)
@@ -317,7 +317,7 @@ MACHINE_START(NAS100D, "Iomega NAS 100d")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .init_machine   = nas100d_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index e2903fa..7e55236 100644 (file)
@@ -232,10 +232,6 @@ static void __init nslu2_timer_init(void)
     ixp4xx_timer_init();
 }
 
-static struct sys_timer nslu2_timer = {
-    .init   = nslu2_timer_init,
-};
-
 static void __init nslu2_init(void)
 {
        uint8_t __iomem *f;
@@ -303,7 +299,7 @@ MACHINE_START(NSLU2, "Linksys NSLU2")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &nslu2_timer,
+       .init_time      = nslu2_timer_init,
        .init_machine   = nslu2_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
index 158ddb7..46a89f5 100644 (file)
@@ -245,7 +245,7 @@ MACHINE_START(DEVIXP, "Omicron DEVIXP")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .init_machine   = omixp_init,
        .restart        = ixp4xx_restart,
 MACHINE_END
@@ -257,7 +257,7 @@ MACHINE_START(MICCPT, "Omicron MICCPT")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .init_machine   = omixp_init,
 #if defined(CONFIG_PCI)
        .dma_zone_size  = SZ_64M,
@@ -272,7 +272,7 @@ MACHINE_START(MIC256, "Omicron MIC256")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .init_machine   = omixp_init,
        .restart        = ixp4xx_restart,
 MACHINE_END
index 2798f43..d42730a 100644 (file)
@@ -239,7 +239,7 @@ MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = vulcan_init,
 #if defined(CONFIG_PCI)
index a785175..8f9ea2f 100644 (file)
@@ -100,7 +100,7 @@ MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
        .map_io         = ixp4xx_map_io,
        .init_early     = ixp4xx_init_early,
        .init_irq       = ixp4xx_init_irq,
-       .timer          = &ixp4xx_timer,
+       .init_time      = ixp4xx_timer_init,
        .atag_offset    = 0x100,
        .init_machine   = wg302v2_init,
 #if defined(CONFIG_PCI)
index de4fd2b..d4af5c1 100644 (file)
@@ -183,7 +183,7 @@ DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = orion_dt_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .init_machine   = kirkwood_dt_init,
        .restart        = kirkwood_restart,
        .dt_compat      = kirkwood_dt_board_compat,
index bac21a5..b5ad4df 100644 (file)
@@ -530,7 +530,7 @@ static int __init kirkwood_find_tclk(void)
        return 166666667;
 }
 
-static void __init kirkwood_timer_init(void)
+void __init kirkwood_timer_init(void)
 {
        kirkwood_tclk = kirkwood_find_tclk();
 
@@ -538,10 +538,6 @@ static void __init kirkwood_timer_init(void)
                        IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
-struct sys_timer kirkwood_timer = {
-       .init = kirkwood_timer_init,
-};
-
 /*****************************************************************************
  * Audio
  ****************************************************************************/
index 5ffa57f..283ab61 100644 (file)
@@ -156,7 +156,7 @@ void kirkwood_xor1_init(void);
 void kirkwood_crypto_init(void);
 
 extern int kirkwood_tclk;
-extern struct sys_timer kirkwood_timer;
+extern void kirkwood_timer_init(void);
 
 #define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
 
index 2c1a453..4534180 100644 (file)
@@ -226,6 +226,6 @@ MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index c49b177..5a369fe 100644 (file)
@@ -103,6 +103,6 @@ MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 791a98f..77f98f2 100644 (file)
@@ -107,6 +107,6 @@ MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 7cb55f9..1c6e736 100644 (file)
@@ -126,6 +126,6 @@ MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 6d8364a..ba384b9 100644 (file)
@@ -167,6 +167,6 @@ MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 728e86d..3b70661 100644 (file)
@@ -263,7 +263,7 @@ MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -275,7 +275,7 @@ MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -287,7 +287,7 @@ MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
index a3b0914..913d032 100644 (file)
@@ -404,7 +404,7 @@ MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -416,7 +416,7 @@ MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
index 7e81e9b..8ddd69f 100644 (file)
@@ -221,7 +221,7 @@ MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -234,7 +234,7 @@ MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -247,7 +247,7 @@ MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
index 19072c8..e4fd312 100644 (file)
@@ -84,6 +84,6 @@ MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 9717101..c7d93b4 100644 (file)
@@ -120,6 +120,6 @@ MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 8a17594..55b68fa 100644 (file)
@@ -143,7 +143,7 @@ MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
@@ -155,7 +155,7 @@ MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
 #endif
index f2daf71..8736f8c 100644 (file)
@@ -211,6 +211,6 @@ MACHINE_START(T5325, "HP t5325 Thin Client")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index 73e2b6c..283abff 100644 (file)
@@ -137,6 +137,6 @@ MACHINE_START(TS219, "QNAP TS-119/TS-219")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index e4c6127..81d5858 100644 (file)
@@ -181,6 +181,6 @@ MACHINE_START(TS41X, "QNAP TS-41x")
        .map_io         = kirkwood_map_io,
        .init_early     = kirkwood_init_early,
        .init_irq       = kirkwood_init_irq,
-       .timer          = &kirkwood_timer,
+       .init_time      = kirkwood_timer_init,
        .restart        = kirkwood_restart,
 MACHINE_END
index b0c306c..456d638 100644 (file)
@@ -227,6 +227,6 @@ MACHINE_START(ACS5K, "Brivo Systems LLC ACS-5000 Master board")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = acs5k_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
index e0d36ce..d37c218 100644 (file)
@@ -125,6 +125,6 @@ MACHINE_START(DSM320, "D-Link DSM-320 Wireless Media Player")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = dsm320_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
index a827072..3acbdfd 100644 (file)
@@ -57,6 +57,6 @@ MACHINE_START(KS8695, "KS8695 Centaur Development Board")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = micrel_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
index 1623ba4..002bc61 100644 (file)
@@ -145,7 +145,7 @@ MACHINE_START(CM4002, "OpenGear/CM4002")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = og_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -157,7 +157,7 @@ MACHINE_START(CM4008, "OpenGear/CM4008")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = og_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -169,7 +169,7 @@ MACHINE_START(CM41XX, "OpenGear/CM41xx")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = og_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -181,7 +181,7 @@ MACHINE_START(IM4004, "OpenGear/IM4004")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = og_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -193,7 +193,7 @@ MACHINE_START(IM42XX, "OpenGear/IM42xx")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = og_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
index f35b98b..fdf2352 100644 (file)
@@ -91,7 +91,7 @@ MACHINE_START(LITE300, "SecureComputing/SG300")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = sg_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -103,7 +103,7 @@ MACHINE_START(SG310, "McAfee/SG310")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = sg_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -115,7 +115,7 @@ MACHINE_START(SE4200, "SecureComputing/SE4200")
        .map_io         = ks8695_map_io,
        .init_irq       = ks8695_init_irq,
        .init_machine   = sg_init,
-       .timer          = &ks8695_timer,
+       .init_time      = ks8695_timer_init,
        .restart        = ks8695_restart,
 MACHINE_END
 #endif
index f8bdb11..6e97ce4 100644 (file)
@@ -13,4 +13,4 @@
 extern __init void ks8695_map_io(void);
 extern __init void ks8695_init_irq(void);
 extern void ks8695_restart(char, const char *);
-extern struct sys_timer ks8695_timer;
+extern void ks8695_timer_init(void);
index 46c84bc..c272a38 100644 (file)
@@ -146,7 +146,7 @@ static void ks8695_timer_setup(void)
                                        0xFFFFFFFFU);
 }
 
-static void __init ks8695_timer_init (void)
+void __init ks8695_timer_init(void)
 {
        ks8695_timer_setup();
 
@@ -154,10 +154,6 @@ static void __init ks8695_timer_init (void)
        setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq);
 }
 
-struct sys_timer ks8695_timer = {
-       .init           = ks8695_timer_init,
-};
-
 void ks8695_restart(char mode, const char *cmd)
 {
        unsigned int reg;
index afeac3b..e0b2606 100644 (file)
@@ -25,7 +25,7 @@
 /*
  * Other arch specific structures and functions
  */
-extern struct sys_timer lpc32xx_timer;
+extern void lpc32xx_timer_init(void);
 extern void __init lpc32xx_init_irq(void);
 extern void __init lpc32xx_map_io(void);
 extern void __init lpc32xx_serial_init(void);
index e8ff4c3..c1cd5a9 100644 (file)
@@ -263,7 +263,7 @@ DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)")
        .atag_offset    = 0x100,
        .map_io         = lpc32xx_map_io,
        .init_irq       = lpc32xx_init_irq,
-       .timer          = &lpc32xx_timer,
+       .init_time      = lpc32xx_timer_init,
        .init_machine   = lpc3250_machine_init,
        .dt_compat      = lpc32xx_dt_compat,
        .restart        = lpc23xx_restart,
index c40667c..20eab63 100644 (file)
@@ -70,7 +70,6 @@ static void lpc32xx_clkevt_mode(enum clock_event_mode mode,
 static struct clock_event_device lpc32xx_clkevt = {
        .name           = "lpc32xx_clkevt",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 300,
        .set_next_event = lpc32xx_clkevt_next_event,
        .set_mode       = lpc32xx_clkevt_mode,
@@ -100,7 +99,7 @@ static struct irqaction lpc32xx_timer_irq = {
  * clocks need to be enabled here manually and then tagged as used in
  * the clock driver initialization
  */
-static void __init lpc32xx_timer_init(void)
+void __init lpc32xx_timer_init(void)
 {
        u32 clkrate, pllreg;
 
@@ -141,14 +140,8 @@ static void __init lpc32xx_timer_init(void)
        setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
 
        /* Setup the clockevent structure. */
-       lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC,
-               lpc32xx_clkevt.shift);
-       lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1,
-               &lpc32xx_clkevt);
-       lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1,
-               &lpc32xx_clkevt) + 1;
        lpc32xx_clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&lpc32xx_clkevt);
+       clockevents_config_and_register(&lpc32xx_clkevt, clkrate, 1, -1);
 
        /* Use timer1 as clock source. */
        __raw_writel(LPC32XX_TIMER_CNTR_TCR_RESET,
@@ -161,8 +154,3 @@ static void __init lpc32xx_timer_init(void)
        clocksource_mmio_init(LPC32XX_TIMER_TC(LPC32XX_TIMER1_BASE),
                "lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up);
 }
-
-struct sys_timer lpc32xx_timer = {
-       .init           = &lpc32xx_timer_init,
-};
-
index e5dba9c..9f64d56 100644 (file)
@@ -262,7 +262,7 @@ MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
-       .timer          = &pxa168_timer,
+       .init_time      = pxa168_timer_init,
        .init_machine   = common_init,
        .restart        = pxa168_restart,
 MACHINE_END
@@ -271,7 +271,7 @@ MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
-       .timer          = &pxa168_timer,
+       .init_time      = pxa168_timer_init,
        .init_machine   = common_init,
        .restart        = pxa168_restart,
 MACHINE_END
index 603542a..1f94957 100644 (file)
@@ -45,7 +45,7 @@ MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
-       .timer          = &pxa168_timer,
+       .init_time      = pxa168_timer_init,
        .init_machine   = avengers_lite_init,
        .restart        = pxa168_restart,
 MACHINE_END
index 5cb769c..2358011 100644 (file)
@@ -218,7 +218,7 @@ MACHINE_START(BROWNSTONE, "Brownstone Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = BROWNSTONE_NR_IRQS,
        .init_irq       = mmp2_init_irq,
-       .timer          = &mmp2_timer,
+       .init_time      = mmp2_timer_init,
        .init_machine   = brownstone_init,
        .restart        = mmp_restart,
 MACHINE_END
index bd45327..0bdc50b 100644 (file)
@@ -1,7 +1,5 @@
 #define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
 
-struct sys_timer;
-
 extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
index 8059cc0..754c352 100644 (file)
@@ -121,7 +121,7 @@ MACHINE_START(FLINT, "Flint Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = FLINT_NR_IRQS,
        .init_irq       = mmp2_init_irq,
-       .timer          = &mmp2_timer,
+       .init_time      = mmp2_timer_init,
        .init_machine   = flint_init,
        .restart        = mmp_restart,
 MACHINE_END
index 5c3d61e..d1e2d59 100644 (file)
@@ -194,7 +194,7 @@ MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
-       .timer          = &pxa168_timer,
+       .init_time      = pxa168_timer_init,
        .init_machine   = gplugd_init,
        .restart        = pxa168_restart,
 MACHINE_END
index c4ca4d1..0764f4e 100644 (file)
@@ -3,9 +3,7 @@
 
 #include <linux/platform_data/pxa_sdhci.h>
 
-struct sys_timer;
-
-extern struct sys_timer mmp2_timer;
+extern void mmp2_timer_init(void);
 extern void __init mmp2_init_icu(void);
 extern void __init mmp2_init_irq(void);
 extern void mmp2_clear_pmic_int(void);
index 37632d9..7ed1df2 100644 (file)
@@ -1,9 +1,7 @@
 #ifndef __ASM_MACH_PXA168_H
 #define __ASM_MACH_PXA168_H
 
-struct sys_timer;
-
-extern struct sys_timer pxa168_timer;
+extern void pxa168_timer_init(void);
 extern void __init pxa168_init_irq(void);
 extern void pxa168_restart(char, const char *);
 extern void pxa168_clear_keypad_wakeup(void);
index 3b58a3b..eff31ab 100644 (file)
@@ -1,9 +1,7 @@
 #ifndef __ASM_MACH_PXA910_H
 #define __ASM_MACH_PXA910_H
 
-struct sys_timer;
-
-extern struct sys_timer pxa910_timer;
+extern void pxa910_timer_init(void);
 extern void __init pxa910_init_irq(void);
 
 #include <linux/i2c.h>
index ff73249..66634fd 100644 (file)
@@ -174,7 +174,7 @@ MACHINE_START(MARVELL_JASPER, "Jasper Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = JASPER_NR_IRQS,
        .init_irq       = mmp2_init_irq,
-       .timer          = &mmp2_timer,
+       .init_time      = mmp2_timer_init,
        .init_machine   = jasper_init,
        .restart        = mmp_restart,
 MACHINE_END
index 033cc31..d063efa 100644 (file)
 extern void __init mmp_dt_irq_init(void);
 extern void __init mmp_dt_init_timer(void);
 
-static struct sys_timer mmp_dt_timer = {
-       .init   = mmp_dt_init_timer,
-};
-
 static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
        OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
@@ -69,7 +65,7 @@ static const char *mmp_dt_board_compat[] __initdata = {
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
        .map_io         = mmp_map_io,
        .init_irq       = mmp_dt_irq_init,
-       .timer          = &mmp_dt_timer,
+       .init_time      = mmp_dt_init_timer,
        .init_machine   = pxa168_dt_init,
        .dt_compat      = mmp_dt_board_compat,
 MACHINE_END
@@ -77,7 +73,7 @@ MACHINE_END
 DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
        .map_io         = mmp_map_io,
        .init_irq       = mmp_dt_irq_init,
-       .timer          = &mmp_dt_timer,
+       .init_time      = mmp_dt_init_timer,
        .init_machine   = pxa910_dt_init,
        .dt_compat      = mmp_dt_board_compat,
 MACHINE_END
index 535a5ed..fad431a 100644 (file)
 extern void __init mmp_dt_irq_init(void);
 extern void __init mmp_dt_init_timer(void);
 
-static struct sys_timer mmp_dt_timer = {
-       .init   = mmp_dt_init_timer,
-};
-
 static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
        OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
@@ -54,7 +50,7 @@ static const char *mmp2_dt_board_compat[] __initdata = {
 DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
        .map_io         = mmp_map_io,
        .init_irq       = mmp_dt_irq_init,
-       .timer          = &mmp_dt_timer,
+       .init_time      = mmp_dt_init_timer,
        .init_machine   = mmp2_dt_init,
        .dt_compat      = mmp2_dt_board_compat,
 MACHINE_END
index 3a3768c..d94d114 100644 (file)
@@ -114,7 +114,7 @@ postcore_initcall(mmp2_init);
 
 #define APBC_TIMERS    APBC_REG(0x024)
 
-static void __init mmp2_timer_init(void)
+void __init mmp2_timer_init(void)
 {
        unsigned long clk_rst;
 
@@ -130,10 +130,6 @@ static void __init mmp2_timer_init(void)
        timer_init(IRQ_MMP2_TIMER1);
 }
 
-struct sys_timer mmp2_timer = {
-       .init   = mmp2_timer_init,
-};
-
 /* on-chip devices */
 MMP2_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4030000, 0x30, 4, 5);
 MMP2_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4017000, 0x30, 20, 21);
index b7f074f..9bc7b86 100644 (file)
@@ -67,7 +67,7 @@ postcore_initcall(pxa168_init);
 #define TIMER_CLK_RST  (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
 #define APBC_TIMERS    APBC_REG(0x34)
 
-static void __init pxa168_timer_init(void)
+void __init pxa168_timer_init(void)
 {
        /* this is early, we have to initialize the CCU registers by
         * ourselves instead of using clk_* API. Clock rate is defined
@@ -81,10 +81,6 @@ static void __init pxa168_timer_init(void)
        timer_init(IRQ_PXA168_TIMER1);
 }
 
-struct sys_timer pxa168_timer = {
-       .init   = pxa168_timer_init,
-};
-
 void pxa168_clear_keypad_wakeup(void)
 {
        uint32_t val;
index 8b1e16f..c6a89f1 100644 (file)
@@ -101,7 +101,7 @@ postcore_initcall(pxa910_init);
 #define TIMER_CLK_RST  (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
 #define APBC_TIMERS    APBC_REG(0x34)
 
-static void __init pxa910_timer_init(void)
+void __init pxa910_timer_init(void)
 {
        /* reset and configure */
        __raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
@@ -110,10 +110,6 @@ static void __init pxa910_timer_init(void)
        timer_init(IRQ_PXA910_AP1_TIMER1);
 }
 
-struct sys_timer pxa910_timer = {
-       .init   = pxa910_timer_init,
-};
-
 /* on-chip devices */
 
 /* NOTE: there are totally 3 UARTs on PXA910:
index b28f908..4c127d2 100644 (file)
@@ -103,7 +103,7 @@ MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa910_init_irq,
-       .timer          = &pxa910_timer,
+       .init_time      = pxa910_timer_init,
        .init_machine   = tavorevb_init,
        .restart        = mmp_restart,
 MACHINE_END
index dd30ea7..8609967 100644 (file)
@@ -86,7 +86,7 @@ MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
-       .timer          = &pxa168_timer,
+       .init_time      = pxa168_timer_init,
        .init_machine   = teton_bga_init,
        .restart        = pxa168_restart,
 MACHINE_END
index 936447c..86a18b3 100644 (file)
@@ -141,7 +141,6 @@ static void timer_set_mode(enum clock_event_mode mode,
 static struct clock_event_device ckevt = {
        .name           = "clockevent",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 200,
        .set_next_event = timer_set_next_event,
        .set_mode       = timer_set_mode,
@@ -198,15 +197,13 @@ void __init timer_init(int irq)
 
        setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE);
 
-       ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift);
-       ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt);
-       ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt);
        ckevt.cpumask = cpumask_of(0);
 
        setup_irq(irq, &timer_irq);
 
        clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
-       clockevents_register_device(&ckevt);
+       clockevents_config_and_register(&ckevt, CLOCK_TICK_RATE,
+                                       MIN_DELTA, MAX_DELTA);
 }
 
 #ifdef CONFIG_OF
index ce55fd8..6e47490 100644 (file)
@@ -218,7 +218,7 @@ MACHINE_START(TTC_DKB, "PXA910-based TTC_DKB Development Platform")
        .map_io         = mmp_map_io,
        .nr_irqs        = TTCDKB_NR_IRQS,
        .init_irq       = pxa910_init_irq,
-       .timer          = &pxa910_timer,
+       .init_time      = pxa910_timer_init,
        .init_machine   = ttc_dkb_init,
        .restart        = mmp_restart,
 MACHINE_END
index c111cec..7dcfc53 100644 (file)
@@ -47,6 +47,6 @@ DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
        .init_irq = irqchip_init,
        .init_machine = msm8x60_dt_init,
        .init_late = msm8x60_init_late,
-       .timer = &msm_dt_timer,
+       .init_time      = msm_dt_timer_init,
        .dt_compat = msm8x60_fluid_match,
 MACHINE_END
index fad0e50..7301936 100644 (file)
@@ -32,7 +32,7 @@ DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
        .smp = smp_ops(msm_smp_ops),
        .map_io = msm_map_msm8960_io,
        .init_irq = irqchip_init,
-       .timer = &msm_dt_timer,
+       .init_time      = msm_dt_timer_init,
        .init_machine = msm_dt_init,
        .dt_compat = msm8960_dt_match,
 MACHINE_END
index 6ce542e..84d720a 100644 (file)
@@ -106,5 +106,5 @@ MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
        .init_irq       = halibut_init_irq,
        .init_machine   = halibut_init,
        .init_late      = halibut_init_late,
-       .timer          = &msm7x01_timer,
+       .init_time      = msm7x01_timer_init,
 MACHINE_END
index df00bc0..30c3496 100644 (file)
@@ -75,7 +75,7 @@ static void __init mahimahi_init_late(void)
        smd_debugfs_init();
 }
 
-extern struct sys_timer msm_timer;
+void msm_timer_init(void);
 
 MACHINE_START(MAHIMAHI, "mahimahi")
        .atag_offset    = 0x100,
@@ -84,5 +84,5 @@ MACHINE_START(MAHIMAHI, "mahimahi")
        .init_irq       = msm_init_irq,
        .init_machine   = mahimahi_init,
        .init_late      = mahimahi_init_late,
-       .timer          = &msm_timer,
+       .init_time      = msm_timer_init,
 MACHINE_END
index effa6f4..7bc3f82 100644 (file)
@@ -131,7 +131,7 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
        .init_late = msm7x30_init_late,
-       .timer = &msm7x30_timer,
+       .init_time      = msm7x30_timer_init,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
@@ -142,7 +142,7 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
        .init_late = msm7x30_init_late,
-       .timer = &msm7x30_timer,
+       .init_time      = msm7x30_timer_init,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
@@ -153,5 +153,5 @@ MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
        .init_irq = msm7x30_init_irq,
        .init_machine = msm7x30_init,
        .init_late = msm7x30_init_late,
-       .timer = &msm7x30_timer,
+       .init_time      = msm7x30_timer_init,
 MACHINE_END
index 2448fcf..686e794 100644 (file)
@@ -200,7 +200,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
        .init_irq = qsd8x50_init_irq,
        .init_machine = qsd8x50_init,
        .init_late = qsd8x50_init_late,
-       .timer = &qsd8x50_timer,
+       .init_time      = qsd8x50_timer_init,
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
@@ -209,5 +209,5 @@ MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
        .init_irq = qsd8x50_init_irq,
        .init_machine = qsd8x50_init,
        .init_late = qsd8x50_init_late,
-       .timer = &qsd8x50_timer,
+       .init_time      = qsd8x50_timer_init,
 MACHINE_END
index b7b0fc7..7073011 100644 (file)
@@ -53,7 +53,7 @@ static struct platform_device *devices[] __initdata = {
        &msm_device_uart3,
 };
 
-extern struct sys_timer msm_timer;
+void msm_timer_init(void);
 
 static void __init sapphire_init_irq(void)
 {
@@ -113,5 +113,5 @@ MACHINE_START(SAPPHIRE, "sapphire")
        .init_irq       = sapphire_init_irq,
        .init_machine   = sapphire_init,
        .init_late      = sapphire_init_late,
-       .timer          = &msm_timer,
+       .init_time      = msm_timer_init,
 MACHINE_END
index 4ba0800..919bfa3 100644 (file)
@@ -110,5 +110,5 @@ MACHINE_START(TROUT, "HTC Dream")
        .init_irq       = trout_init_irq,
        .init_machine   = trout_init,
        .init_late      = trout_init_late,
-       .timer          = &msm7x01_timer,
+       .init_time      = msm7x01_timer_init,
 MACHINE_END
index 633a715..ce8215a 100644 (file)
 #ifndef __MACH_COMMON_H
 #define __MACH_COMMON_H
 
-extern struct sys_timer msm7x01_timer;
-extern struct sys_timer msm7x30_timer;
-extern struct sys_timer msm_dt_timer;
-extern struct sys_timer qsd8x50_timer;
+extern void msm7x01_timer_init(void);
+extern void msm7x30_timer_init(void);
+extern void msm_dt_timer_init(void);
+extern void qsd8x50_timer_init(void);
 
 extern void msm_map_common_io(void);
 extern void msm_map_msm7x30_io(void);
index 4330285..2969027 100644 (file)
@@ -143,13 +143,9 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
        evt->rating = msm_clockevent.rating;
        evt->set_mode = msm_timer_set_mode;
        evt->set_next_event = msm_timer_set_next_event;
-       evt->shift = msm_clockevent.shift;
-       evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift);
-       evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt);
-       evt->min_delta_ns = clockevent_delta2ns(4, evt);
 
        *__this_cpu_ptr(msm_evt.percpu_evt) = evt;
-       clockevents_register_device(evt);
+       clockevents_config_and_register(evt, GPT_HZ, 4, 0xf0000000);
        enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
        return 0;
 }
@@ -228,7 +224,7 @@ static const struct of_device_id msm_gpt_match[] __initconst = {
        { },
 };
 
-static void __init msm_dt_timer_init(void)
+void __init msm_dt_timer_init(void)
 {
        struct device_node *np;
        u32 freq;
@@ -295,10 +291,6 @@ static void __init msm_dt_timer_init(void)
 
        msm_timer_init(freq, 32, irq, !!percpu_offset);
 }
-
-struct sys_timer msm_dt_timer = {
-       .init = msm_dt_timer_init
-};
 #endif
 
 static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
@@ -316,7 +308,7 @@ static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
        return 0;
 }
 
-static void __init msm7x01_timer_init(void)
+void __init msm7x01_timer_init(void)
 {
        struct clocksource *cs = &msm_clocksource;
 
@@ -329,28 +321,16 @@ static void __init msm7x01_timer_init(void)
                        false);
 }
 
-struct sys_timer msm7x01_timer = {
-       .init = msm7x01_timer_init
-};
-
-static void __init msm7x30_timer_init(void)
+void __init msm7x30_timer_init(void)
 {
        if (msm_timer_map(0xc0100004, 0xc0100024))
                return;
        msm_timer_init(24576000 / 4, 32, 1, false);
 }
 
-struct sys_timer msm7x30_timer = {
-       .init = msm7x30_timer_init
-};
-
-static void __init qsd8x50_timer_init(void)
+void __init qsd8x50_timer_init(void)
 {
        if (msm_timer_map(0xAC100000, 0xAC100010))
                return;
        msm_timer_init(19200000 / 4, 32, 7, false);
 }
-
-struct sys_timer qsd8x50_timer = {
-       .init = qsd8x50_timer_init
-};
index ee74ec9..1f2ef98 100644 (file)
@@ -150,6 +150,6 @@ MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
        .init_irq       = mv78xx0_init_irq,
-       .timer          = &mv78xx0_timer,
+       .init_time      = mv78xx0_timer_init,
        .restart        = mv78xx0_restart,
 MACHINE_END
index d0cb485..0efa144 100644 (file)
@@ -336,16 +336,12 @@ void __init mv78xx0_init_early(void)
        orion_time_set_base(TIMER_VIRT_BASE);
 }
 
-static void __init_refok mv78xx0_timer_init(void)
+void __init_refok mv78xx0_timer_init(void)
 {
        orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
                        IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
-struct sys_timer mv78xx0_timer = {
-       .init = mv78xx0_timer_init,
-};
-
 
 /*****************************************************************************
  * General
index 507c767..5e9485b 100644 (file)
@@ -47,7 +47,7 @@ void mv78xx0_uart3_init(void);
 void mv78xx0_i2c_init(void);
 void mv78xx0_restart(char, const char *);
 
-extern struct sys_timer mv78xx0_timer;
+extern void mv78xx0_timer_init(void);
 
 
 #endif
index 4d6d48b..4e0f22b 100644 (file)
@@ -98,6 +98,6 @@ MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
        .init_irq       = mv78xx0_init_irq,
-       .timer          = &mv78xx0_timer,
+       .init_time      = mv78xx0_timer_init,
        .restart        = mv78xx0_restart,
 MACHINE_END
index 9a88270..d2d06f3 100644 (file)
@@ -83,6 +83,6 @@ MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
        .map_io         = mv78xx0_map_io,
        .init_early     = mv78xx0_init_early,
        .init_irq       = mv78xx0_init_irq,
-       .timer          = &mv78xx0_timer,
+       .init_time      = mv78xx0_timer_init,
        .restart        = mv78xx0_restart,
 MACHINE_END
index 7434b5e..a5ea616 100644 (file)
@@ -56,10 +56,6 @@ void __init armada_370_xp_init_early(void)
        init_dma_coherent_pool_size(SZ_1M);
 }
 
-struct sys_timer armada_370_xp_timer = {
-       .init           = armada_370_xp_timer_and_clk_init,
-};
-
 static void __init armada_370_xp_dt_init(void)
 {
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -78,7 +74,7 @@ DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)")
        .init_early     = armada_370_xp_init_early,
        .init_irq       = armada_370_xp_init_irq,
        .handle_irq     = armada_370_xp_handle_irq,
-       .timer          = &armada_370_xp_timer,
+       .init_time      = armada_370_xp_timer_and_clk_init,
        .restart        = mvebu_restart,
        .dt_compat      = armada_370_xp_dt_compat,
 MACHINE_END
index c66129b..5fad7ce 100644 (file)
@@ -163,19 +163,11 @@ static void __init imx23_timer_init(void)
        mx23_clocks_init();
 }
 
-static struct sys_timer imx23_timer = {
-       .init = imx23_timer_init,
-};
-
 static void __init imx28_timer_init(void)
 {
        mx28_clocks_init();
 }
 
-static struct sys_timer imx28_timer = {
-       .init = imx28_timer_init,
-};
-
 enum mac_oui {
        OUI_FSL,
        OUI_DENX,
@@ -446,7 +438,7 @@ DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)")
        .map_io         = mx23_map_io,
        .init_irq       = icoll_init_irq,
        .handle_irq     = icoll_handle_irq,
-       .timer          = &imx23_timer,
+       .init_time      = imx23_timer_init,
        .init_machine   = mxs_machine_init,
        .dt_compat      = imx23_dt_compat,
        .restart        = mxs_restart,
@@ -456,7 +448,7 @@ DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
        .map_io         = mx28_map_io,
        .init_irq       = icoll_init_irq,
        .handle_irq     = icoll_handle_irq,
-       .timer          = &imx28_timer,
+       .init_time      = imx28_timer_init,
        .init_machine   = mxs_machine_init,
        .dt_compat      = imx28_dt_compat,
        .restart        = mxs_restart,
index 856f4c7..27451b1 100644 (file)
@@ -195,7 +195,6 @@ static void mxs_set_mode(enum clock_event_mode mode,
 static struct clock_event_device mxs_clockevent_device = {
        .name           = "mxs_timrot",
        .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .set_mode       = mxs_set_mode,
        .set_next_event = timrotv2_set_next_event,
        .rating         = 200,
@@ -203,25 +202,12 @@ static struct clock_event_device mxs_clockevent_device = {
 
 static int __init mxs_clockevent_init(struct clk *timer_clk)
 {
-       unsigned int c = clk_get_rate(timer_clk);
-
-       mxs_clockevent_device.mult =
-               div_sc(c, NSEC_PER_SEC, mxs_clockevent_device.shift);
-       mxs_clockevent_device.cpumask = cpumask_of(0);
-       if (timrot_is_v1()) {
+       if (timrot_is_v1())
                mxs_clockevent_device.set_next_event = timrotv1_set_next_event;
-               mxs_clockevent_device.max_delta_ns =
-                       clockevent_delta2ns(0xfffe, &mxs_clockevent_device);
-               mxs_clockevent_device.min_delta_ns =
-                       clockevent_delta2ns(0xf, &mxs_clockevent_device);
-       } else {
-               mxs_clockevent_device.max_delta_ns =
-                       clockevent_delta2ns(0xfffffffe, &mxs_clockevent_device);
-               mxs_clockevent_device.min_delta_ns =
-                       clockevent_delta2ns(0xf, &mxs_clockevent_device);
-       }
-
-       clockevents_register_device(&mxs_clockevent_device);
+       mxs_clockevent_device.cpumask = cpumask_of(0);
+       clockevents_config_and_register(&mxs_clockevent_device,
+                                       clk_get_rate(timer_clk), 0xf,
+                                       timrot_is_v1() ? 0xfffe : 0xfffffffe);
 
        return 0;
 }
index 9b91511..768b26b 100644 (file)
@@ -21,5 +21,4 @@ extern void __init netx_map_io(void);
 extern void __init netx_init_irq(void);
 extern void netx_restart(char, const char *);
 
-struct sys_timer;
-extern struct sys_timer netx_timer;
+extern void netx_timer_init(void);
index 04d5e5e..9b558eb 100644 (file)
@@ -203,7 +203,7 @@ MACHINE_START(NXDB500, "Hilscher nxdb500")
        .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
-       .timer          = &netx_timer,
+       .init_time      = netx_timer_init,
        .init_machine   = nxdb500_init,
        .restart        = netx_restart,
 MACHINE_END
index cf15bdd..a5e86cd 100644 (file)
@@ -96,7 +96,7 @@ MACHINE_START(NXDKN, "Hilscher nxdkn")
        .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
-       .timer          = &netx_timer,
+       .init_time      = netx_timer_init,
        .init_machine   = nxdkn_init,
        .restart        = netx_restart,
 MACHINE_END
index 069bd26..ad17885 100644 (file)
@@ -180,7 +180,7 @@ MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
        .atag_offset    = 0x100,
        .map_io         = netx_map_io,
        .init_irq       = netx_init_irq,
-       .timer          = &netx_timer,
+       .init_time      = netx_timer_init,
        .init_machine   = nxeb500hmi_init,
        .restart        = netx_restart,
 MACHINE_END
index e24c141..6df42e6 100644 (file)
@@ -76,7 +76,6 @@ static int netx_set_next_event(unsigned long evt,
 
 static struct clock_event_device netx_clockevent = {
        .name = "netx-timer" __stringify(TIMER_CLOCKEVENT),
-       .shift = 32,
        .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_next_event = netx_set_next_event,
        .set_mode = netx_set_mode,
@@ -107,7 +106,7 @@ static struct irqaction netx_timer_irq = {
 /*
  * Set up timer interrupt
  */
-static void __init netx_timer_init(void)
+void __init netx_timer_init(void)
 {
        /* disable timer initially */
        writel(0, NETX_GPIO_COUNTER_CTRL(0));
@@ -140,18 +139,9 @@ static void __init netx_timer_init(void)
        clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
                "netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up);
 
-       netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
-                       netx_clockevent.shift);
-       netx_clockevent.max_delta_ns =
-               clockevent_delta2ns(0xfffffffe, &netx_clockevent);
        /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine.
         * Adding some safety ... */
-       netx_clockevent.min_delta_ns =
-               clockevent_delta2ns(0xa00, &netx_clockevent);
        netx_clockevent.cpumask = cpumask_of(0);
-       clockevents_register_device(&netx_clockevent);
+       clockevents_config_and_register(&netx_clockevent, CLOCK_TICK_RATE,
+                                       0xa00, 0xfffffffe);
 }
-
-struct sys_timer netx_timer = {
-       .init           = netx_timer_init,
-};
index 5748df0..aaed48d 100644 (file)
@@ -266,10 +266,6 @@ static void __init nomadik_timer_init(void)
        nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0);
 }
 
-static struct sys_timer nomadik_timer = {
-       .init   = nomadik_timer_init,
-};
-
 static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = {
        {
                I2C_BOARD_INFO("stw4811", 0x2d),
@@ -351,7 +347,7 @@ MACHINE_START(NOMADIK, "NHK8815")
        .atag_offset    = 0x100,
        .map_io         = cpu8815_map_io,
        .init_irq       = cpu8815_init_irq,
-       .timer          = &nomadik_timer,
+       .init_time      = nomadik_timer_init,
        .init_machine   = nhk8815_platform_init,
        .restart        = cpu8815_restart,
 MACHINE_END
index 2e98a3a..2aab761 100644 (file)
@@ -628,6 +628,6 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
        .init_irq       = omap1_init_irq,
        .init_machine   = ams_delta_init,
        .init_late      = ams_delta_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 560a7dc..702d580 100644 (file)
@@ -364,6 +364,6 @@ MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_fsample_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 608e7d2..e1d9171 100644 (file)
@@ -84,6 +84,6 @@ MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_generic_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 2274bd6..0dac3d2 100644 (file)
@@ -461,6 +461,6 @@ MACHINE_START(OMAP_H2, "TI-H2")
        .init_irq       = omap1_init_irq,
        .init_machine   = h2_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 1051935..816ecd1 100644 (file)
@@ -454,6 +454,6 @@ MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
        .init_irq       = omap1_init_irq,
        .init_machine   = h3_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 356f816..35a2379 100644 (file)
@@ -603,6 +603,6 @@ MACHINE_START(HERALD, "HTC Herald")
        .init_irq       = omap1_init_irq,
        .init_machine   = htcherald_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index f8033fa..bd5f02e 100644 (file)
@@ -458,6 +458,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
        .init_irq       = omap1_init_irq,
        .init_machine   = innovator_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 24d2f2d..4695ca7 100644 (file)
@@ -242,6 +242,6 @@ MACHINE_START(NOKIA770, "Nokia 770")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_nokia770_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 872ea47..a7ce692 100644 (file)
@@ -609,6 +609,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
        .init_irq       = omap1_init_irq,
        .init_machine   = osk_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index c33dceb..845a1a7 100644 (file)
@@ -268,6 +268,6 @@ MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_palmte_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 2948b0e..65a4a3e 100644 (file)
@@ -314,6 +314,6 @@ MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_palmtt_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 7a05895..01c9700 100644 (file)
@@ -330,6 +330,6 @@ MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_palmz71_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 27f8d12..8b2f712 100644 (file)
@@ -326,6 +326,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_perseus2_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index 20ed52a..9732a98 100644 (file)
@@ -407,6 +407,6 @@ MACHINE_START(SX1, "OMAP310 based Siemens SX1")
        .init_irq       = omap1_init_irq,
        .init_machine   = omap_sx1_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = omap1_restart,
 MACHINE_END
index abf705f..6c116e1 100644 (file)
@@ -289,6 +289,6 @@ MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
        .init_irq       = omap1_init_irq,
        .init_machine   = voiceblue_init,
        .init_late      = omap1_init_late,
-       .timer          = &omap1_timer,
+       .init_time      = omap1_timer_init,
        .restart        = voiceblue_restart,
 MACHINE_END
index b53e085..fb18831 100644 (file)
@@ -75,7 +75,7 @@ extern void __init omap_check_revision(void);
 extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
                               unsigned int ctrl);
 
-extern struct sys_timer omap1_timer;
+extern void omap1_timer_init(void);
 #ifdef CONFIG_OMAP_32K_TIMER
 extern int omap_32k_timer_init(void);
 #else
index 4d4816f..726ec23 100644 (file)
@@ -145,7 +145,6 @@ static void omap_mpu_set_mode(enum clock_event_mode mode,
 static struct clock_event_device clockevent_mpu_timer1 = {
        .name           = "mpu_timer1",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .set_next_event = omap_mpu_set_next_event,
        .set_mode       = omap_mpu_set_mode,
 };
@@ -170,15 +169,9 @@ static __init void omap_init_mpu_timer(unsigned long rate)
        setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
        omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
 
-       clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC,
-                                           clockevent_mpu_timer1.shift);
-       clockevent_mpu_timer1.max_delta_ns =
-               clockevent_delta2ns(-1, &clockevent_mpu_timer1);
-       clockevent_mpu_timer1.min_delta_ns =
-               clockevent_delta2ns(1, &clockevent_mpu_timer1);
-
        clockevent_mpu_timer1.cpumask = cpumask_of(0);
-       clockevents_register_device(&clockevent_mpu_timer1);
+       clockevents_config_and_register(&clockevent_mpu_timer1, rate,
+                                       1, -1);
 }
 
 
@@ -236,12 +229,8 @@ static inline void omap_mpu_timer_init(void)
  * Timer initialization
  * ---------------------------------------------------------------------------
  */
-static void __init omap1_timer_init(void)
+void __init omap1_timer_init(void)
 {
        if (omap_32k_timer_init() != 0)
                omap_mpu_timer_init();
 }
-
-struct sys_timer omap1_timer = {
-       .init           = omap1_timer_init,
-};
index 41152fa..0b74246 100644 (file)
@@ -140,7 +140,6 @@ static void omap_32k_timer_set_mode(enum clock_event_mode mode,
 static struct clock_event_device clockevent_32k_timer = {
        .name           = "32k-timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .set_next_event = omap_32k_timer_set_next_event,
        .set_mode       = omap_32k_timer_set_mode,
 };
@@ -165,16 +164,9 @@ static __init void omap_init_32k_timer(void)
 {
        setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
 
-       clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
-                                          NSEC_PER_SEC,
-                                          clockevent_32k_timer.shift);
-       clockevent_32k_timer.max_delta_ns =
-               clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
-       clockevent_32k_timer.min_delta_ns =
-               clockevent_delta2ns(1, &clockevent_32k_timer);
-
        clockevent_32k_timer.cpumask = cpumask_of(0);
-       clockevents_register_device(&clockevent_32k_timer);
+       clockevents_config_and_register(&clockevent_32k_timer,
+                                       OMAP_32K_TICKS_PER_SEC, 1, 0xfffffffe);
 }
 
 /*
index 4815ea6..5f41396 100644 (file)
@@ -284,6 +284,6 @@ MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_2430sdp_init,
        .init_late      = omap2430_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
index bb73afc..8e2513f 100644 (file)
@@ -597,6 +597,6 @@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_3430sdp_init,
        .init_late      = omap3430_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 050aaa7..3384627 100644 (file)
@@ -211,6 +211,6 @@ MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_sdp_init,
        .init_late      = omap3630_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index cb43253..f8eeef4 100644 (file)
@@ -724,6 +724,6 @@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
        .init_irq       = gic_init_irq,
        .init_machine   = omap_4430sdp_init,
        .init_late      = omap4430_init_late,
-       .timer          = &omap4_timer,
+       .init_time      = omap4_local_timer_init,
        .restart        = omap44xx_restart,
 MACHINE_END
index 51b96a1..07f0be2 100644 (file)
@@ -92,6 +92,6 @@ MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = am3517_crane_init,
        .init_late      = am35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index f81a303..6f5b2a0 100644 (file)
@@ -393,6 +393,6 @@ MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = am3517_evm_init,
        .init_late      = am35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 5d0a61f..3a6ca74 100644 (file)
@@ -337,6 +337,6 @@ MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_apollon_init,
        .init_late      = omap2420_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
index b3102c2..68647c3 100644 (file)
@@ -751,7 +751,7 @@ MACHINE_START(CM_T35, "Compulab CM-T35")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = cm_t35_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
 
@@ -764,6 +764,6 @@ MACHINE_START(CM_T3730, "Compulab CM-T3730")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = cm_t3730_init,
        .init_late     = omap3630_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index ebbc2ad..6a9529a 100644 (file)
@@ -297,6 +297,6 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = cm_t3517_init,
        .init_late      = am35xx_init_late,
-       .timer          = &omap3_gp_timer,
+       .init_time      = omap3_gp_gptimer_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 12865af..0b1d8f7 100644 (file)
@@ -643,6 +643,6 @@ MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = devkit8000_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_secure_timer,
+       .init_time      = omap3_secure_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 73be868..2590463 100644 (file)
@@ -64,7 +64,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .dt_compat      = omap242x_boards_compat,
        .restart        = omap2xxx_restart,
 MACHINE_END
@@ -83,7 +83,7 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .dt_compat      = omap243x_boards_compat,
        .restart        = omap2xxx_restart,
 MACHINE_END
@@ -102,7 +102,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .dt_compat      = omap3_boards_compat,
        .restart        = omap3xxx_restart,
 MACHINE_END
@@ -119,7 +119,7 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .timer          = &omap3_secure_timer,
+       .init_time      = omap3_secure_sync32k_timer_init,
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
 MACHINE_END
@@ -138,7 +138,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .timer          = &omap3_am33xx_timer,
+       .init_time      = omap3_am33xx_gptimer_timer_init,
        .dt_compat      = am33xx_boards_compat,
 MACHINE_END
 #endif
@@ -157,7 +157,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .init_irq       = omap_gic_of_init,
        .init_machine   = omap_generic_init,
        .init_late      = omap4430_init_late,
-       .timer          = &omap4_timer,
+       .init_time      = omap4_local_timer_init,
        .dt_compat      = omap4_boards_compat,
        .restart        = omap44xx_restart,
 MACHINE_END
@@ -176,7 +176,7 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
        .init_early     = omap5_init_early,
        .init_irq       = omap_gic_of_init,
        .init_machine   = omap_generic_init,
-       .timer          = &omap5_timer,
+       .init_time      = omap5_realtime_timer_init,
        .dt_compat      = omap5_boards_compat,
        .restart        = omap44xx_restart,
 MACHINE_END
index 3be1311..812c829 100644 (file)
@@ -342,6 +342,6 @@ MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_h4_init,
        .init_late      = omap2420_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
index 0f24cb8..5b44764 100644 (file)
@@ -655,7 +655,7 @@ MACHINE_START(IGEP0020, "IGEP v2 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = igep_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
 
@@ -668,6 +668,6 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = igep_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 0869f4f..ff440c0 100644 (file)
@@ -435,6 +435,6 @@ MACHINE_START(OMAP_LDP, "OMAP LDP board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_ldp_init,
        .init_late      = omap3430_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 0abb30f..f6eeb87 100644 (file)
@@ -731,7 +731,7 @@ MACHINE_START(NOKIA_N800, "Nokia N800")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
 
@@ -744,7 +744,7 @@ MACHINE_START(NOKIA_N810, "Nokia N810")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
 
@@ -757,6 +757,6 @@ MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
-       .timer          = &omap2_timer,
+       .init_time      = omap2_sync32k_timer_init,
        .restart        = omap2xxx_restart,
 MACHINE_END
index 22c483d..b81b458 100644 (file)
@@ -544,6 +544,6 @@ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3_beagle_init,
        .init_late      = omap3_init_late,
-       .timer          = &omap3_secure_timer,
+       .init_time      = omap3_secure_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 3985f35..f2f636b 100644 (file)
@@ -757,6 +757,6 @@ MACHINE_START(OMAP3EVM, "OMAP3 EVM")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3_evm_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 2a065ba..0fba43a 100644 (file)
@@ -231,7 +231,7 @@ MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3logic_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
 
@@ -244,6 +244,6 @@ MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3logic_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index a53a668..12e1816 100644 (file)
@@ -618,6 +618,6 @@ MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3pandora_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 53a6cbc..13ee405 100644 (file)
@@ -427,6 +427,6 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
        .handle_irq             = omap3_intc_handle_irq,
        .init_machine           = omap3_stalker_init,
        .init_late              = omap35xx_init_late,
-       .timer                  = &omap3_secure_timer,
+       .init_time              = omap3_secure_sync32k_timer_init,
        .restart                = omap3xxx_restart,
 MACHINE_END
index 263cb9c..36c455c 100644 (file)
@@ -386,6 +386,6 @@ MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3_touchbook_init,
        .init_late      = omap3430_init_late,
-       .timer          = &omap3_secure_timer,
+       .init_time      = omap3_secure_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index e9270b3..b623179 100644 (file)
@@ -461,6 +461,6 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
        .init_irq       = gic_init_irq,
        .init_machine   = omap4_panda_init,
        .init_late      = omap4430_init_late,
-       .timer          = &omap4_timer,
+       .init_time      = omap4_local_timer_init,
        .restart        = omap44xx_restart,
 MACHINE_END
index c8fde3e..233a37d 100644 (file)
@@ -551,6 +551,6 @@ MACHINE_START(OVERO, "Gumstix Overo")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = overo_init,
        .init_late      = omap35xx_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 0c777b7..386a2dd 100644 (file)
@@ -147,7 +147,7 @@ MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = rm680_init,
        .init_late      = omap3630_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
 
@@ -160,6 +160,6 @@ MACHINE_START(NOKIA_RM696, "Nokia RM-696 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = rm680_init,
        .init_late      = omap3630_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index d0374ea..f7c4616 100644 (file)
@@ -123,6 +123,6 @@ MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = rx51_init,
        .init_late      = omap3430_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 1a3e056..6273c28 100644 (file)
@@ -43,7 +43,7 @@ MACHINE_START(TI8168EVM, "ti8168evm")
        .map_io         = ti81xx_map_io,
        .init_early     = ti81xx_init_early,
        .init_irq       = ti81xx_init_irq,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .init_machine   = ti81xx_evm_init,
        .init_late      = ti81xx_init_late,
        .restart        = omap44xx_restart,
@@ -55,7 +55,7 @@ MACHINE_START(TI8148EVM, "ti8148evm")
        .map_io         = ti81xx_map_io,
        .init_early     = ti81xx_init_early,
        .init_irq       = ti81xx_init_irq,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .init_machine   = ti81xx_evm_init,
        .init_late      = ti81xx_init_late,
        .restart        = omap44xx_restart,
index d7fa31e..d257cf1 100644 (file)
@@ -137,7 +137,7 @@ MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_zoom_init,
        .init_late      = omap3430_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
 
@@ -150,6 +150,6 @@ MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_zoom_init,
        .init_late      = omap3630_init_late,
-       .timer          = &omap3_timer,
+       .init_time      = omap3_sync32k_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 948bcaa..b435027 100644 (file)
@@ -79,13 +79,13 @@ static inline int omap_mux_late_init(void)
 
 extern void omap2_init_common_infrastructure(void);
 
-extern struct sys_timer omap2_timer;
-extern struct sys_timer omap3_timer;
-extern struct sys_timer omap3_secure_timer;
-extern struct sys_timer omap3_gp_timer;
-extern struct sys_timer omap3_am33xx_timer;
-extern struct sys_timer omap4_timer;
-extern struct sys_timer omap5_timer;
+extern void omap2_sync32k_timer_init(void);
+extern void omap3_sync32k_timer_init(void);
+extern void omap3_secure_sync32k_timer_init(void);
+extern void omap3_gp_gptimer_timer_init(void);
+extern void omap3_am33xx_gptimer_timer_init(void);
+extern void omap4_local_timer_init(void);
+extern void omap5_realtime_timer_init(void);
 
 void omap2420_init_early(void);
 void omap2430_init_early(void);
index b8ad6e6..d860747 100644 (file)
@@ -131,7 +131,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 static struct clock_event_device clockevent_gpt = {
        .name           = "gp_timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 300,
        .set_next_event = omap2_gp_timer_set_next_event,
        .set_mode       = omap2_gp_timer_set_mode,
@@ -336,17 +335,11 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 
        __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
 
-       clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
-                                    clockevent_gpt.shift);
-       clockevent_gpt.max_delta_ns =
-               clockevent_delta2ns(0xffffffff, &clockevent_gpt);
-       clockevent_gpt.min_delta_ns =
-               clockevent_delta2ns(3, &clockevent_gpt);
-               /* Timer internal resynch latency. */
-
        clockevent_gpt.cpumask = cpu_possible_mask;
        clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
-       clockevents_register_device(&clockevent_gpt);
+       clockevents_config_and_register(&clockevent_gpt, clkev.rate,
+                                       3, /* Timer internal resynch latency */
+                                       0xffffffff);
 
        pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
                gptimer_id, clkev.rate);
@@ -552,7 +545,7 @@ static inline void __init realtime_counter_init(void)
 
 #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,  \
                               clksrc_nr, clksrc_src)                   \
-static void __init omap##name##_gptimer_timer_init(void)               \
+void __init omap##name##_gptimer_timer_init(void)                      \
 {                                                                      \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
@@ -561,7 +554,7 @@ static void __init omap##name##_gptimer_timer_init(void)            \
 
 #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
                                clksrc_nr, clksrc_src)                  \
-static void __init omap##name##_sync32k_timer_init(void)               \
+void __init omap##name##_sync32k_timer_init(void)              \
 {                                                                      \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
@@ -572,33 +565,23 @@ static void __init omap##name##_sync32k_timer_init(void)          \
                omap2_sync32k_clocksource_init();                       \
 }
 
-#define OMAP_SYS_TIMER(name, clksrc)                                   \
-struct sys_timer omap##name##_timer = {                                        \
-       .init   = omap##name##_##clksrc##_timer_init,                   \
-};
-
 #ifdef CONFIG_ARCH_OMAP2
 OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP2_MPU_SOURCE);
-OMAP_SYS_TIMER(2, sync32k);
 #endif /* CONFIG_ARCH_OMAP2 */
 
 #ifdef CONFIG_ARCH_OMAP3
 OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3, sync32k);
 OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure",
                        2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3_secure, sync32k);
 OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
                       2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3_gp, gptimer);
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #ifdef CONFIG_SOC_AM33XX
 OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon",
                       2, OMAP4_MPU_SOURCE);
-OMAP_SYS_TIMER(3_am33xx, gptimer);
 #endif /* CONFIG_SOC_AM33XX */
 
 #ifdef CONFIG_ARCH_OMAP4
@@ -606,7 +589,7 @@ OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP4_MPU_SOURCE);
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
-static void __init omap4_local_timer_init(void)
+void __init omap4_local_timer_init(void)
 {
        omap4_sync32k_timer_init();
        /* Local timers are not supprted on OMAP4430 ES1.0 */
@@ -624,18 +607,17 @@ static void __init omap4_local_timer_init(void)
        }
 }
 #else /* CONFIG_LOCAL_TIMERS */
-static void __init omap4_local_timer_init(void)
+void __init omap4_local_timer_init(void)
 {
        omap4_sync32k_timer_init();
 }
 #endif /* CONFIG_LOCAL_TIMERS */
-OMAP_SYS_TIMER(4, local);
 #endif /* CONFIG_ARCH_OMAP4 */
 
 #ifdef CONFIG_SOC_OMAP5
 OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP4_MPU_SOURCE);
-static void __init omap5_realtime_timer_init(void)
+void __init omap5_realtime_timer_init(void)
 {
        int err;
 
@@ -646,7 +628,6 @@ static void __init omap5_realtime_timer_init(void)
        if (err)
                pr_err("%s: arch_timer_register failed %d\n", __func__, err);
 }
-OMAP_SYS_TIMER(5, realtime);
 #endif /* CONFIG_SOC_OMAP5 */
 
 /**
index 32e5c21..35a8014 100644 (file)
@@ -72,7 +72,7 @@ DT_MACHINE_START(ORION5X_DT, "Marvell Orion5x (Flattened Device Tree)")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion_dt_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .init_machine   = orion5x_dt_init,
        .restart        = orion5x_restart,
        .dt_compat      = orion5x_dt_compat,
index 550f923..d068f14 100644 (file)
@@ -217,7 +217,7 @@ int __init orion5x_find_tclk(void)
        return 166666667;
 }
 
-static void __init orion5x_timer_init(void)
+void __init orion5x_timer_init(void)
 {
        orion5x_tclk = orion5x_find_tclk();
 
@@ -225,10 +225,6 @@ static void __init orion5x_timer_init(void)
                        IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
-struct sys_timer orion5x_timer = {
-       .init = orion5x_timer_init,
-};
-
 
 /*****************************************************************************
  * General
index 7db5cdd..e603457 100644 (file)
@@ -15,7 +15,7 @@ void orion5x_init(void);
 void orion5x_id(u32 *dev, u32 *rev, char **dev_name);
 void clk_init(void);
 extern int orion5x_tclk;
-extern struct sys_timer orion5x_timer;
+extern void orion5x_timer_init(void);
 
 /*
  * Enumerations and functions for Orion windows mapping. Used by Orion core
index e3629c0..57d0af7 100644 (file)
@@ -342,7 +342,7 @@ MACHINE_START(D2NET, "LaCie d2 Network")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
@@ -355,7 +355,7 @@ MACHINE_START(BIGDISK, "LaCie Big Disk Network")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 41fe2b1..7666564 100644 (file)
@@ -362,6 +362,6 @@ MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .restart        = orion5x_restart,
 MACHINE_END
index e533588..6eb1732 100644 (file)
@@ -714,7 +714,7 @@ MACHINE_START(DNS323, "D-Link DNS-323")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index f1ae10a..b984035 100644 (file)
@@ -383,7 +383,7 @@ MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
@@ -397,7 +397,7 @@ MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 0c9e413..044da5b 100644 (file)
@@ -322,7 +322,7 @@ MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index c1b5d8a..d49f934 100644 (file)
@@ -269,7 +269,7 @@ MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 949eaa8..8e3965c 100644 (file)
@@ -271,7 +271,7 @@ MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 1c16d04..0ec94a1 100644 (file)
@@ -265,7 +265,7 @@ MACHINE_START(MSS2, "Maxtor Shared Storage II")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index c87fde4..18143f2 100644 (file)
@@ -233,7 +233,7 @@ MACHINE_START(MV2120, "HP Media Vault mv2120")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 3506f16..282e503 100644 (file)
@@ -425,7 +425,7 @@ MACHINE_START(NET2BIG, "LaCie 2Big Network")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 9b1c953..d6e72f6 100644 (file)
@@ -171,7 +171,7 @@ MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 51ba2b8..c8b7913 100644 (file)
@@ -183,7 +183,7 @@ MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 0a56b94..f9e1567 100644 (file)
@@ -281,6 +281,6 @@ MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .restart        = orion5x_restart,
 MACHINE_END
index ed50910..78a1e6a 100644 (file)
@@ -123,7 +123,7 @@ MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 90e571d..acc0877 100644 (file)
@@ -361,7 +361,7 @@ MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index b184f68..9c17f0c 100644 (file)
@@ -326,7 +326,7 @@ MACHINE_START(TS209, "QNAP TS-109/TS-209")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index a5c2e64..8cc5ab6 100644 (file)
@@ -315,7 +315,7 @@ MACHINE_START(TS409, "QNAP TS-409")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index b0727dc..e960855 100644 (file)
@@ -619,6 +619,6 @@ MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
        .map_io         = ts78xx_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .restart        = orion5x_restart,
 MACHINE_END
index 754c12b..66552ca 100644 (file)
@@ -176,7 +176,7 @@ MACHINE_START(WNR854T, "Netgear WNR854T")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 45c2125..2c5408e 100644 (file)
@@ -264,7 +264,7 @@ MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
        .map_io         = orion5x_map_io,
        .init_early     = orion5x_init_early,
        .init_irq       = orion5x_init_irq,
-       .timer          = &orion5x_timer,
+       .init_time      = orion5x_timer_init,
        .fixup          = tag_fixup_mem32,
        .restart        = orion5x_restart,
 MACHINE_END
index 35ee214..70b441a 100644 (file)
@@ -88,7 +88,7 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
        .map_io         = picoxcell_map_io,
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = irqchip_init,
-       .timer          = &dw_apb_timer,
+       .init_time      = dw_apb_timer_init,
        .init_machine   = picoxcell_init_machine,
        .dt_compat      = picoxcell_dt_match,
        .restart        = picoxcell_wdt_restart,
index a65cb02..481b42a 100644 (file)
@@ -12,6 +12,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer dw_apb_timer;
+extern void dw_apb_timer_init(void);
 
 #endif /* __PICOXCELL_COMMON_H__ */
index f25a541..ed3570e 100644 (file)
@@ -40,7 +40,7 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
        /* Maintainer: Barry Song <baohua.song@csr.com> */
        .map_io         = sirfsoc_map_lluart,
        .init_irq       = sirfsoc_of_irq_init,
-       .timer          = &sirfsoc_timer,
+       .init_time      = sirfsoc_timer_init,
        .dma_zone_size  = SZ_256M,
        .init_machine   = sirfsoc_mach_init,
        .init_late      = sirfsoc_init_late,
index 60d826f..9c75f12 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <asm/mach/time.h>
 
-extern struct sys_timer sirfsoc_timer;
+extern void sirfsoc_timer_init(void);
 
 extern void __init sirfsoc_of_irq_init(void);
 extern void __init sirfsoc_of_clk_init(void);
index d95bf25..a7a2c19 100644 (file)
@@ -175,19 +175,13 @@ static u32 notrace sirfsoc_read_sched_clock(void)
 
 static void __init sirfsoc_clockevent_init(void)
 {
-       clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
-
-       sirfsoc_clockevent.max_delta_ns =
-               clockevent_delta2ns(-2, &sirfsoc_clockevent);
-       sirfsoc_clockevent.min_delta_ns =
-               clockevent_delta2ns(2, &sirfsoc_clockevent);
-
        sirfsoc_clockevent.cpumask = cpumask_of(0);
-       clockevents_register_device(&sirfsoc_clockevent);
+       clockevents_config_and_register(&sirfsoc_clockevent, CLOCK_TICK_RATE,
+                                       2, -2);
 }
 
 /* initialize the kernel jiffy timer source */
-static void __init sirfsoc_timer_init(void)
+void __init sirfsoc_timer_init(void)
 {
        unsigned long rate;
        struct clk *clk;
@@ -226,7 +220,7 @@ static struct of_device_id timer_ids[] = {
        {},
 };
 
-static void __init sirfsoc_of_timer_map(void)
+void __init sirfsoc_of_timer_map(void)
 {
        struct device_node *np;
        const unsigned int *intspec;
@@ -245,7 +239,3 @@ static void __init sirfsoc_of_timer_map(void)
 
        of_node_put(np);
 }
-
-struct sys_timer sirfsoc_timer = {
-       .init = sirfsoc_timer_init,
-};
index 2082293..2f71b3f 100644 (file)
@@ -822,7 +822,7 @@ MACHINE_START(BALLOON3, "Balloon3")
        .nr_irqs        = BALLOON3_NR_IRQS,
        .init_irq       = balloon3_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = balloon3_init,
        .atag_offset    = 0x100,
        .restart        = pxa_restart,
index 9a8760b..c092730 100644 (file)
@@ -153,7 +153,7 @@ MACHINE_START(CAPC7117,
        .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa3xx_init_irq,
        .handle_irq = pxa3xx_handle_irq,
-       .timer = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine = capc7117_init,
        .restart        = pxa_restart,
 MACHINE_END
index a103c8f..bb99f59 100644 (file)
@@ -520,7 +520,7 @@ MACHINE_START(ARMCORE, "Compulab CM-X2XX")
        .init_irq       = cmx2xx_init_irq,
        /* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = cmx2xx_init,
 #ifdef CONFIG_PCI
        .dma_zone_size  = SZ_64M,
index cc2b23a..8091aac 100644 (file)
@@ -854,7 +854,7 @@ MACHINE_START(CM_X300, "CM-X300 module")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = cm_x300_init,
        .fixup          = cm_x300_fixup,
        .restart        = pxa_restart,
index b2f227d..5f9d930 100644 (file)
@@ -313,7 +313,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
@@ -324,7 +324,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
index a9c9c16..f1a1ac1 100644 (file)
@@ -189,7 +189,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
index 25515cd..f6cc8b0 100644 (file)
@@ -259,7 +259,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
index 7c83f52..a5b8fea 100644 (file)
@@ -733,7 +733,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = corgi_restart,
 MACHINE_END
 #endif
@@ -746,7 +746,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = corgi_restart,
 MACHINE_END
 #endif
@@ -759,7 +759,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = corgi_restart,
 MACHINE_END
 #endif
index 7039f44..fadfff8 100644 (file)
@@ -278,6 +278,6 @@ MACHINE_START(CSB726, "Cogent CSB726")
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .init_machine   = csb726_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
index 1b64114..446563a 100644 (file)
@@ -1298,7 +1298,7 @@ MACHINE_START(EM_X270, "Compulab EM-X270")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = em_x270_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -1309,7 +1309,7 @@ MACHINE_START(EXEDA, "Compulab eXeda")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = em_x270_init,
        .restart        = pxa_restart,
 MACHINE_END
index be2ee9b..8280ebc 100644 (file)
@@ -195,7 +195,7 @@ MACHINE_START(E330, "Toshiba e330")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e330_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -246,7 +246,7 @@ MACHINE_START(E350, "Toshiba e350")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e350_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -370,7 +370,7 @@ MACHINE_START(E400, "Toshiba e400")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e400_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -566,7 +566,7 @@ MACHINE_START(E740, "Toshiba e740")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e740_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -765,7 +765,7 @@ MACHINE_START(E750, "Toshiba e750")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e750_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -977,7 +977,7 @@ MACHINE_START(E800, "Toshiba e800")
        .handle_irq     = pxa25x_handle_irq,
        .fixup          = eseries_fixup,
        .init_machine   = e800_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
index dc58fa0..dca1070 100644 (file)
@@ -802,7 +802,7 @@ MACHINE_START(EZX_A780, "Motorola EZX A780")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = a780_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -869,7 +869,7 @@ MACHINE_START(EZX_E680, "Motorola EZX E680")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = e680_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -936,7 +936,7 @@ MACHINE_START(EZX_A1200, "Motorola EZX A1200")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = a1200_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -1128,7 +1128,7 @@ MACHINE_START(EZX_A910, "Motorola EZX A910")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = a910_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -1195,7 +1195,7 @@ MACHINE_START(EZX_E6, "Motorola EZX E6")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = e6_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -1236,7 +1236,7 @@ MACHINE_START(EZX_E2, "Motorola EZX E2")
        .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = e2_init,
        .restart        = pxa_restart,
 MACHINE_END
index 42d5cca..fd7ea39 100644 (file)
@@ -10,9 +10,8 @@
  */
 
 struct irq_data;
-struct sys_timer;
 
-extern struct sys_timer pxa_timer;
+extern void pxa_timer_init(void);
 
 extern void __init pxa_map_io(void);
 
index 60755a6..00b92da 100644 (file)
@@ -238,7 +238,7 @@ MACHINE_START(GUMSTIX, "Gumstix")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = gumstix_init,
        .restart        = pxa_restart,
 MACHINE_END
index e7dec58..875ec33 100644 (file)
@@ -208,7 +208,7 @@ MACHINE_START(H5400, "HP iPAQ H5000")
        .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
-       .timer = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine = h5000_init,
        .restart        = pxa_restart,
 MACHINE_END
index 2962de8..7a8d749 100644 (file)
@@ -164,6 +164,6 @@ MACHINE_START(HIMALAYA, "HTC Himalaya")
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
        .init_machine = himalaya_init,
-       .timer = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
index e2c6391..133109e 100644 (file)
@@ -900,6 +900,6 @@ MACHINE_START(H4700, "HP iPAQ HX4700")
        .init_irq     = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine = hx4700_init,
-       .timer        = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
index 1d02eab..fe31bfc 100644 (file)
@@ -196,7 +196,7 @@ MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = icontrol_init,
        .restart        = pxa_restart,
 MACHINE_END
index 64507cd..343c4e3 100644 (file)
@@ -279,7 +279,7 @@ MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = idp_init,
        .restart        = pxa_restart,
 MACHINE_END
index 402874f..e848c46 100644 (file)
@@ -443,7 +443,7 @@ MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleto
        .nr_irqs        = LITTLETON_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = littleton_init,
        .restart        = pxa_restart,
 MACHINE_END
index 1a63eaa..1255ee0 100644 (file)
@@ -503,7 +503,7 @@ MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
        .nr_irqs        = LPD270_NR_IRQS,
        .init_irq       = lpd270_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = lpd270_init,
        .restart        = pxa_restart,
 MACHINE_END
index 553056d..d8a1be6 100644 (file)
@@ -650,7 +650,7 @@ MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
        .nr_irqs        = LUBBOCK_NR_IRQS,
        .init_irq       = lubbock_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = lubbock_init,
        .restart        = pxa_restart,
 MACHINE_END
index f792240..f44532f 100644 (file)
@@ -774,6 +774,6 @@ MACHINE_START(MAGICIAN, "HTC Magician")
        .init_irq = pxa27x_init_irq,
        .handle_irq = pxa27x_handle_irq,
        .init_machine = magician_init,
-       .timer = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
index f27a61e..7a12c1b 100644 (file)
@@ -714,7 +714,7 @@ MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
        .nr_irqs        = MAINSTONE_NR_IRQS,
        .init_irq       = mainstone_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = mainstone_init,
        .restart        = pxa_restart,
 MACHINE_END
index 2831308..f8979b9 100644 (file)
@@ -762,6 +762,6 @@ MACHINE_START(MIOA701, "MIO A701")
        .init_irq       = &pxa27x_init_irq,
        .handle_irq     = &pxa27x_handle_irq,
        .init_machine   = mioa701_machine_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = mioa701_restart,
 MACHINE_END
index 152efbf..854f1f5 100644 (file)
@@ -93,7 +93,7 @@ static void __init mp900c_init(void)
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
        .atag_offset    = 0x220100,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .map_io         = pxa25x_map_io,
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
index 8bcc96e..909b713 100644 (file)
@@ -347,7 +347,7 @@ MACHINE_START(PALMLD, "Palm LifeDrive")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmld_init,
        .restart        = pxa_restart,
 MACHINE_END
index 5ca7b90..5033fd0 100644 (file)
@@ -208,7 +208,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmt5_init,
        .restart        = pxa_restart,
 MACHINE_END
index ca924cf..100b176 100644 (file)
@@ -542,7 +542,7 @@ MACHINE_START(PALMTC, "Palm Tungsten|C")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmtc_init,
        .restart        = pxa_restart,
 MACHINE_END
index 32e0d79..0742721 100644 (file)
@@ -363,7 +363,7 @@ MACHINE_START(PALMTE2, "Palm Tungsten|E2")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmte2_init,
        .restart        = pxa_restart,
 MACHINE_END
index 3f3c48f..d17bda2 100644 (file)
@@ -451,7 +451,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = treo680_init,
        .restart        = pxa_restart,
 MACHINE_END
@@ -465,7 +465,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = centro_init,
        .restart        = pxa_restart,
 MACHINE_END
index 8b43666..627c93a 100644 (file)
@@ -366,7 +366,7 @@ MACHINE_START(PALMTX, "Palm T|X")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmtx_init,
        .restart        = pxa_restart,
 MACHINE_END
index 8cdd4f5..18b7fcd 100644 (file)
@@ -404,7 +404,7 @@ MACHINE_START(PALMZ72, "Palm Zire72")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = palmz72_init,
        .restart        = pxa_restart,
 MACHINE_END
index fe90544..69918c7 100644 (file)
@@ -263,7 +263,7 @@ MACHINE_START(PCM027, "Phytec Messtechnik GmbH phyCORE-PXA270")
        .nr_irqs        = PCM027_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = pcm027_init,
        .restart        = pxa_restart,
 MACHINE_END
index 2910bb9..50ccd5f 100644 (file)
@@ -469,7 +469,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
        .nr_irqs        = POODLE_NR_IRQS,       /* 4 for LoCoMo */
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = poodle_init,
        .restart        = pxa_restart,
 MACHINE_END
index c9192ce..3835979 100644 (file)
@@ -55,7 +55,7 @@ DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)")
        .map_io         = pxa3xx_map_io,
        .init_irq       = pxa3xx_dt_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
        .init_machine   = pxa3xx_dt_init,
        .dt_compat      = pxa3xx_dt_board_compat,
index 25b08bf..af41888 100644 (file)
@@ -1095,7 +1095,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -1108,7 +1108,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
@@ -1121,7 +1121,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 #endif
index 08d87a5..710c493 100644 (file)
@@ -601,7 +601,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = saar_init,
        .restart        = pxa_restart,
 MACHINE_END
index 2073f0e..f90aa27 100644 (file)
@@ -986,7 +986,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = spitz_restart,
 MACHINE_END
 #endif
@@ -1000,7 +1000,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = spitz_restart,
 MACHINE_END
 #endif
@@ -1014,7 +1014,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = spitz_restart,
 MACHINE_END
 #endif
index 456560b..88fde43 100644 (file)
@@ -1006,7 +1006,7 @@ MACHINE_START(INTELMOTE2, "IMOTE 2")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = imote2_init,
        .atag_offset    = 0x100,
        .restart        = pxa_restart,
@@ -1019,7 +1019,7 @@ MACHINE_START(STARGATE2, "Stargate 2")
        .nr_irqs = STARGATE_NR_IRQS,
        .init_irq = pxa27x_init_irq,
        .handle_irq = pxa27x_handle_irq,
-       .timer = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine = stargate2_init,
        .atag_offset = 0x100,
        .restart        = pxa_restart,
index 1a25f8a..f55979c 100644 (file)
@@ -494,7 +494,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = tavorevb_init,
        .restart        = pxa_restart,
 MACHINE_END
index 4bc47d6..8f1ee92 100644 (file)
@@ -89,48 +89,10 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
        }
 }
 
-static struct clock_event_device ckevt_pxa_osmr0 = {
-       .name           = "osmr0",
-       .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 200,
-       .set_next_event = pxa_osmr0_set_next_event,
-       .set_mode       = pxa_osmr0_set_mode,
-};
-
-static struct irqaction pxa_ost0_irq = {
-       .name           = "ost0",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = pxa_ost0_interrupt,
-       .dev_id         = &ckevt_pxa_osmr0,
-};
-
-static void __init pxa_timer_init(void)
-{
-       unsigned long clock_tick_rate = get_clock_tick_rate();
-
-       writel_relaxed(0, OIER);
-       writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
-       setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate);
-
-       clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4);
-       ckevt_pxa_osmr0.max_delta_ns =
-               clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
-       ckevt_pxa_osmr0.min_delta_ns =
-               clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1;
-       ckevt_pxa_osmr0.cpumask = cpumask_of(0);
-
-       setup_irq(IRQ_OST0, &pxa_ost0_irq);
-
-       clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
-               clocksource_mmio_readl_up);
-       clockevents_register_device(&ckevt_pxa_osmr0);
-}
-
 #ifdef CONFIG_PM
 static unsigned long osmr[4], oier, oscr;
 
-static void pxa_timer_suspend(void)
+static void pxa_timer_suspend(struct clock_event_device *cedev)
 {
        osmr[0] = readl_relaxed(OSMR0);
        osmr[1] = readl_relaxed(OSMR1);
@@ -140,7 +102,7 @@ static void pxa_timer_suspend(void)
        oscr = readl_relaxed(OSCR);
 }
 
-static void pxa_timer_resume(void)
+static void pxa_timer_resume(struct clock_event_device *cedev)
 {
        /*
         * Ensure that we have at least MIN_OSCR_DELTA between match
@@ -163,8 +125,38 @@ static void pxa_timer_resume(void)
 #define pxa_timer_resume NULL
 #endif
 
-struct sys_timer pxa_timer = {
-       .init           = pxa_timer_init,
+static struct clock_event_device ckevt_pxa_osmr0 = {
+       .name           = "osmr0",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .rating         = 200,
+       .set_next_event = pxa_osmr0_set_next_event,
+       .set_mode       = pxa_osmr0_set_mode,
        .suspend        = pxa_timer_suspend,
        .resume         = pxa_timer_resume,
 };
+
+static struct irqaction pxa_ost0_irq = {
+       .name           = "ost0",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = pxa_ost0_interrupt,
+       .dev_id         = &ckevt_pxa_osmr0,
+};
+
+void __init pxa_timer_init(void)
+{
+       unsigned long clock_tick_rate = get_clock_tick_rate();
+
+       writel_relaxed(0, OIER);
+       writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+       setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate);
+
+       ckevt_pxa_osmr0.cpumask = cpumask_of(0);
+
+       setup_irq(IRQ_OST0, &pxa_ost0_irq);
+
+       clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
+               clocksource_mmio_readl_up);
+       clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
+               MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
index 233629e..9e7998d 100644 (file)
@@ -982,6 +982,6 @@ MACHINE_START(TOSA, "SHARP Tosa")
        .init_irq       = pxa25x_init_irq,
        .handle_irq       = pxa25x_handle_irq,
        .init_machine   = tosa_init,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = tosa_restart,
 MACHINE_END
index fbbcbed..c580434 100644 (file)
@@ -561,7 +561,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
@@ -573,6 +573,6 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
index c773e4d..9c363c0 100644 (file)
@@ -997,7 +997,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = viper_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = viper_init,
        .restart        = pxa_restart,
 MACHINE_END
index 491b6c9..aa89488 100644 (file)
@@ -719,7 +719,7 @@ MACHINE_START(VPAC270, "Voipac PXA270")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = vpac270_init,
        .restart        = pxa_restart,
 MACHINE_END
index 4275713..13b1d45 100644 (file)
@@ -185,7 +185,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .restart        = pxa_restart,
 MACHINE_END
 
index 97529fa..989903a 100644 (file)
@@ -722,7 +722,7 @@ MACHINE_START(ZIPIT2, "Zipit Z2")
        .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = z2_init,
        .restart        = pxa_restart,
 MACHINE_END
index abd3aa1..f5d4364 100644 (file)
@@ -910,7 +910,7 @@ MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
        .nr_irqs        = ZEUS_NR_IRQS,
        .init_irq       = zeus_init_irq,
        .handle_irq     = pxa27x_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = zeus_init,
        .restart        = pxa_restart,
 MACHINE_END
index 226279f..1f00d65 100644 (file)
@@ -428,7 +428,7 @@ MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
        .nr_irqs        = ZYLONITE_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
-       .timer          = &pxa_timer,
+       .init_time      = pxa_timer_init,
        .init_machine   = zylonite_init,
        .restart        = pxa_restart,
 MACHINE_END
index d6b5073..4475423 100644 (file)
 /*
  * Only define NR_IRQS if less than NR_IRQS_EB
  */
-#define NR_IRQS_EB             (IRQ_EB_GIC_START + 96)
+#define NR_IRQS_EB             (IRQ_EB_GIC_START + 128)
 
 #if defined(CONFIG_MACH_REALVIEW_EB) \
        && (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
index 728587c..5b1c8bf 100644 (file)
@@ -418,10 +418,6 @@ static void __init realview_eb_timer_init(void)
        realview_eb_twd_init();
 }
 
-static struct sys_timer realview_eb_timer = {
-       .init           = realview_eb_timer_init,
-};
-
 static void realview_eb_restart(char mode, const char *cmd)
 {
        void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -472,7 +468,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
        .map_io         = realview_eb_map_io,
        .init_early     = realview_init_early,
        .init_irq       = gic_init_irq,
-       .timer          = &realview_eb_timer,
+       .init_time      = realview_eb_timer_init,
        .init_machine   = realview_eb_init,
 #ifdef CONFIG_ZONE_DMA
        .dma_zone_size  = SZ_256M,
index 3d116c4..d5e83a1 100644 (file)
@@ -329,10 +329,6 @@ static void __init realview_pb1176_timer_init(void)
        realview_timer_init(IRQ_DC1176_TIMER0);
 }
 
-static struct sys_timer realview_pb1176_timer = {
-       .init           = realview_pb1176_timer_init,
-};
-
 static void realview_pb1176_restart(char mode, const char *cmd)
 {
        void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -384,7 +380,7 @@ MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
        .map_io         = realview_pb1176_map_io,
        .init_early     = realview_init_early,
        .init_irq       = gic_init_irq,
-       .timer          = &realview_pb1176_timer,
+       .init_time      = realview_pb1176_timer_init,
        .init_machine   = realview_pb1176_init,
 #ifdef CONFIG_ZONE_DMA
        .dma_zone_size  = SZ_256M,
index e1b8efd..c3cfe21 100644 (file)
@@ -316,10 +316,6 @@ static void __init realview_pb11mp_timer_init(void)
        realview_pb11mp_twd_init();
 }
 
-static struct sys_timer realview_pb11mp_timer = {
-       .init           = realview_pb11mp_timer_init,
-};
-
 static void realview_pb11mp_restart(char mode, const char *cmd)
 {
        void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -367,7 +363,7 @@ MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
        .map_io         = realview_pb11mp_map_io,
        .init_early     = realview_init_early,
        .init_irq       = gic_init_irq,
-       .timer          = &realview_pb11mp_timer,
+       .init_time      = realview_pb11mp_timer_init,
        .init_machine   = realview_pb11mp_init,
 #ifdef CONFIG_ZONE_DMA
        .dma_zone_size  = SZ_256M,
index 0b037f2..dde652a 100644 (file)
@@ -264,10 +264,6 @@ static void __init realview_pba8_timer_init(void)
        realview_timer_init(IRQ_PBA8_TIMER0_1);
 }
 
-static struct sys_timer realview_pba8_timer = {
-       .init           = realview_pba8_timer_init,
-};
-
 static void realview_pba8_restart(char mode, const char *cmd)
 {
        void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -308,7 +304,7 @@ MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
        .map_io         = realview_pba8_map_io,
        .init_early     = realview_init_early,
        .init_irq       = gic_init_irq,
-       .timer          = &realview_pba8_timer,
+       .init_time      = realview_pba8_timer_init,
        .init_machine   = realview_pba8_init,
 #ifdef CONFIG_ZONE_DMA
        .dma_zone_size  = SZ_256M,
index a1f1ef5..54f0185 100644 (file)
@@ -324,10 +324,6 @@ static void __init realview_pbx_timer_init(void)
        realview_pbx_twd_init();
 }
 
-static struct sys_timer realview_pbx_timer = {
-       .init           = realview_pbx_timer_init,
-};
-
 static void realview_pbx_fixup(struct tag *tags, char **from,
                               struct meminfo *meminfo)
 {
@@ -404,7 +400,7 @@ MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
        .map_io         = realview_pbx_map_io,
        .init_early     = realview_init_early,
        .init_irq       = gic_init_irq,
-       .timer          = &realview_pbx_timer,
+       .init_time      = realview_pbx_timer_init,
        .init_machine   = realview_pbx_init,
 #ifdef CONFIG_ZONE_DMA
        .dma_zone_size  = SZ_256M,
index f3fa259..a302cf5 100644 (file)
@@ -211,7 +211,7 @@ static void rpc_restart(char mode, const char *cmd)
        soft_restart(0);
 }
 
-extern struct sys_timer ioc_timer;
+void ioc_timer_init(void);
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
        /* Maintainer: Russell King */
@@ -220,6 +220,6 @@ MACHINE_START(RISCPC, "Acorn-RiscPC")
        .reserve_lp1    = 1,
        .map_io         = rpc_map_io,
        .init_irq       = rpc_init_irq,
-       .timer          = &ioc_timer,
+       .init_time      = ioc_timer_init,
        .restart        = rpc_restart,
 MACHINE_END
index 581fca9..9a6def1 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <asm/mach/time.h>
 
-unsigned long ioc_timer_gettimeoffset(void)
+static u32 ioc_timer_gettimeoffset(void)
 {
        unsigned int count1, count2, status;
        long offset;
@@ -56,7 +56,7 @@ unsigned long ioc_timer_gettimeoffset(void)
        }
 
        offset = (LATCH - offset) * (tick_nsec / 1000);
-       return (offset + LATCH/2) / LATCH;
+       return ((offset + LATCH/2) / LATCH) * 1000;
 }
 
 void __init ioctime_init(void)
@@ -82,14 +82,9 @@ static struct irqaction ioc_timer_irq = {
 /*
  * Set up timer interrupt.
  */
-static void __init ioc_timer_init(void)
+void __init ioc_timer_init(void)
 {
+       arch_gettimeoffset = ioc_timer_gettimeoffset;
        ioctime_init();
        setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
-
-struct sys_timer ioc_timer = {
-       .init           = ioc_timer_init,
-       .offset         = ioc_timer_gettimeoffset,
-};
-
index f4ad99c..0e0279e 100644 (file)
@@ -237,6 +237,6 @@ MACHINE_START(AML_M5900, "AML_M5900")
        .map_io         = amlm5900_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = amlm5900_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 1ee8c46..85eefab 100644 (file)
@@ -448,6 +448,6 @@ MACHINE_START(ANUBIS, "Simtec-Anubis")
        .map_io         = anubis_map_io,
        .init_machine   = anubis_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 00381fe..b31c4aa 100644 (file)
@@ -210,6 +210,6 @@ MACHINE_START(AT2440EVB, "AT2440EVB")
        .map_io         = at2440evb_map_io,
        .init_machine   = at2440evb_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 6a30ce7..526964c 100644 (file)
@@ -612,6 +612,6 @@ MACHINE_START(BAST, "Simtec-BAST")
        .map_io         = bast_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = bast_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 973b87c..fb5d3b3 100644 (file)
@@ -595,6 +595,6 @@ MACHINE_START(NEO1973_GTA02, "GTA02")
        .map_io         = gta02_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = gta02_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index b23dd1b..2eb09e2 100644 (file)
@@ -746,6 +746,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
        .reserve        = h1940_reserve,
        .init_irq       = h1940_init_irq,
        .init_machine   = h1940_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index c9954e2..d7a1725 100644 (file)
@@ -661,6 +661,6 @@ MACHINE_START(JIVE, "JIVE")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = jive_map_io,
        .init_machine   = jive_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index a31d5b8..2db09ad 100644 (file)
@@ -688,6 +688,6 @@ MACHINE_START(MINI2440, "MINI2440")
        .map_io         = mini2440_map_io,
        .init_machine   = mini2440_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index c53a9bf..d9d04b2 100644 (file)
@@ -589,7 +589,7 @@ MACHINE_START(N30, "Acer-N30")
                                Ben Dooks <ben-linux@fluff.org>
        */
        .atag_offset    = 0x100,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .init_machine   = n30_init,
        .init_irq       = s3c24xx_init_irq,
        .map_io         = n30_map_io,
@@ -600,7 +600,7 @@ MACHINE_START(N35, "Acer-N35")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>
        */
        .atag_offset    = 0x100,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .init_machine   = n30_init,
        .init_irq       = s3c24xx_init_irq,
        .map_io         = n30_map_io,
index a2b92b0..a454e24 100644 (file)
@@ -153,6 +153,6 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        .map_io         = nexcoder_map_io,
        .init_machine   = nexcoder_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index bb36d83..ba0f5b5 100644 (file)
@@ -428,6 +428,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
        .map_io         = osiris_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = osiris_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index bca39f0..e0fdae9 100644 (file)
@@ -118,6 +118,6 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        .map_io         = otom11_map_io,
        .init_machine   = otom11_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 7b6ba13..56175f0 100644 (file)
@@ -343,6 +343,6 @@ MACHINE_START(QT2410, "QT2410")
        .map_io         = qt2410_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = qt2410_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 0606f2f..e14ec71 100644 (file)
@@ -814,6 +814,6 @@ MACHINE_START(RX1950, "HP iPAQ RX1950")
        .reserve        = rx1950_reserve,
        .init_irq = s3c24xx_init_irq,
        .init_machine = rx1950_init_machine,
-       .timer = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index dacbb9a..d00caa8 100644 (file)
@@ -212,6 +212,6 @@ MACHINE_START(RX3715, "IPAQ-RX3715")
        .reserve        = rx3715_reserve,
        .init_irq       = rx3715_init_irq,
        .init_machine   = rx3715_init_machine,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 82796b9..e184bfa 100644 (file)
@@ -117,6 +117,6 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
        .map_io         = smdk2410_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = smdk2410_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index ce99fd8..69f356e 100644 (file)
@@ -133,7 +133,7 @@ MACHINE_START(S3C2413, "S3C2413")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
 
@@ -145,7 +145,7 @@ MACHINE_START(SMDK2412, "SMDK2412")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
 
@@ -157,6 +157,6 @@ MACHINE_START(SMDK2413, "SMDK2413")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index f30d7fc..fe160c7 100644 (file)
@@ -254,6 +254,6 @@ MACHINE_START(SMDK2416, "SMDK2416")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2416_map_io,
        .init_machine   = smdk2416_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2416_restart,
 MACHINE_END
index b7ff882..a8fdafe 100644 (file)
@@ -182,6 +182,6 @@ MACHINE_START(S3C2440, "SMDK2440")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2440_map_io,
        .init_machine   = smdk2440_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 2568656..7830d70 100644 (file)
@@ -144,6 +144,6 @@ MACHINE_START(SMDK2443, "SMDK2443")
        .init_irq       = s3c24xx_init_irq,
        .map_io         = smdk2443_map_io,
        .init_machine   = smdk2443_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2443_restart,
 MACHINE_END
index 495bf5c..24b3d79 100644 (file)
@@ -149,6 +149,6 @@ MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
        .map_io         = tct_hammer_map_io,
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = tct_hammer_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 14d5b12..dda21a0 100644 (file)
@@ -357,6 +357,6 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
        .map_io         = vr1000_map_io,
        .init_machine   = vr1000_init,
        .init_irq       = s3c24xx_init_irq,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index f1d44ae..7fe7d4f 100644 (file)
@@ -161,6 +161,6 @@ MACHINE_START(VSTMS, "VSTMS")
        .init_irq       = s3c24xx_init_irq,
        .init_machine   = vstms_init,
        .map_io         = vstms_map_io,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index fa570c2..afeae0b 100644 (file)
@@ -232,6 +232,6 @@ MACHINE_START(ANW6410, "A&W6410")
        .map_io         = anw6410_map_io,
        .init_machine   = anw6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 3185f82..5b6adc7 100644 (file)
@@ -869,6 +869,6 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
        .map_io         = crag6410_map_io,
        .init_machine   = crag6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 2c81bf1..7212eb9 100644 (file)
@@ -275,6 +275,6 @@ MACHINE_START(HMT, "Airgoo-HMT")
        .map_io         = hmt_map_io,
        .init_machine   = hmt_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 3f1e010..e173e6e 100644 (file)
@@ -354,6 +354,6 @@ MACHINE_START(MINI6410, "MINI6410")
        .map_io         = mini6410_map_io,
        .init_machine   = mini6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 73caf9f..8d3cedd 100644 (file)
@@ -103,6 +103,6 @@ MACHINE_START(NCP, "NCP")
        .map_io         = ncp_map_io,
        .init_machine   = ncp_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 4f8129d..4d0d47a 100644 (file)
@@ -333,6 +333,6 @@ MACHINE_START(REAL6410, "REAL6410")
        .map_io         = real6410_map_io,
        .init_machine   = real6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 323399b..ca2afcf 100644 (file)
@@ -155,6 +155,6 @@ MACHINE_START(SMARTQ5, "SmartQ 5")
        .map_io         = smartq_map_io,
        .init_machine   = smartq5_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 9077b85..37bb0c6 100644 (file)
@@ -171,6 +171,6 @@ MACHINE_START(SMARTQ7, "SmartQ 7")
        .map_io         = smartq_map_io,
        .init_machine   = smartq7_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 7df76e4..a392869 100644 (file)
@@ -92,6 +92,6 @@ MACHINE_START(SMDK6400, "SMDK6400")
        .map_io         = smdk6400_map_io,
        .init_machine   = smdk6400_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index ad5142a..1663d10 100644 (file)
@@ -702,6 +702,6 @@ MACHINE_START(SMDK6410, "SMDK6410")
        .map_io         = smdk6410_map_io,
        .init_machine   = smdk6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index e241929..a40d5eb 100644 (file)
@@ -273,6 +273,6 @@ MACHINE_START(SMDK6440, "SMDK6440")
        .init_irq       = s5p6440_init_irq,
        .map_io         = smdk6440_map_io,
        .init_machine   = smdk6440_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5p64x0_restart,
 MACHINE_END
index 9992731..703e576 100644 (file)
@@ -292,6 +292,6 @@ MACHINE_START(SMDK6450, "SMDK6450")
        .init_irq       = s5p6450_init_irq,
        .map_io         = smdk6450_map_io,
        .init_machine   = smdk6450_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5p64x0_restart,
 MACHINE_END
index c3f3095..185a195 100644 (file)
@@ -255,6 +255,6 @@ MACHINE_START(SMDKC100, "SMDKC100")
        .init_irq       = s5pc100_init_irq,
        .map_io         = smdkc100_map_io,
        .init_machine   = smdkc100_machine_init,
-       .timer          = &s3c24xx_timer,
+       .init_time      = s3c24xx_timer_init,
        .restart        = s5pc100_restart,
 MACHINE_END
index 45eb0a8..11900a8 100644 (file)
@@ -686,6 +686,6 @@ MACHINE_START(AQUILA, "Aquila")
        .init_irq       = s5pv210_init_irq,
        .map_io         = aquila_map_io,
        .init_machine   = aquila_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5pv210_restart,
 MACHINE_END
index 9f7f160..5704815 100644 (file)
@@ -973,7 +973,7 @@ MACHINE_START(GONI, "GONI")
        .init_irq       = s5pv210_init_irq,
        .map_io         = goni_map_io,
        .init_machine   = goni_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .reserve        = &goni_reserve,
        .restart        = s5pv210_restart,
 MACHINE_END
index 2f152f9..28bd024 100644 (file)
@@ -153,7 +153,7 @@ MACHINE_START(SMDKC110, "SMDKC110")
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkc110_map_io,
        .init_machine   = smdkc110_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5pv210_restart,
        .reserve        = &smdkc110_reserve,
 MACHINE_END
index 721967b..3c73f36 100644 (file)
@@ -329,7 +329,7 @@ MACHINE_START(SMDKV210, "SMDKV210")
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkv210_map_io,
        .init_machine   = smdkv210_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5pv210_restart,
        .reserve        = &smdkv210_reserve,
 MACHINE_END
index 0ed270f..2d4c553 100644 (file)
@@ -130,6 +130,6 @@ MACHINE_START(TORBRECK, "TORBRECK")
        .init_irq       = s5pv210_init_irq,
        .map_io         = torbreck_map_io,
        .init_machine   = torbreck_machine_init,
-       .timer          = &s5p_timer,
+       .init_time      = s5p_timer_init,
        .restart        = s5pv210_restart,
 MACHINE_END
index 9a23739..b38d252 100644 (file)
@@ -621,7 +621,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
        .map_io         = assabet_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = assabet_init,
        .init_late      = sa11x0_init_late,
 #ifdef CONFIG_SA1111
index b2dadf3..63361b6 100644 (file)
@@ -336,7 +336,7 @@ MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .init_late      = sa11x0_init_late,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
 #ifdef CONFIG_SA1111
        .dma_zone_size  = SZ_1M,
 #endif
index 304bca4..2d25ece 100644 (file)
@@ -174,7 +174,7 @@ MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
        .map_io         = cerf_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = cerf_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = cerf_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index 45f424f..612a456 100644 (file)
@@ -399,7 +399,7 @@ MACHINE_START(COLLIE, "Sharp-Collie")
        .map_io         = collie_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = collie_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index a5b7c13..2abc6a1 100644 (file)
@@ -4,9 +4,7 @@
  * Author: Nicolas Pitre
  */
 
-struct sys_timer;
-
-extern struct sys_timer sa1100_timer;
+extern void sa1100_timer_init(void);
 extern void __init sa1100_map_io(void);
 extern void __init sa1100_init_irq(void);
 extern void __init sa1100_init_gpio(void);
index e1571ea..b8f2b15 100644 (file)
@@ -108,7 +108,7 @@ MACHINE_START(H3100, "Compaq iPAQ H3100")
        .map_io         = h3100_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = h3100_mach_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index ba7a290..b8dc5bd 100644 (file)
@@ -158,7 +158,7 @@ MACHINE_START(H3600, "Compaq iPAQ H3600")
        .map_io         = h3600_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = h3600_mach_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index d005939..643d5f2 100644 (file)
@@ -229,7 +229,7 @@ MACHINE_START(HACKKIT, "HackKit Cpu Board")
        .map_io         = hackkit_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = hackkit_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index 35cfc42..c0b1f5b 100644 (file)
@@ -346,7 +346,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
        .map_io         = jornada720_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = jornada720_mach_init,
        .init_late      = sa11x0_init_late,
 #ifdef CONFIG_SA1111
index f69f78f..a899176 100644 (file)
@@ -174,6 +174,6 @@ MACHINE_START(LART, "LART")
        .init_irq       = sa1100_init_irq,
        .init_machine   = lart_init,
        .init_late      = sa11x0_init_late,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .restart        = sa11x0_restart,
 MACHINE_END
index 102e08f..f1cb378 100644 (file)
@@ -110,7 +110,7 @@ MACHINE_START(NANOENGINE, "BSE nanoEngine")
        .map_io         = nanoengine_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = nanoengine_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index c51bb63..0912618 100644 (file)
@@ -133,7 +133,7 @@ MACHINE_START(PLEB, "PLEB")
        .map_io         = pleb_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = pleb_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index 6460d25..c8866bc 100644 (file)
@@ -102,7 +102,7 @@ MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
        .map_io         = shannon_map_io,
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .init_machine   = shannon_init,
        .init_late      = sa11x0_init_late,
        .restart        = sa11x0_restart,
index 6d65f65..bcbc945 100644 (file)
@@ -396,6 +396,6 @@ MACHINE_START(SIMPAD, "Simpad")
        .nr_irqs        = SA1100_NR_IRQS,
        .init_irq       = sa1100_init_irq,
        .init_late      = sa11x0_init_late,
-       .timer          = &sa1100_timer,
+       .init_time      = sa1100_timer_init,
        .restart        = sa11x0_restart,
 MACHINE_END
index 80702c9..a59a13a 100644 (file)
@@ -69,46 +69,10 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
        }
 }
 
-static struct clock_event_device ckevt_sa1100_osmr0 = {
-       .name           = "osmr0",
-       .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 200,
-       .set_next_event = sa1100_osmr0_set_next_event,
-       .set_mode       = sa1100_osmr0_set_mode,
-};
-
-static struct irqaction sa1100_timer_irq = {
-       .name           = "ost0",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = sa1100_ost0_interrupt,
-       .dev_id         = &ckevt_sa1100_osmr0,
-};
-
-static void __init sa1100_timer_init(void)
-{
-       writel_relaxed(0, OIER);
-       writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
-       setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
-
-       clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4);
-       ckevt_sa1100_osmr0.max_delta_ns =
-               clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0);
-       ckevt_sa1100_osmr0.min_delta_ns =
-               clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
-       ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
-
-       setup_irq(IRQ_OST0, &sa1100_timer_irq);
-
-       clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
-               clocksource_mmio_readl_up);
-       clockevents_register_device(&ckevt_sa1100_osmr0);
-}
-
 #ifdef CONFIG_PM
 unsigned long osmr[4], oier;
 
-static void sa1100_timer_suspend(void)
+static void sa1100_timer_suspend(struct clock_event_device *cedev)
 {
        osmr[0] = readl_relaxed(OSMR0);
        osmr[1] = readl_relaxed(OSMR1);
@@ -117,7 +81,7 @@ static void sa1100_timer_suspend(void)
        oier = readl_relaxed(OIER);
 }
 
-static void sa1100_timer_resume(void)
+static void sa1100_timer_resume(struct clock_event_device *cedev)
 {
        writel_relaxed(0x0f, OSSR);
        writel_relaxed(osmr[0], OSMR0);
@@ -136,8 +100,36 @@ static void sa1100_timer_resume(void)
 #define sa1100_timer_resume NULL
 #endif
 
-struct sys_timer sa1100_timer = {
-       .init           = sa1100_timer_init,
+static struct clock_event_device ckevt_sa1100_osmr0 = {
+       .name           = "osmr0",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .rating         = 200,
+       .set_next_event = sa1100_osmr0_set_next_event,
+       .set_mode       = sa1100_osmr0_set_mode,
        .suspend        = sa1100_timer_suspend,
        .resume         = sa1100_timer_resume,
 };
+
+static struct irqaction sa1100_timer_irq = {
+       .name           = "ost0",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = sa1100_ost0_interrupt,
+       .dev_id         = &ckevt_sa1100_osmr0,
+};
+
+void __init sa1100_timer_init(void)
+{
+       writel_relaxed(0, OIER);
+       writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+       setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
+
+       ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
+
+       setup_irq(IRQ_OST0, &sa1100_timer_irq);
+
+       clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
+               clocksource_mmio_readl_up);
+       clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400,
+                                       MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
index 9ad2e97..b63dec8 100644 (file)
@@ -128,10 +128,6 @@ static void __init shark_timer_init(void)
        setup_irq(IRQ_TIMER, &shark_timer_irq);
 }
 
-static struct sys_timer shark_timer = {
-       .init           = shark_timer_init,
-};
-
 static void shark_init_early(void)
 {
        disable_hlt();
@@ -142,7 +138,7 @@ MACHINE_START(SHARK, "Shark")
        .atag_offset    = 0x3000,
        .init_early     = shark_init_early,
        .init_irq       = shark_init_irq,
-       .timer          = &shark_timer,
+       .init_time      = shark_timer_init,
        .dma_zone_size  = SZ_4M,
        .restart        = shark_restart,
 MACHINE_END
index fd28358..705bc63 100644 (file)
@@ -670,5 +670,5 @@ MACHINE_START(AG5EVM, "ag5evm")
        .init_irq       = sh73a0_init_irq,
        .init_machine   = ag5evm_init,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = sh73a0_earlytimer_init,
 MACHINE_END
index 99ef190..c1d4ab6 100644 (file)
@@ -1350,5 +1350,5 @@ MACHINE_START(AP4EVB, "ap4evb")
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = ap4evb_init,
        .init_late      = sh7372_pm_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = sh7372_earlytimer_init,
 MACHINE_END
index 5353adf..e791244 100644 (file)
@@ -1192,9 +1192,6 @@ static void __init eva_earlytimer_init(void)
 static void __init eva_add_early_devices(void)
 {
        r8a7740_add_early_devices();
-
-       /* override timer setup with board-specific code */
-       shmobile_timer.init = eva_earlytimer_init;
 }
 
 #define RESCNT2 IOMEM(0xe6188020)
@@ -1216,7 +1213,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = eva_init,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = eva_earlytimer_init,
        .dt_compat      = eva_boards_compat_dt,
        .restart        = eva_restart,
 MACHINE_END
index cb8c994..331b7ce 100644 (file)
@@ -499,9 +499,6 @@ static void __init bonito_earlytimer_init(void)
 static void __init bonito_add_early_devices(void)
 {
        r8a7740_add_early_devices();
-
-       /* override timer setup with board-specific code */
-       shmobile_timer.init = bonito_earlytimer_init;
 }
 
 MACHINE_START(BONITO, "bonito")
@@ -511,5 +508,5 @@ MACHINE_START(BONITO, "bonito")
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = bonito_init,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = bonito_earlytimer_init,
 MACHINE_END
index a1d315f..d759a9c 100644 (file)
@@ -552,5 +552,5 @@ MACHINE_START(KOTA2, "kota2")
        .init_irq       = sh73a0_init_irq,
        .init_machine   = kota2_init,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = sh73a0_earlytimer_init,
 MACHINE_END
index f3f180d..c254782 100644 (file)
@@ -90,6 +90,6 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d")
        .init_irq       = emev2_init_irq,
        .init_machine   = kzm9d_add_standard_devices,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = shmobile_timer_init,
        .dt_compat      = kzm9d_boards_compat_dt,
 MACHINE_END
index 278c8f2..ac94285 100644 (file)
@@ -794,7 +794,7 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g")
        .init_irq       = sh73a0_init_irq,
        .init_machine   = kzm_init,
        .init_late      = shmobile_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = sh73a0_earlytimer_init,
        .restart        = kzm9g_restart,
        .dt_compat      = kzm9g_boards_compat_dt,
 MACHINE_END
index 2fed62f..fe4917f 100644 (file)
@@ -1593,6 +1593,6 @@ DT_MACHINE_START(MACKEREL_DT, "mackerel")
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = mackerel_init,
        .init_late      = sh7372_pm_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = sh7372_earlytimer_init,
        .dt_compat  = mackerel_boards_compat_dt,
 MACHINE_END
index fad8db1..cdcb799 100644 (file)
@@ -383,5 +383,5 @@ MACHINE_START(MARZEN, "marzen")
        .init_irq       = r8a7779_init_irq,
        .init_machine   = marzen_init,
        .init_late      = marzen_init_late,
-       .timer          = &shmobile_timer,
+       .init_time      = r8a7779_earlytimer_init,
 MACHINE_END
index dfeca79..a57439e 100644 (file)
@@ -2,7 +2,7 @@
 #define __ARCH_MACH_COMMON_H
 
 extern void shmobile_earlytimer_init(void);
-extern struct sys_timer shmobile_timer;
+extern void shmobile_timer_init(void);
 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
                         unsigned int mult, unsigned int div);
 struct twd_local_timer;
@@ -20,6 +20,7 @@ extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
 
 extern void sh7372_init_irq(void);
 extern void sh7372_map_io(void);
+extern void sh7372_earlytimer_init(void);
 extern void sh7372_add_early_devices(void);
 extern void sh7372_add_standard_devices(void);
 extern void sh7372_clock_init(void);
@@ -32,6 +33,7 @@ extern struct clk sh7372_extal2_clk;
 
 extern void sh73a0_init_irq(void);
 extern void sh73a0_map_io(void);
+extern void sh73a0_earlytimer_init(void);
 extern void sh73a0_add_early_devices(void);
 extern void sh73a0_add_standard_devices(void);
 extern void sh73a0_clock_init(void);
@@ -50,6 +52,7 @@ extern void r8a7740_pinmux_init(void);
 
 extern void r8a7779_init_irq(void);
 extern void r8a7779_map_io(void);
+extern void r8a7779_earlytimer_init(void);
 extern void r8a7779_add_early_devices(void);
 extern void r8a7779_add_standard_devices(void);
 extern void r8a7779_clock_init(void);
index 646d61b..47662a5 100644 (file)
@@ -456,7 +456,7 @@ DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = irqchip_init,
        .init_machine   = emev2_add_standard_devices_dt,
-       .timer          = &shmobile_timer,
+       .init_time      = shmobile_timer_init,
        .dt_compat      = emev2_boards_compat_dt,
 MACHINE_END
 
index 0952224..03c69f9 100644 (file)
@@ -705,12 +705,6 @@ void __init r8a7740_add_standard_devices(void)
        rmobile_add_device_to_domain("A3SP",    &i2c1_device);
 }
 
-static void __init r8a7740_earlytimer_init(void)
-{
-       r8a7740_clock_init(0);
-       shmobile_earlytimer_init();
-}
-
 void __init r8a7740_add_early_devices(void)
 {
        early_platform_add_devices(r8a7740_early_devices,
@@ -718,9 +712,6 @@ void __init r8a7740_add_early_devices(void)
 
        /* setup early console here as well */
        shmobile_setup_console();
-
-       /* override timer setup with soc-specific code */
-       shmobile_timer.init = r8a7740_earlytimer_init;
 }
 
 #ifdef CONFIG_USE_OF
@@ -763,7 +754,7 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
        .init_irq       = r8a7740_init_irq,
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = r8a7740_add_standard_devices_dt,
-       .timer          = &shmobile_timer,
+       .init_time      = shmobile_timer_init,
        .dt_compat      = r8a7740_boards_compat_dt,
 MACHINE_END
 
index 7a1ad4f..a181ced 100644 (file)
@@ -339,7 +339,7 @@ void __init r8a7779_add_standard_devices(void)
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak r8a7779_register_twd(void) { }
 
-static void __init r8a7779_earlytimer_init(void)
+void __init r8a7779_earlytimer_init(void)
 {
        r8a7779_clock_init();
        shmobile_earlytimer_init();
@@ -366,7 +366,4 @@ void __init r8a7779_add_early_devices(void)
         * As a final step pass earlyprint=sh-sci.2,115200 on the kernel
         * command line in case of the marzen board.
         */
-
-       /* override timer setup with soc-specific code */
-       shmobile_timer.init = r8a7779_earlytimer_init;
 }
index c917882..191ae72 100644 (file)
@@ -1054,7 +1054,7 @@ void __init sh7372_add_standard_devices(void)
                                       ARRAY_SIZE(domain_devices));
 }
 
-static void __init sh7372_earlytimer_init(void)
+void __init sh7372_earlytimer_init(void)
 {
        sh7372_clock_init();
        shmobile_earlytimer_init();
@@ -1067,9 +1067,6 @@ void __init sh7372_add_early_devices(void)
 
        /* setup early console here as well */
        shmobile_setup_console();
-
-       /* override timer setup with soc-specific code */
-       shmobile_timer.init = sh7372_earlytimer_init;
 }
 
 #ifdef CONFIG_USE_OF
@@ -1113,7 +1110,7 @@ DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)")
        .init_irq       = sh7372_init_irq,
        .handle_irq     = shmobile_handle_irq_intc,
        .init_machine   = sh7372_add_standard_devices_dt,
-       .timer          = &shmobile_timer,
+       .init_time      = shmobile_timer_init,
        .dt_compat      = sh7372_boards_compat_dt,
 MACHINE_END
 
index db99a4a..8c2d642 100644 (file)
@@ -796,7 +796,7 @@ void __init sh73a0_add_standard_devices(void)
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak sh73a0_register_twd(void) { }
 
-static void __init sh73a0_earlytimer_init(void)
+void __init sh73a0_earlytimer_init(void)
 {
        sh73a0_clock_init();
        shmobile_earlytimer_init();
@@ -810,7 +810,4 @@ void __init sh73a0_add_early_devices(void)
 
        /* setup early console here as well */
        shmobile_setup_console();
-
-       /* override timer setup with soc-specific code */
-       shmobile_timer.init = sh73a0_earlytimer_init;
 }
index a689197..fdbe54a 100644 (file)
@@ -60,10 +60,6 @@ void __init shmobile_earlytimer_init(void)
        late_time_init = shmobile_late_time_init;
 }
 
-static void __init shmobile_timer_init(void)
+void __init shmobile_timer_init(void)
 {
 }
-
-struct sys_timer shmobile_timer = {
-       .init           = shmobile_timer_init,
-};
index 7d55feb..27d6846 100644 (file)
@@ -101,7 +101,7 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
        .smp            = smp_ops(socfpga_smp_ops),
        .map_io         = socfpga_map_io,
        .init_irq       = socfpga_init_irq,
-       .timer          = &dw_apb_timer,
+       .init_time      = dw_apb_timer_init,
        .init_machine   = socfpga_cyclone5_init,
        .restart        = socfpga_cyclone5_restart,
        .dt_compat      = altera_dt_match,
index 510dec7..633e678 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/mach/time.h>
 
 /* Add spear13xx structure declarations here */
-extern struct sys_timer spear13xx_timer;
+extern void spear13xx_timer_init(void);
 extern struct pl022_ssp_controller pl022_plat_data;
 extern struct dw_dma_platform_data dmac_plat_data;
 extern struct dw_dma_slave cf_dma_priv;
index 5de3e6f..56214d1 100644 (file)
@@ -91,7 +91,7 @@ DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
        .smp            =       smp_ops(spear13xx_smp_ops),
        .map_io         =       spear1310_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear13xx_timer,
+       .init_time      =       spear13xx_timer_init,
        .init_machine   =       spear1310_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear1310_dt_board_compat,
index 18331de..9a28beb 100644 (file)
@@ -185,7 +185,7 @@ DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
        .smp            =       smp_ops(spear13xx_smp_ops),
        .map_io         =       spear13xx_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear13xx_timer,
+       .init_time      =       spear13xx_timer_init,
        .init_machine   =       spear1340_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear1340_dt_board_compat,
index 22e3cd5..c7d2b4a 100644 (file)
@@ -152,7 +152,7 @@ static void __init spear13xx_clk_init(void)
                pr_err("%s: Unknown machine\n", __func__);
 }
 
-static void __init spear13xx_timer_init(void)
+void __init spear13xx_timer_init(void)
 {
        char pclk_name[] = "osc_24m_clk";
        struct clk *gpt_clk, *pclk;
@@ -181,7 +181,3 @@ static void __init spear13xx_timer_init(void)
        spear_setup_of_timer();
        twd_local_timer_of_register();
 }
-
-struct sys_timer spear13xx_timer = {
-       .init = spear13xx_timer_init,
-};
index c26b7a4..df31079 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/mach/map.h>
 
 /* Add spear3xx family device structure declarations here */
-extern struct sys_timer spear3xx_timer;
+extern void spear3xx_timer_init(void);
 extern struct pl022_ssp_controller pl022_plat_data;
 extern struct pl08x_platform_data pl080_plat_data;
 
index 499479b..bbc9b7e 100644 (file)
@@ -213,7 +213,7 @@ static void __init spear300_map_io(void)
 DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
        .map_io         =       spear300_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear3xx_timer,
+       .init_time      =       spear3xx_timer_init,
        .init_machine   =       spear300_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear300_dt_board_compat,
index 367d9be..c13a434 100644 (file)
@@ -255,7 +255,7 @@ static void __init spear310_map_io(void)
 DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
        .map_io         =       spear310_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear3xx_timer,
+       .init_time      =       spear3xx_timer_init,
        .init_machine   =       spear310_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear310_dt_board_compat,
index 34c212e..e1c7707 100644 (file)
@@ -269,7 +269,7 @@ static void __init spear320_map_io(void)
 DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
        .map_io         =       spear320_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear3xx_timer,
+       .init_time      =       spear3xx_timer_init,
        .init_machine   =       spear320_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear320_dt_board_compat,
index c6003ef..b2ba516 100644 (file)
@@ -84,7 +84,7 @@ void __init spear3xx_map_io(void)
        iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
 }
 
-static void __init spear3xx_timer_init(void)
+void __init spear3xx_timer_init(void)
 {
        char pclk_name[] = "pll3_clk";
        struct clk *gpt_clk, *pclk;
@@ -112,7 +112,3 @@ static void __init spear3xx_timer_init(void)
 
        spear_setup_of_timer();
 }
-
-struct sys_timer spear3xx_timer = {
-       .init = spear3xx_timer_init,
-};
index 3f6fac0..b8bd33c 100644 (file)
@@ -373,7 +373,7 @@ void __init spear6xx_map_io(void)
        iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
 }
 
-static void __init spear6xx_timer_init(void)
+void __init spear6xx_timer_init(void)
 {
        char pclk_name[] = "pll3_clk";
        struct clk *gpt_clk, *pclk;
@@ -402,10 +402,6 @@ static void __init spear6xx_timer_init(void)
        spear_setup_of_timer();
 }
 
-struct sys_timer spear6xx_timer = {
-       .init = spear6xx_timer_init,
-};
-
 /* Add auxdata to pass platform data */
 struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
@@ -427,7 +423,7 @@ static const char *spear600_dt_board_compat[] = {
 DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
        .map_io         =       spear6xx_map_io,
        .init_irq       =       irqchip_init,
-       .timer          =       &spear6xx_timer,
+       .init_time      =       spear6xx_timer_init,
        .init_machine   =       spear600_dt_init,
        .restart        =       spear_restart,
        .dt_compat      =       spear600_dt_board_compat,
index 0ff310e..fb8fbce 100644 (file)
@@ -89,6 +89,6 @@ DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
        .init_irq       = sunxi_init_irq,
        .handle_irq     = sunxi_handle_irq,
        .restart        = sunxi_restart,
-       .timer          = &sunxi_timer,
+       .init_time      = &sunxi_timer_init,
        .dt_compat      = sunxi_board_dt_compat,
 MACHINE_END
index 04008c8..5ed81ba 100644 (file)
@@ -200,7 +200,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
        .smp            = smp_ops(tegra_smp_ops),
        .init_early     = tegra20_init_early,
        .init_irq       = tegra_dt_init_irq,
-       .timer          = &tegra_sys_timer,
+       .init_time      = tegra_init_timer,
        .init_machine   = tegra_dt_init,
        .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
index 672db8a..12dc2dd 100644 (file)
@@ -111,7 +111,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
        .map_io         = tegra_map_common_io,
        .init_early     = tegra30_init_early,
        .init_irq       = tegra_dt_init_irq,
-       .timer          = &tegra_sys_timer,
+       .init_time      = tegra_init_timer,
        .init_machine   = tegra30_dt_init,
        .init_late      = tegra_init_late,
        .restart        = tegra_assert_system_reset,
index 91fbe73..744cdd2 100644 (file)
@@ -55,5 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; }
 
 void __init tegra_paz00_wifikill_init(void);
 
-extern struct sys_timer tegra_sys_timer;
+extern void tegra_init_timer(void);
 #endif
index e4863f3..eba0969 100644 (file)
@@ -168,7 +168,7 @@ static const struct of_device_id rtc_match[] __initconst = {
        {}
 };
 
-static void __init tegra_init_timer(void)
+void __init tegra_init_timer(void)
 {
        struct device_node *np;
        struct clk *clk;
@@ -259,24 +259,16 @@ static void __init tegra_init_timer(void)
                BUG();
        }
 
-       clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5);
-       tegra_clockevent.max_delta_ns =
-               clockevent_delta2ns(0x1fffffff, &tegra_clockevent);
-       tegra_clockevent.min_delta_ns =
-               clockevent_delta2ns(0x1, &tegra_clockevent);
        tegra_clockevent.cpumask = cpu_all_mask;
        tegra_clockevent.irq = tegra_timer_irq.irq;
-       clockevents_register_device(&tegra_clockevent);
+       clockevents_config_and_register(&tegra_clockevent, 1000000,
+                                       0x1, 0x1fffffff);
 #ifdef CONFIG_HAVE_ARM_TWD
        twd_local_timer_of_register();
 #endif
        register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 
-struct sys_timer tegra_sys_timer = {
-       .init = tegra_init_timer,
-};
-
 #ifdef CONFIG_PM
 static u32 usec_config;
 
index 26b48fa..12060ae 100644 (file)
@@ -1779,7 +1779,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
        .map_io         = u300_map_io,
        .nr_irqs        = 0,
        .init_irq       = u300_init_irq,
-       .timer          = &u300_timer,
+       .init_time      = u300_timer_init,
        .init_machine   = u300_init_machine,
        .restart        = u300_restart,
 MACHINE_END
index 1da10e2..d9e7320 100644 (file)
@@ -349,7 +349,7 @@ static u32 notrace u300_read_sched_clock(void)
 /*
  * This sets up the system timers, clock source and clock event.
  */
-static void __init u300_timer_init(void)
+void __init u300_timer_init(void)
 {
        struct clk *clk;
        unsigned long rate;
@@ -413,11 +413,3 @@ static void __init u300_timer_init(void)
         * used by hrtimers!
         */
 }
-
-/*
- * Very simple system timer that only register the clock event and
- * clock source.
- */
-struct sys_timer u300_timer = {
-       .init           = u300_timer_init,
-};
index b5e9791..d34287b 100644 (file)
@@ -1 +1 @@
-extern struct sys_timer u300_timer;
+extern void u300_timer_init(void);
index af406c7..0e928d2 100644 (file)
@@ -750,7 +750,7 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        /* we re-use nomadik timer here */
-       .timer          = &ux500_timer,
+       .init_time      = ux500_timer_init,
        .init_machine   = mop500_init_machine,
        .init_late      = ux500_init_late,
 MACHINE_END
@@ -759,7 +759,7 @@ MACHINE_START(U8520, "ST-Ericsson U8520 Platform HREFP520")
        .atag_offset    = 0x100,
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
-       .timer          = &ux500_timer,
+       .init_time      = ux500_timer_init,
        .init_machine   = mop500_init_machine,
        .init_late      = ux500_init_late,
 MACHINE_END
@@ -769,7 +769,7 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
        .smp            = smp_ops(ux500_smp_ops),
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
-       .timer          = &ux500_timer,
+       .init_time      = ux500_timer_init,
        .init_machine   = hrefv60_init_machine,
        .init_late      = ux500_init_late,
 MACHINE_END
@@ -780,7 +780,7 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        /* we re-use nomadik timer here */
-       .timer          = &ux500_timer,
+       .init_time      = ux500_timer_init,
        .init_machine   = snowball_init_machine,
        .init_late      = NULL,
 MACHINE_END
index 4c91d76..218a6b1 100644 (file)
@@ -340,7 +340,7 @@ DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)")
        .map_io         = u8500_map_io,
        .init_irq       = ux500_init_irq,
        /* we re-use nomadik timer here */
-       .timer          = &ux500_timer,
+       .init_time      = ux500_timer_init,
        .init_machine   = u8500_init_machine,
        .init_late      = NULL,
        .dt_compat      = stericsson_dt_platform_compat,
index 6be4c4d..bddce2b 100644 (file)
@@ -28,8 +28,7 @@ extern struct device *ux500_soc_device_init(const char *soc_id);
 struct amba_device;
 extern void __init amba_add_devices(struct amba_device *devs[], int num);
 
-struct sys_timer;
-extern struct sys_timer ux500_timer;
+extern void ux500_timer_init(void);
 
 #define __IO_DEV_DESC(x, sz)   {               \
        .virtual        = IO_ADDRESS(x),        \
index 875309a..aa2a78a 100644 (file)
@@ -46,7 +46,7 @@ const static struct of_device_id prcmu_timer_of_match[] __initconst = {
        { },
 };
 
-static void __init ux500_timer_init(void)
+void __init ux500_timer_init(void)
 {
        void __iomem *mtu_timer_base;
        void __iomem *prcmu_timer_base;
@@ -99,14 +99,3 @@ dt_fail:
        clksrc_dbx500_prcmu_init(prcmu_timer_base);
        ux500_twd_init();
 }
-
-static void ux500_timer_reset(void)
-{
-       nmdk_clkevt_reset();
-       nmdk_clksrc_reset();
-}
-
-struct sys_timer ux500_timer = {
-       .init           = ux500_timer_init,
-       .resume         = ux500_timer_reset,
-};
index 49ac384..a42b890 100644 (file)
@@ -770,7 +770,7 @@ void __init versatile_init(void)
 /*
  * Set up timer interrupt, and return the current time in seconds.
  */
-static void __init versatile_timer_init(void)
+void __init versatile_timer_init(void)
 {
        u32 val;
 
@@ -797,8 +797,3 @@ static void __init versatile_timer_init(void)
        sp804_clocksource_init(TIMER3_VA_BASE, "timer3");
        sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0");
 }
-
-struct sys_timer versatile_timer = {
-       .init           = versatile_timer_init,
-};
-
index 683e607..5c1b87d 100644 (file)
@@ -29,7 +29,7 @@ extern void __init versatile_init(void);
 extern void __init versatile_init_early(void);
 extern void __init versatile_init_irq(void);
 extern void __init versatile_map_io(void);
-extern struct sys_timer versatile_timer;
+extern void versatile_timer_init(void);
 extern void versatile_restart(char, const char *);
 extern unsigned int mmc_status(struct device *dev);
 #ifdef CONFIG_OF
index ddeec67..1caef10 100644 (file)
@@ -38,7 +38,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
-       .timer          = &versatile_timer,
+       .init_time      = versatile_timer_init,
        .init_machine   = versatile_init,
        .restart        = versatile_restart,
 MACHINE_END
index f48f2e4..2558f2e 100644 (file)
@@ -45,7 +45,7 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
-       .timer          = &versatile_timer,
+       .init_time      = versatile_timer_init,
        .init_machine   = versatile_dt_init,
        .dt_compat      = versatile_dt_match,
        .restart        = versatile_restart,
index e52eb23..611d140 100644 (file)
@@ -106,7 +106,7 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
        .map_io         = versatile_map_io,
        .init_early     = versatile_init_early,
        .init_irq       = versatile_init_irq,
-       .timer          = &versatile_timer,
+       .init_time      = versatile_timer_init,
        .init_machine   = versatile_pb_init,
        .restart        = versatile_restart,
 MACHINE_END
index 82be02b..915683c 100644 (file)
@@ -291,10 +291,6 @@ static void __init v2m_timer_init(void)
        v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
 }
 
-static struct sys_timer v2m_timer = {
-       .init   = v2m_timer_init,
-};
-
 static void __init v2m_init_early(void)
 {
        if (ct_desc->init_early)
@@ -376,7 +372,7 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
        .map_io         = v2m_map_io,
        .init_early     = v2m_init_early,
        .init_irq       = v2m_init_irq,
-       .timer          = &v2m_timer,
+       .init_time      = v2m_timer_init,
        .init_machine   = v2m_init,
        .restart        = vexpress_restart,
 MACHINE_END
@@ -457,10 +453,6 @@ static void __init v2m_dt_timer_init(void)
                                24000000);
 }
 
-static struct sys_timer v2m_dt_timer = {
-       .init = v2m_dt_timer_init,
-};
-
 static const struct of_device_id v2m_dt_bus_match[] __initconst = {
        { .compatible = "simple-bus", },
        { .compatible = "arm,amba-bus", },
@@ -487,7 +479,7 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
        .map_io         = v2m_dt_map_io,
        .init_early     = v2m_dt_init_early,
        .init_irq       = irqchip_init,
-       .timer          = &v2m_dt_timer,
+       .init_time      = v2m_dt_timer_init,
        .init_machine   = v2m_dt_init,
        .restart        = vexpress_restart,
 MACHINE_END
index 2ed0b7d..570a801 100644 (file)
@@ -8,5 +8,6 @@ config ARCH_VT8500
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_CLK
+       select VT8500_TIMER
        help
          Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
index e035251..92ceb24 100644 (file)
@@ -1 +1 @@
-obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o
+obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o
index 6f2b843..77611a6 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/of.h>
 
-void __init vt8500_timer_init(void);
 int __init vt8500_irq_init(struct device_node *node,
                                struct device_node *parent);
 
index 3c66d48..b9fd9d3 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/io.h>
 #include <linux/pm.h>
+#include <linux/vt8500_timer.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -175,10 +176,6 @@ static void __init vt8500_init_irq(void)
        of_irq_init(vt8500_irq_match);
 };
 
-static struct sys_timer vt8500_timer = {
-       .init = vt8500_timer_init,
-};
-
 static const char * const vt8500_dt_compat[] = {
        "via,vt8500",
        "wm,wm8650",
@@ -189,7 +186,7 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
        .dt_compat      = vt8500_dt_compat,
        .map_io         = vt8500_map_io,
        .init_irq       = vt8500_init_irq,
-       .timer          = &vt8500_timer,
+       .init_time      = vt8500_timer_init,
        .init_machine   = vt8500_init,
        .restart        = vt8500_restart,
        .handle_irq     = vt8500_handle_irq,
index b4243e4..92f1c97 100644 (file)
@@ -37,6 +37,6 @@ MACHINE_START(W90P910EVB, "W90P910EVB")
        .map_io         = nuc910evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc910evb_init,
-       .timer          = &nuc900_timer,
+       .init_time      = nuc900_timer_init,
        .restart        = nuc9xx_restart,
 MACHINE_END
index 500fe59..26f7189 100644 (file)
@@ -40,6 +40,6 @@ MACHINE_START(W90P950EVB, "W90P950EVB")
        .map_io         = nuc950evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc950evb_init,
-       .timer          = &nuc900_timer,
+       .init_time      = nuc900_timer_init,
        .restart        = nuc9xx_restart,
 MACHINE_END
index cbb3adc..9b4e73f 100644 (file)
@@ -37,6 +37,6 @@ MACHINE_START(W90N960EVB, "W90N960EVB")
        .map_io         = nuc960evb_map_io,
        .init_irq       = nuc900_init_irq,
        .init_machine   = nuc960evb_init,
-       .timer          = &nuc900_timer,
+       .init_time      = nuc900_timer_init,
        .restart        = nuc9xx_restart,
 MACHINE_END
index 91acb40..88ef4b2 100644 (file)
  *
  */
 struct map_desc;
-struct sys_timer;
 
 /* core initialisation functions */
 
 extern void nuc900_init_irq(void);
-extern struct sys_timer nuc900_timer;
+extern void nuc900_timer_init(void);
 extern void nuc9xx_restart(char, const char *);
index fa27c49..30fbca8 100644 (file)
@@ -91,7 +91,6 @@ static int nuc900_clockevent_setnextevent(unsigned long evt,
 
 static struct clock_event_device nuc900_clockevent_device = {
        .name           = "nuc900-timer0",
-       .shift          = 32,
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode       = nuc900_clockevent_setmode,
        .set_next_event = nuc900_clockevent_setnextevent,
@@ -133,15 +132,10 @@ static void __init nuc900_clockevents_init(void)
        __raw_writel(RESETINT, REG_TISR);
        setup_irq(IRQ_TIMER0, &nuc900_timer0_irq);
 
-       nuc900_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC,
-                                       nuc900_clockevent_device.shift);
-       nuc900_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff,
-                                       &nuc900_clockevent_device);
-       nuc900_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf,
-                                       &nuc900_clockevent_device);
        nuc900_clockevent_device.cpumask = cpumask_of(0);
 
-       clockevents_register_device(&nuc900_clockevent_device);
+       clockevents_config_and_register(&nuc900_clockevent_device, rate,
+                                       0xf, 0xffffffff);
 }
 
 static void __init nuc900_clocksource_init(void)
@@ -167,12 +161,8 @@ static void __init nuc900_clocksource_init(void)
                TDR_SHIFT, clocksource_mmio_readl_down);
 }
 
-static void __init nuc900_timer_init(void)
+void __init nuc900_timer_init(void)
 {
        nuc900_clocksource_init();
        nuc900_clockevents_init();
 }
-
-struct sys_timer nuc900_timer = {
-       .init           = nuc900_timer_init,
-};
index 2d96745..6472a69 100644 (file)
@@ -79,13 +79,6 @@ static void __init xilinx_zynq_timer_init(void)
        xttcpss_timer_init();
 }
 
-/*
- * Instantiate and initialize the system timer structure
- */
-static struct sys_timer xttcpss_sys_timer = {
-       .init           = xilinx_zynq_timer_init,
-};
-
 /**
  * xilinx_map_io() - Create memory mappings needed for early I/O.
  */
@@ -105,6 +98,6 @@ MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
        .map_io         = xilinx_map_io,
        .init_irq       = irqchip_init,
        .init_machine   = xilinx_init_machine,
-       .timer          = &xttcpss_sys_timer,
+       .init_time      = xilinx_zynq_timer_init,
        .dt_compat      = xilinx_dt_match,
 MACHINE_END
index 076c26d..dda3904 100644 (file)
@@ -640,7 +640,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 
        if (is_coherent || nommu())
                addr = __alloc_simple_buffer(dev, size, gfp, &page);
-       else if (gfp & GFP_ATOMIC)
+       else if (!(gfp & __GFP_WAIT))
                addr = __alloc_from_pool(size, &page);
        else if (!IS_ENABLED(CONFIG_CMA))
                addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
index 99db769..2dffc01 100644 (file)
@@ -1,4 +1,6 @@
+#include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 
 #include <asm/cputype.h>
 #include <asm/idmap.h>
@@ -6,6 +8,7 @@
 #include <asm/pgtable.h>
 #include <asm/sections.h>
 #include <asm/system_info.h>
+#include <asm/virt.h>
 
 pgd_t *idmap_pgd;
 
@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
        } while (pud++, addr = next, addr != end);
 }
 
-static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
+static void identity_mapping_add(pgd_t *pgd, const char *text_start,
+                                const char *text_end, unsigned long prot)
 {
-       unsigned long prot, next;
+       unsigned long addr, end;
+       unsigned long next;
+
+       addr = virt_to_phys(text_start);
+       end = virt_to_phys(text_end);
+
+       prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
 
-       prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
        if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
                prot |= PMD_BIT4;
 
@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e
        } while (pgd++, addr = next, addr != end);
 }
 
+#if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE)
+pgd_t *hyp_pgd;
+
+extern char  __hyp_idmap_text_start[], __hyp_idmap_text_end[];
+
+static int __init init_static_idmap_hyp(void)
+{
+       hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+       if (!hyp_pgd)
+               return -ENOMEM;
+
+       pr_info("Setting up static HYP identity map for 0x%p - 0x%p\n",
+               __hyp_idmap_text_start, __hyp_idmap_text_end);
+       identity_mapping_add(hyp_pgd, __hyp_idmap_text_start,
+                            __hyp_idmap_text_end, PMD_SECT_AP1);
+
+       return 0;
+}
+#else
+static int __init init_static_idmap_hyp(void)
+{
+       return 0;
+}
+#endif
+
 extern char  __idmap_text_start[], __idmap_text_end[];
 
 static int __init init_static_idmap(void)
 {
-       phys_addr_t idmap_start, idmap_end;
+       int ret;
 
        idmap_pgd = pgd_alloc(&init_mm);
        if (!idmap_pgd)
                return -ENOMEM;
 
-       /* Add an identity mapping for the physical address of the section. */
-       idmap_start = virt_to_phys((void *)__idmap_text_start);
-       idmap_end = virt_to_phys((void *)__idmap_text_end);
+       pr_info("Setting up static identity map for 0x%p - 0x%p\n",
+               __idmap_text_start, __idmap_text_end);
+       identity_mapping_add(idmap_pgd, __idmap_text_start,
+                            __idmap_text_end, 0);
 
-       pr_info("Setting up static identity map for 0x%llx - 0x%llx\n",
-               (long long)idmap_start, (long long)idmap_end);
-       identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
+       ret = init_static_idmap_hyp();
 
        /* Flush L1 for the hardware to see this page table content */
        flush_cache_louis();
 
-       return 0;
+       return ret;
 }
 early_initcall(init_static_idmap);
 
index ce328c7..8fcf8bd 100644 (file)
@@ -57,6 +57,9 @@ static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
 static unsigned int ecc_mask __initdata = 0;
 pgprot_t pgprot_user;
 pgprot_t pgprot_kernel;
+pgprot_t pgprot_hyp_device;
+pgprot_t pgprot_s2;
+pgprot_t pgprot_s2_device;
 
 EXPORT_SYMBOL(pgprot_user);
 EXPORT_SYMBOL(pgprot_kernel);
@@ -66,34 +69,46 @@ struct cachepolicy {
        unsigned int    cr_mask;
        pmdval_t        pmd;
        pteval_t        pte;
+       pteval_t        pte_s2;
 };
 
+#ifdef CONFIG_ARM_LPAE
+#define s2_policy(policy)      policy
+#else
+#define s2_policy(policy)      0
+#endif
+
 static struct cachepolicy cache_policies[] __initdata = {
        {
                .policy         = "uncached",
                .cr_mask        = CR_W|CR_C,
                .pmd            = PMD_SECT_UNCACHED,
                .pte            = L_PTE_MT_UNCACHED,
+               .pte_s2         = s2_policy(L_PTE_S2_MT_UNCACHED),
        }, {
                .policy         = "buffered",
                .cr_mask        = CR_C,
                .pmd            = PMD_SECT_BUFFERED,
                .pte            = L_PTE_MT_BUFFERABLE,
+               .pte_s2         = s2_policy(L_PTE_S2_MT_UNCACHED),
        }, {
                .policy         = "writethrough",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WT,
                .pte            = L_PTE_MT_WRITETHROUGH,
+               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITETHROUGH),
        }, {
                .policy         = "writeback",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WB,
                .pte            = L_PTE_MT_WRITEBACK,
+               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITEBACK),
        }, {
                .policy         = "writealloc",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WBWA,
                .pte            = L_PTE_MT_WRITEALLOC,
+               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITEBACK),
        }
 };
 
@@ -310,6 +325,7 @@ static void __init build_mem_type_table(void)
        struct cachepolicy *cp;
        unsigned int cr = get_cr();
        pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
+       pteval_t hyp_device_pgprot, s2_pgprot, s2_device_pgprot;
        int cpu_arch = cpu_architecture();
        int i;
 
@@ -421,6 +437,8 @@ static void __init build_mem_type_table(void)
         */
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
+       s2_pgprot = cp->pte_s2;
+       hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
 
        /*
         * ARMv6 and above have extended page tables.
@@ -444,6 +462,7 @@ static void __init build_mem_type_table(void)
                        user_pgprot |= L_PTE_SHARED;
                        kern_pgprot |= L_PTE_SHARED;
                        vecs_pgprot |= L_PTE_SHARED;
+                       s2_pgprot |= L_PTE_SHARED;
                        mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
                        mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
                        mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
@@ -498,6 +517,9 @@ static void __init build_mem_type_table(void)
        pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
        pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
                                 L_PTE_DIRTY | kern_pgprot);
+       pgprot_s2  = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | s2_pgprot);
+       pgprot_s2_device  = __pgprot(s2_device_pgprot);
+       pgprot_hyp_device  = __pgprot(hyp_device_pgprot);
 
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
index cbfbbe4..837a2d5 100644 (file)
@@ -156,14 +156,9 @@ void __init iop_init_time(unsigned long tick_rate)
        write_tmr0(timer_ctl & ~IOP_TMR_EN);
        write_tisr(1);
        setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
-       clockevents_calc_mult_shift(&iop_clockevent,
-                                   tick_rate, IOP_MIN_RANGE);
-       iop_clockevent.max_delta_ns =
-               clockevent_delta2ns(0xfffffffe, &iop_clockevent);
-       iop_clockevent.min_delta_ns =
-               clockevent_delta2ns(0xf, &iop_clockevent);
        iop_clockevent.cpumask = cpumask_of(0);
-       clockevents_register_device(&iop_clockevent);
+       clockevents_config_and_register(&iop_clockevent, tick_rate,
+                                       0xf, 0xfffffffe);
 
        /*
         * Set up free-running clocksource timer 1.
index 0f4fa86..5d5ac0f 100644 (file)
@@ -156,7 +156,6 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 static struct clock_event_device orion_clkevt = {
        .name           = "orion_tick",
        .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
-       .shift          = 32,
        .rating         = 300,
        .set_next_event = orion_clkevt_next_event,
        .set_mode       = orion_clkevt_mode,
@@ -221,9 +220,6 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
         * Setup clockevent timer (interrupt-driven).
         */
        setup_irq(irq, &orion_timer_irq);
-       orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
-       orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
-       orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
        orion_clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&orion_clkevt);
+       clockevents_config_and_register(&orion_clkevt, tclk, 1, 0xfffffffe);
 }
index b69e11d..37703ef 100644 (file)
@@ -194,8 +194,7 @@ extern void s3c24xx_init_uartdevs(char *name,
 
 /* timer for 2410/2440 */
 
-struct sys_timer;
-extern struct sys_timer s3c24xx_timer;
+extern void s3c24xx_timer_init(void);
 
 extern struct syscore_ops s3c2410_pm_syscore_ops;
 extern struct syscore_ops s3c2412_pm_syscore_ops;
index 3a70aeb..9c96f35 100644 (file)
@@ -36,5 +36,5 @@ struct s5p_timer_source {
 
 extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
                                        enum s5p_timer_mode source);
-extern struct sys_timer s5p_timer;
+extern void s5p_timer_init(void);
 #endif /* __ASM_PLAT_S5P_TIME_H */
index 028b6e8..e92510c 100644 (file)
@@ -274,15 +274,8 @@ static void __init s5p_clockevent_init(void)
        clock_rate = clk_get_rate(tin_event);
        clock_count_per_tick = clock_rate / HZ;
 
-       clockevents_calc_mult_shift(&time_event_device,
-                                   clock_rate, S5PTIMER_MIN_RANGE);
-       time_event_device.max_delta_ns =
-               clockevent_delta2ns(-1, &time_event_device);
-       time_event_device.min_delta_ns =
-               clockevent_delta2ns(1, &time_event_device);
-
        time_event_device.cpumask = cpumask_of(0);
-       clockevents_register_device(&time_event_device);
+       clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
 
        irq_number = timer_source.event_id + IRQ_TIMER0;
        setup_irq(irq_number, &s5p_clock_event_irq);
@@ -393,13 +386,9 @@ static void __init s5p_timer_resources(void)
        clk_enable(tin_source);
 }
 
-static void __init s5p_timer_init(void)
+void __init s5p_timer_init(void)
 {
        s5p_timer_resources();
        s5p_clockevent_init();
        s5p_clocksource_init();
 }
-
-struct sys_timer s5p_timer = {
-       .init           = s5p_timer_init,
-};
index 60552e2..73defd0 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/mach-types.h>
 
@@ -95,7 +96,7 @@ static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
  * IRQs are disabled before entering here from do_gettimeofday()
  */
 
-static unsigned long s3c2410_gettimeoffset (void)
+static u32 s3c2410_gettimeoffset(void)
 {
        unsigned long tdone;
        unsigned long tval;
@@ -120,7 +121,7 @@ static unsigned long s3c2410_gettimeoffset (void)
                        tdone += timer_startval;
        }
 
-       return timer_ticks_to_usec(tdone);
+       return timer_ticks_to_usec(tdone) * 1000;
 }
 
 
@@ -271,15 +272,16 @@ static void __init s3c2410_timer_resources(void)
        clk_enable(tin);
 }
 
-static void __init s3c2410_timer_init(void)
+static struct syscore_ops s3c24xx_syscore_ops = {
+       .resume         = s3c2410_timer_setup,
+};
+
+void __init s3c24xx_timer_init(void)
 {
+       arch_gettimeoffset = s3c2410_gettimeoffset;
+
        s3c2410_timer_resources();
        s3c2410_timer_setup();
        setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+       register_syscore_ops(&s3c24xx_syscore_ops);
 }
-
-struct sys_timer s3c24xx_timer = {
-       .init           = s3c2410_timer_init,
-       .offset         = s3c2410_gettimeoffset,
-       .resume         = s3c2410_timer_setup
-};
index 03321af..bd5c53c 100644 (file)
@@ -186,15 +186,9 @@ static void __init spear_clockevent_init(int irq)
        tick_rate = clk_get_rate(gpt_clk);
        tick_rate >>= CTRL_PRESCALER16;
 
-       clockevents_calc_mult_shift(&clkevt, tick_rate, SPEAR_MIN_RANGE);
-
-       clkevt.max_delta_ns = clockevent_delta2ns(0xfff0,
-                       &clkevt);
-       clkevt.min_delta_ns = clockevent_delta2ns(3, &clkevt);
-
        clkevt.cpumask = cpumask_of(0);
 
-       clockevents_register_device(&clkevt);
+       clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0);
 
        setup_irq(irq, &spear_timer_irq);
 }
index aaf5199..b3d18f9 100644 (file)
@@ -336,4 +336,14 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif /* __ASM_AVR32_DMA_MAPPING_H */
index bbf4610..054d9ec 100644 (file)
@@ -154,4 +154,14 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        _dma_sync((dma_addr_t)vaddr, size, dir);
 }
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif                         /* _BLACKFIN_DMA_MAPPING_H */
index 2310b24..3126b92 100644 (file)
@@ -85,7 +85,7 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *))
 /*
  * Should return useconds since last timer tick
  */
-u32 arch_gettimeoffset(void)
+static u32 blackfin_gettimeoffset(void)
 {
        unsigned long offset;
        unsigned long clocks_per_jiffy;
@@ -141,6 +141,10 @@ void read_persistent_clock(struct timespec *ts)
 
 void __init time_init(void)
 {
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+       arch_gettimeoffset = blackfin_gettimeoffset;
+#endif
+
 #ifdef CONFIG_RTC_DRV_BFIN
        /* [#2663] hack to filter junk RTC values that would cause
         * userspace to have to deal with time values greater than
index 3c69406..88bd0d8 100644 (file)
@@ -89,4 +89,19 @@ extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f))
 #define dma_free_noncoherent(d, s, v, h)  dma_free_coherent((d), (s), (v), (h))
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif /* _ASM_C6X_DMA_MAPPING_H */
index bcffcb6..fce7c54 100644 (file)
@@ -55,9 +55,9 @@ unsigned long get_ns_in_jiffie(void)
        return ns;
 }
 
-unsigned long do_slow_gettimeoffset(void)
+static u32 cris_v10_gettimeoffset(void)
 {
-       unsigned long count;
+       u32 count;
 
        /* The timer interrupt comes from Etrax timer 0. In order to get
         * better precision, we check the current value. It might have
@@ -65,8 +65,8 @@ unsigned long do_slow_gettimeoffset(void)
         */
        count = *R_TIMER0_DATA;
 
-       /* Convert timer value to usec */
-       return (TIMER0_DIV - count) * ((NSEC_PER_SEC/1000)/HZ)/TIMER0_DIV;
+       /* Convert timer value to nsec */
+       return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV;
 }
 
 /* Excerpt from the Etrax100 HSDD about the built-in watchdog:
@@ -191,6 +191,8 @@ static struct irqaction irq2  = {
 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 
index 8588b2c..2f0f654 100644 (file)
@@ -158,5 +158,15 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 {
 }
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 
 #endif
index 277ffc4..fe6acda 100644 (file)
 extern unsigned long loops_per_jiffy; /* init/main.c */
 unsigned long loops_per_usec;
 
-
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-extern unsigned long do_slow_gettimeoffset(void);
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-
-u32 arch_gettimeoffset(void)
-{
-       return do_gettimeoffset() * 1000;
-}
-#endif
-
 int set_rtc_mmss(unsigned long nowtime)
 {
        D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime));
index dfb8110..1746a2b 100644 (file)
@@ -132,4 +132,19 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        flush_write_buffers();
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif  /* _ASM_DMA_MAPPING_H */
index 84dd040..1a15f81 100644 (file)
@@ -57,7 +57,7 @@ extern void smp_local_timer_interrupt(void);
 
 static unsigned long latch;
 
-u32 arch_gettimeoffset(void)
+static u32 m32r_gettimeoffset(void)
 {
        unsigned long  elapsed_time = 0;  /* [us] */
 
@@ -165,6 +165,8 @@ void read_persistent_clock(struct timespec *ts)
 
 void __init time_init(void)
 {
+       arch_gettimeoffset = m32r_gettimeoffset;
+
 #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
        || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
        || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
index ee01b7a..b819390 100644 (file)
@@ -95,7 +95,7 @@ static void amiga_sched_init(irq_handler_t handler);
 static void amiga_get_model(char *model);
 static void amiga_get_hardware_list(struct seq_file *m);
 /* amiga specific timer functions */
-static unsigned long amiga_gettimeoffset(void);
+static u32 amiga_gettimeoffset(void);
 extern void amiga_mksound(unsigned int count, unsigned int ticks);
 static void amiga_reset(void);
 extern void amiga_init_sound(void);
@@ -377,7 +377,7 @@ void __init config_amiga(void)
        mach_init_IRQ        = amiga_init_IRQ;
        mach_get_model       = amiga_get_model;
        mach_get_hardware_list = amiga_get_hardware_list;
-       mach_gettimeoffset   = amiga_gettimeoffset;
+       arch_gettimeoffset   = amiga_gettimeoffset;
 
        /*
         * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
@@ -482,10 +482,10 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-static unsigned long amiga_gettimeoffset(void)
+static u32 amiga_gettimeoffset(void)
 {
        unsigned short hi, lo, hi2;
-       unsigned long ticks, offset = 0;
+       u32 ticks, offset = 0;
 
        /* read CIA B timer A current value */
        hi  = ciab.tahi;
@@ -507,7 +507,7 @@ static unsigned long amiga_gettimeoffset(void)
        ticks = jiffy_ticks - ticks;
        ticks = (10000 * ticks) / jiffy_ticks;
 
-       return ticks + offset;
+       return (ticks + offset) * 1000;
 }
 
 static void amiga_reset(void)  __noreturn;
index f5565d6..3ea56b9 100644 (file)
@@ -26,7 +26,7 @@ u_long apollo_model;
 
 extern void dn_sched_init(irq_handler_t handler);
 extern void dn_init_IRQ(void);
-extern unsigned long dn_gettimeoffset(void);
+extern u32 dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern int dn_dummy_set_clock_mmss(unsigned long);
 extern void dn_dummy_reset(void);
@@ -151,7 +151,7 @@ void __init config_apollo(void)
 
        mach_sched_init=dn_sched_init; /* */
        mach_init_IRQ=dn_init_IRQ;
-       mach_gettimeoffset   = dn_gettimeoffset;
+       arch_gettimeoffset   = dn_gettimeoffset;
        mach_max_dma_address = 0xffffffff;
        mach_hwclk           = dn_dummy_hwclk; /* */
        mach_set_clock_mmss  = dn_dummy_set_clock_mmss; /* */
@@ -203,10 +203,9 @@ void dn_sched_init(irq_handler_t timer_routine)
                pr_err("Couldn't register timer interrupt\n");
 }
 
-unsigned long dn_gettimeoffset(void) {
-
+u32 dn_gettimeoffset(void)
+{
        return 0xdeadbeef;
-
 }
 
 int dn_dummy_hwclk(int op, struct rtc_time *t) {
index d8eb327..037c11c 100644 (file)
@@ -74,7 +74,7 @@ static void atari_heartbeat(int on);
 
 /* atari specific timer functions (in time.c) */
 extern void atari_sched_init(irq_handler_t);
-extern unsigned long atari_gettimeoffset (void);
+extern u32 atari_gettimeoffset(void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
 extern int atari_mste_set_clock_mmss (unsigned long);
@@ -204,7 +204,7 @@ void __init config_atari(void)
        mach_init_IRQ        = atari_init_IRQ;
        mach_get_model   = atari_get_model;
        mach_get_hardware_list = atari_get_hardware_list;
-       mach_gettimeoffset   = atari_gettimeoffset;
+       arch_gettimeoffset   = atari_gettimeoffset;
        mach_reset           = atari_reset;
        mach_max_dma_address = 0xffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
index c0cc68a..da8f981 100644 (file)
@@ -42,9 +42,9 @@ atari_sched_init(irq_handler_t timer_routine)
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-unsigned long atari_gettimeoffset (void)
+u32 atari_gettimeoffset(void)
 {
-  unsigned long ticks, offset = 0;
+  u32 ticks, offset = 0;
 
   /* read MFP timer C current value */
   ticks = st_mfp.tim_dt_c;
@@ -57,7 +57,7 @@ unsigned long atari_gettimeoffset (void)
   ticks = INT_TICKS - ticks;
   ticks = ticks * 10000L / INT_TICKS;
 
-  return ticks + offset;
+  return (ticks + offset) * 1000;
 }
 
 
index 0bf850a..8943aa4 100644 (file)
@@ -38,7 +38,7 @@
 
 static void bvme6000_get_model(char *model);
 extern void bvme6000_sched_init(irq_handler_t handler);
-extern unsigned long bvme6000_gettimeoffset (void);
+extern u32 bvme6000_gettimeoffset(void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
 extern void bvme6000_reset (void);
@@ -110,7 +110,7 @@ void __init config_bvme6000(void)
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = bvme6000_sched_init;
     mach_init_IRQ        = bvme6000_init_IRQ;
-    mach_gettimeoffset   = bvme6000_gettimeoffset;
+    arch_gettimeoffset   = bvme6000_gettimeoffset;
     mach_hwclk           = bvme6000_hwclk;
     mach_set_clock_mmss         = bvme6000_set_clock_mmss;
     mach_reset          = bvme6000_reset;
@@ -216,13 +216,13 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
  * results...
  */
 
-unsigned long bvme6000_gettimeoffset (void)
+u32 bvme6000_gettimeoffset(void)
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
     unsigned char msr = rtc->msr & 0xc0;
     unsigned char t1int, t1op;
-    unsigned long v = 800000, ov;
+    u32 v = 800000, ov;
 
     rtc->msr = 0;      /* Ensure timer registers accessible */
 
@@ -246,7 +246,7 @@ unsigned long bvme6000_gettimeoffset (void)
        v += 10000;                     /* Int pending, + 10ms */
     rtc->msr = msr;
 
-    return v;
+    return v * 1000;
 }
 
 /*
index bf16af1..b7609f7 100644 (file)
@@ -251,7 +251,7 @@ void __init config_hp300(void)
        mach_sched_init      = hp300_sched_init;
        mach_init_IRQ        = hp300_init_IRQ;
        mach_get_model       = hp300_get_model;
-       mach_gettimeoffset   = hp300_gettimeoffset;
+       arch_gettimeoffset   = hp300_gettimeoffset;
        mach_hwclk           = hp300_hwclk;
        mach_get_ss          = hp300_get_ss;
        mach_reset           = hp300_reset;
index 29a71be..749543b 100644 (file)
@@ -46,7 +46,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id)
        return vector(irq, NULL);
 }
 
-unsigned long hp300_gettimeoffset(void)
+u32 hp300_gettimeoffset(void)
 {
   /* Read current timer 1 value */
   unsigned char lsb, msb1, msb2;
@@ -59,7 +59,7 @@ unsigned long hp300_gettimeoffset(void)
     /* A carry happened while we were reading.  Read it again */
     lsb = in_8(CLOCKBASE + 7);
   ticks = INTVAL - ((msb2 << 8) | lsb);
-  return (USECS_PER_JIFFY * ticks) / INTVAL;
+  return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
 }
 
 void __init hp300_sched_init(irq_handler_t vector)
index 7b98242..f5583ec 100644 (file)
@@ -1,2 +1,2 @@
 extern void hp300_sched_init(irq_handler_t vector);
-extern unsigned long hp300_gettimeoffset(void);
+extern u32 hp300_gettimeoffset(void);
index 3e6b844..292805f 100644 (file)
@@ -115,4 +115,14 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t handle)
 #include <asm-generic/dma-mapping-broken.h>
 #endif
 
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+                          void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
 #endif  /* _M68K_DMA_MAPPING_H */
index 825c1c8..953ca21 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
+#include <linux/time.h>
 
 struct pt_regs;
 struct mktime;
@@ -16,7 +17,6 @@ extern void (*mach_init_IRQ) (void);
 extern void (*mach_get_model) (char *model);
 extern void (*mach_get_hardware_list) (struct seq_file *m);
 /* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
 extern int (*mach_hwclk)(int, struct rtc_time*);
 extern unsigned int (*mach_get_ss)(void);
 extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
index d872ce4..80cfbe5 100644 (file)
@@ -84,7 +84,6 @@ void (*mach_init_IRQ) (void) __initdata = NULL;
 void (*mach_get_model) (char *model);
 void (*mach_get_hardware_list) (struct seq_file *m);
 /* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
 int (*mach_hwclk) (int, struct rtc_time*);
 EXPORT_SYMBOL(mach_hwclk);
 int (*mach_set_clock_mmss) (unsigned long);
index 5d0bcaa..bea6bcf 100644 (file)
@@ -80,18 +80,8 @@ void read_persistent_clock(struct timespec *ts)
        }
 }
 
-void __init time_init(void)
-{
-       mach_sched_init(timer_interrupt);
-}
-
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
 
-u32 arch_gettimeoffset(void)
-{
-       return mach_gettimeoffset() * 1000;
-}
-
 static int __init rtc_init(void)
 {
        struct platform_device *pdev;
@@ -106,3 +96,8 @@ static int __init rtc_init(void)
 module_init(rtc_init);
 
 #endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
+
+void __init time_init(void)
+{
+       mach_sched_init(timer_interrupt);
+}
index d9f62e0..afb95d5 100644 (file)
@@ -52,7 +52,7 @@ struct mac_booter_data mac_bi_data;
 static unsigned long mac_orig_videoaddr;
 
 /* Mac specific timer functions */
-extern unsigned long mac_gettimeoffset(void);
+extern u32 mac_gettimeoffset(void);
 extern int mac_hwclk(int, struct rtc_time *);
 extern int mac_set_clock_mmss(unsigned long);
 extern void iop_preinit(void);
@@ -177,7 +177,7 @@ void __init config_mac(void)
        mach_sched_init = mac_sched_init;
        mach_init_IRQ = mac_init_IRQ;
        mach_get_model = mac_get_model;
-       mach_gettimeoffset = mac_gettimeoffset;
+       arch_gettimeoffset = mac_gettimeoffset;
        mach_hwclk = mac_hwclk;
        mach_set_clock_mmss = mac_set_clock_mmss;
        mach_reset = mac_reset;
index 2d85662..5d1458b 100644 (file)
@@ -327,7 +327,7 @@ void via_debug_dump(void)
  * TBI: get time offset between scheduling timer ticks
  */
 
-unsigned long mac_gettimeoffset (void)
+u32 mac_gettimeoffset(void)
 {
        unsigned long ticks, offset = 0;
 
@@ -341,7 +341,7 @@ unsigned long mac_gettimeoffset (void)
        ticks = MAC_CLOCK_TICK - ticks;
        ticks = ticks * 10000L / MAC_CLOCK_TICK;
 
-       return ticks + offset;
+       return (ticks + offset) * 1000;
 }
 
 /*
index a41c091..1c62628 100644 (file)
@@ -37,7 +37,7 @@
 
 static void mvme147_get_model(char *model);
 extern void mvme147_sched_init(irq_handler_t handler);
-extern unsigned long mvme147_gettimeoffset (void);
+extern u32 mvme147_gettimeoffset(void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
 extern void mvme147_reset (void);
@@ -88,7 +88,7 @@ void __init config_mvme147(void)
        mach_max_dma_address    = 0x01000000;
        mach_sched_init         = mvme147_sched_init;
        mach_init_IRQ           = mvme147_init_IRQ;
-       mach_gettimeoffset      = mvme147_gettimeoffset;
+       arch_gettimeoffset      = mvme147_gettimeoffset;
        mach_hwclk              = mvme147_hwclk;
        mach_set_clock_mmss     = mvme147_set_clock_mmss;
        mach_reset              = mvme147_reset;
@@ -127,7 +127,7 @@ void mvme147_sched_init (irq_handler_t timer_routine)
 
 /* This is always executed with interrupts disabled.  */
 /* XXX There are race hazards in this code XXX */
-unsigned long mvme147_gettimeoffset (void)
+u32 mvme147_gettimeoffset(void)
 {
        volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
        unsigned short n;
@@ -137,7 +137,7 @@ unsigned long mvme147_gettimeoffset (void)
                n = *cp;
 
        n -= PCC_TIMER_PRELOAD;
-       return (unsigned long)n * 25 / 4;
+       return ((unsigned long)n * 25 / 4) * 1000;
 }
 
 static int bcd2int (unsigned char b)
index b6d7d8a..080a342 100644 (file)
@@ -43,7 +43,7 @@ static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
 
 static void mvme16x_get_model(char *model);
 extern void mvme16x_sched_init(irq_handler_t handler);
-extern unsigned long mvme16x_gettimeoffset (void);
+extern u32 mvme16x_gettimeoffset(void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
 extern void mvme16x_reset (void);
@@ -289,7 +289,7 @@ void __init config_mvme16x(void)
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = mvme16x_sched_init;
     mach_init_IRQ        = mvme16x_init_IRQ;
-    mach_gettimeoffset   = mvme16x_gettimeoffset;
+    arch_gettimeoffset   = mvme16x_gettimeoffset;
     mach_hwclk           = mvme16x_hwclk;
     mach_set_clock_mmss         = mvme16x_set_clock_mmss;
     mach_reset          = mvme16x_reset;
@@ -405,9 +405,9 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
 
 
 /* This is always executed with interrupts disabled.  */
-unsigned long mvme16x_gettimeoffset (void)
+u32 mvme16x_gettimeoffset(void)
 {
-    return (*(volatile unsigned long *)0xfff42008);
+    return (*(volatile u32 *)0xfff42008) * 1000;
 }
 
 int bcd2int (unsigned char b)
index 1adb5b7..658542b 100644 (file)
@@ -40,7 +40,7 @@ extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 extern void q40_sched_init(irq_handler_t handler);
 
-static unsigned long q40_gettimeoffset(void);
+static u32 q40_gettimeoffset(void);
 static int q40_hwclk(int, struct rtc_time *);
 static unsigned int q40_get_ss(void);
 static int q40_set_clock_mmss(unsigned long);
@@ -170,7 +170,7 @@ void __init config_q40(void)
        mach_sched_init = q40_sched_init;
 
        mach_init_IRQ = q40_init_IRQ;
-       mach_gettimeoffset = q40_gettimeoffset;
+       arch_gettimeoffset = q40_gettimeoffset;
        mach_hwclk = q40_hwclk;
        mach_get_ss = q40_get_ss;
        mach_get_rtc_pll = q40_get_rtc_pll;
@@ -204,9 +204,9 @@ int q40_parse_bootinfo(const struct bi_record *rec)
 }
 
 
-static unsigned long q40_gettimeoffset(void)
+static u32 q40_gettimeoffset(void)
 {
-       return 5000 * (ql_ticks != 0);
+       return 5000 * (ql_ticks != 0) * 1000;
 }
 
 
index 2ca25bd..f59ec58 100644 (file)
@@ -36,7 +36,7 @@
 
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
-extern unsigned long sun3_gettimeoffset(void);
+extern u32 sun3_gettimeoffset(void);
 static void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
 extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -141,7 +141,7 @@ void __init config_sun3(void)
         mach_sched_init      =  sun3_sched_init;
         mach_init_IRQ        =  sun3_init_IRQ;
         mach_reset           =  sun3_reboot;
-       mach_gettimeoffset   =  sun3_gettimeoffset;
+       arch_gettimeoffset   =  sun3_gettimeoffset;
        mach_get_model       =  sun3_get_model;
        mach_hwclk           =  sun3_hwclk;
        mach_halt            =  sun3_halt;
index 94fe801..889829e 100644 (file)
@@ -23,9 +23,9 @@
 #define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
 
 /* does this need to be implemented? */
-unsigned long sun3_gettimeoffset(void)
+u32 sun3_gettimeoffset(void)
 {
-  return 1;
+  return 1000;
 }
 
 
index dd306c8..0532d64 100644 (file)
@@ -48,7 +48,7 @@ void __init config_sun3x(void)
        mach_sched_init      = sun3x_sched_init;
        mach_init_IRQ        = sun3_init_IRQ;
 
-       mach_gettimeoffset   = sun3x_gettimeoffset;
+       arch_gettimeoffset   = sun3x_gettimeoffset;
        mach_reset           = sun3x_reboot;
 
        mach_hwclk           = sun3x_hwclk;
index 1d0a724..c8eb08a 100644 (file)
@@ -71,7 +71,7 @@ int sun3x_hwclk(int set, struct rtc_time *t)
        return 0;
 }
 /* Not much we can do here */
-unsigned long sun3x_gettimeoffset (void)
+u32 sun3x_gettimeoffset(void)
 {
     return 0L;
 }
index 6909e12..a4f9126 100644 (file)
@@ -2,7 +2,7 @@
 #define SUN3X_TIME_H
 
 extern int sun3x_hwclk(int set, struct rtc_time *t);
-unsigned long sun3x_gettimeoffset (void);
+u32 sun3x_gettimeoffset(void);
 void sun3x_sched_init(irq_handler_t vector);
 
 struct mostek_dt {
index d7af29f..ba61192 100644 (file)
@@ -8,8 +8,10 @@ config BCM47XX_SSB
        select SSB_DRIVER_EXTIF
        select SSB_EMBEDDED
        select SSB_B43_PCI_BRIDGE if PCI
+       select SSB_DRIVER_PCICORE if PCI
        select SSB_PCICORE_HOSTMODE if PCI
        select SSB_DRIVER_GPIO
+       select GPIOLIB
        default y
        help
         Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -25,6 +27,7 @@ config BCM47XX_BCMA
        select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
        select BCMA_DRIVER_GPIO
+       select GPIOLIB
        default y
        help
         Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
index 9f883bf..33b7214 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/compiler.h>
 #include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
@@ -285,22 +286,22 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
  */
 static void fault_in(uint64_t addr, int len)
 {
-       volatile char *ptr;
-       volatile char dummy;
+       char *ptr;
+
        /*
         * Adjust addr and length so we get all cache lines even for
         * small ranges spanning two cache lines.
         */
        len += addr & CVMX_CACHE_LINE_MASK;
        addr &= ~CVMX_CACHE_LINE_MASK;
-       ptr = (volatile char *)cvmx_phys_to_ptr(addr);
+       ptr = cvmx_phys_to_ptr(addr);
        /*
         * Invalidate L1 cache to make sure all loads result in data
         * being in L2.
         */
        CVMX_DCACHE_INVALIDATE;
        while (len > 0) {
-               dummy += *ptr;
+               ACCESS_ONCE(*ptr);
                len -= CVMX_CACHE_LINE_SIZE;
                ptr += CVMX_CACHE_LINE_SIZE;
        }
index e9bfc08..7bfad05 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/mipsregs.h>
 
 #define DSP_DEFAULT    0x00000000
-#define DSP_MASK       0x3ff
+#define DSP_MASK       0x3f
 
 #define __enable_dsp_hazard()                                          \
 do {                                                                   \
index ab84064..33c34ad 100644 (file)
@@ -353,6 +353,7 @@ union mips_instruction {
        struct u_format u_format;
        struct c_format c_format;
        struct r_format r_format;
+       struct p_format p_format;
        struct f_format f_format;
        struct ma_format ma_format;
        struct b_format b_format;
index edaa06d..e410df4 100644 (file)
@@ -21,4 +21,4 @@
 #define R10000_LLSC_WAR                        0
 #define MIPS34K_MISSED_ITLB_WAR                0
 
-#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */
+#endif /* __ASM_MIPS_MACH_PNX833X_WAR_H */
index c631910..013d5f7 100644 (file)
@@ -230,6 +230,7 @@ static inline void pud_clear(pud_t *pudp)
 #else
 #define pte_pfn(x)             ((unsigned long)((x).pte >> _PFN_SHIFT))
 #define pfn_pte(pfn, prot)     __pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)     __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
 #endif
 
 #define __pgd_offset(address)  pgd_index(address)
index a1a0452..77d4fb3 100644 (file)
@@ -3,6 +3,7 @@ include include/uapi/asm-generic/Kbuild.asm
 
 header-y += auxvec.h
 header-y += bitsperlong.h
+header-y += break.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += errno.h
index 6a2d758..83fa146 100644 (file)
 #define MCOUNT_OFFSET_INSNS 4
 #endif
 
+/* Arch override because MIPS doesn't need to run this from stop_machine() */
+void arch_ftrace_update_code(int command)
+{
+       ftrace_modify_all_code(command);
+}
+
 /*
  * Check if the address is in kernel space
  *
@@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
        return 0;
 }
 
+#ifndef CONFIG_64BIT
+static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
+                               unsigned int new_code2)
+{
+       int faulted;
+
+       safe_store_code(new_code1, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+       ip += 4;
+       safe_store_code(new_code2, ip, faulted);
+       if (unlikely(faulted))
+               return -EFAULT;
+       flush_icache_range(ip, ip + 8); /* original ip + 12 */
+       return 0;
+}
+#endif
+
 /*
  * The details about the calling site of mcount on MIPS
  *
@@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod,
         * needed.
         */
        new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
-
+#ifdef CONFIG_64BIT
        return ftrace_modify_code(ip, new);
+#else
+       /*
+        * On 32 bit MIPS platforms, gcc adds a stack adjust
+        * instruction in the delay slot after the branch to
+        * mcount and expects mcount to restore the sp on return.
+        * This is based on a legacy API and does nothing but
+        * waste instructions so it's being removed at runtime.
+        */
+       return ftrace_modify_code_2(ip, new, INSN_NOP);
+#endif
 }
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
index 4c968e7..1658676 100644 (file)
@@ -46,9 +46,8 @@
        PTR_L   a5, PT_R9(sp)
        PTR_L   a6, PT_R10(sp)
        PTR_L   a7, PT_R11(sp)
-       PTR_ADDIU       sp, PT_SIZE
 #else
-       PTR_ADDIU       sp, (PT_SIZE + 8)
+       PTR_ADDIU       sp, PT_SIZE
 #endif
 .endm
 
@@ -69,7 +68,9 @@ NESTED(ftrace_caller, PT_SIZE, ra)
        .globl _mcount
 _mcount:
        b       ftrace_stub
-        nop
+       addiu sp,sp,8
+
+       /* When tracing is activated, it calls ftrace_caller+8 (aka here) */
        lw      t1, function_trace_stop
        bnez    t1, ftrace_stub
         nop
index eec690a..147cec1 100644 (file)
@@ -705,7 +705,7 @@ static int vpe_run(struct vpe * v)
 
                        printk(KERN_WARNING
                               "VPE loader: TC %d is already in use.\n",
-                               t->index);
+                              v->tc->index);
                        return -ENOEXEC;
                }
        } else {
index f36acd1..a7935bf 100644 (file)
@@ -408,7 +408,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
 #endif
 
        /* tell oprofile which irq to use */
-       cp0_perfcount_irq = LTQ_PERF_IRQ;
+       cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
        /*
         * if the timer irq is not one of the mips irqs we need to
index dc81ca8..288f795 100644 (file)
@@ -21,7 +21,7 @@ void __delay(unsigned long loops)
        "       .set    noreorder                               \n"
        "       .align  3                                       \n"
        "1:     bnez    %0, 1b                                  \n"
-#if __SIZEOF_LONG__ == 4
+#if BITS_PER_LONG == 32
        "       subu    %0, 1                                   \n"
 #else
        "       dsubu   %0, 1                                   \n"
index 7657fd2..cacfd31 100644 (file)
@@ -190,9 +190,3 @@ void __iounmap(const volatile void __iomem *addr)
 
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(__iounmap);
-
-int __virt_addr_valid(const volatile void *kaddr)
-{
-       return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
-}
-EXPORT_SYMBOL_GPL(__virt_addr_valid);
index d9be754..7e5fe27 100644 (file)
@@ -192,3 +192,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 
        return ret;
 }
+
+int __virt_addr_valid(const volatile void *kaddr)
+{
+       return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+}
+EXPORT_SYMBOL_GPL(__virt_addr_valid);
index 4e7f49d..c5ce699 100644 (file)
@@ -193,8 +193,11 @@ static void nlm_init_node(void)
 
 void __init prom_init(void)
 {
-       int i, *argv, *envp;            /* passed as 32 bit ptrs */
+       int *argv, *envp;               /* passed as 32 bit ptrs */
        struct psb_info *prom_infop;
+#ifdef CONFIG_SMP
+       int i;
+#endif
 
        /* truncate to 32 bit and sign extend all args */
        argv = (int *)(long)(int)fw_arg1;
index 1552522..6eaa4f2 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/mach-ath79/pci.h>
 
 #define AR71XX_PCI_MEM_BASE    0x10000000
-#define AR71XX_PCI_MEM_SIZE    0x08000000
+#define AR71XX_PCI_MEM_SIZE    0x07000000
 
 #define AR71XX_PCI_WIN0_OFFS           0x10000000
 #define AR71XX_PCI_WIN1_OFFS           0x11000000
index 86d77a6..c11c75b 100644 (file)
@@ -21,7 +21,7 @@
 #define AR724X_PCI_CTRL_SIZE   0x100
 
 #define AR724X_PCI_MEM_BASE    0x10000000
-#define AR724X_PCI_MEM_SIZE    0x08000000
+#define AR724X_PCI_MEM_SIZE    0x04000000
 
 #define AR724X_PCI_REG_RESET           0x18
 #define AR724X_PCI_REG_INT_STATUS      0x4c
index c1be439..a18abfc 100644 (file)
@@ -168,4 +168,19 @@ void dma_cache_sync(void *vaddr, size_t size,
        mn10300_dcache_flush_inv();
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif
index 467bbd5..106b395 100644 (file)
@@ -238,4 +238,19 @@ void * sba_get_iommu(struct parisc_device *dev);
 /* At the moment, we panic on error for IOMMU resource exaustion */
 #define dma_mapping_error(dev, x)      0
 
+/* This API cannot be supported on PA-RISC */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif
index 5658508..7443481 100644 (file)
@@ -115,11 +115,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        sldi    r29,r5,SID_SHIFT - VPN_SHIFT
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
-
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-12,48          /* (ea >> 12) & 0xffff */
-       xor     r28,r5,r0
+       /*
+        * Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
+        */
+       rldicl  r0,r3,64-12,48
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
@@ -130,11 +132,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        /*
         * calculate hash value for primary slot and
         * store it in r28 for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 =  (va >> 12) & ((1ul << (40 - 12)) -1) */
+       rldicl  r0,r3,64-12,36
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -407,11 +410,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
         */
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
-
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-12,48          /* (ea >> 12) & 0xffff */
-       xor     r28,r5,r0
+       /*
+        * Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
+        */
+       rldicl  r0,r3,64-12,48
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
@@ -426,11 +431,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        /*
         * Calculate hash value for primary slot and
         * store it in r28  for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-12,36          /* (ea >> 12) & 0xfffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
+       rldicl  r0,r3,64-12,36
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
@@ -752,25 +758,27 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
        or      r29,r28,r29
 
-       /* Calculate hash value for primary slot and store it in r28 */
-       rldicl  r5,r5,0,25              /* vsid & 0x0000007fffffffff */
-       rldicl  r0,r3,64-16,52          /* (ea >> 16) & 0xfff */
-       xor     r28,r5,r0
+       /* Calculate hash value for primary slot and store it in r28
+        * r3 = va, r5 = vsid
+        * r0 = (va >> 16) & ((1ul << (28 - 16)) -1)
+        */
+       rldicl  r0,r3,64-16,52
+       xor     r28,r5,r0               /* hash */
        b       4f
 
 3:     /* Calc vpn and put it in r29 */
        sldi    r29,r5,SID_SHIFT_1T - VPN_SHIFT
        rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
        or      r29,r28,r29
-
        /*
         * calculate hash value for primary slot and
         * store it in r28 for 1T segment
+        * r3 = va, r5 = vsid
         */
-       rldic   r28,r5,25,25            /* (vsid << 25) & 0x7fffffffff */
-       clrldi  r5,r5,40                /* vsid & 0xffffff */
-       rldicl  r0,r3,64-16,40          /* (ea >> 16) & 0xffffff */
-       xor     r28,r28,r5
+       sldi    r28,r5,25               /* vsid << 25 */
+       /* r0 = (va >> 16) & ((1ul << (40 - 16)) -1) */
+       rldicl  r0,r3,64-16,40
+       xor     r28,r28,r5              /* vsid ^ ( vsid << 25) */
        xor     r28,r28,r0              /* hash */
 
        /* Convert linux PTE bits into HW equivalents */
index 102ff7c..142c4ce 100644 (file)
@@ -207,7 +207,7 @@ sysexit_from_sys_call:
        testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jnz ia32_ret_from_sys_call
        TRACE_IRQS_ON
-       sti
+       ENABLE_INTERRUPTS(CLBR_NONE)
        movl %eax,%esi          /* second arg, syscall return value */
        cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
        jbe 1f
@@ -217,7 +217,7 @@ sysexit_from_sys_call:
        call __audit_syscall_exit
        movq RAX-ARGOFFSET(%rsp),%rax   /* reload syscall return value */
        movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
-       cli
+       DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jz \exit
index fe9edec..84c1309 100644 (file)
@@ -298,8 +298,7 @@ struct _cache_attr {
                         unsigned int);
 };
 
-#ifdef CONFIG_AMD_NB
-
+#if defined(CONFIG_AMD_NB) && defined(CONFIG_SYSFS)
 /*
  * L3 cache descriptors
  */
@@ -524,9 +523,9 @@ store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
 static struct _cache_attr subcaches =
        __ATTR(subcaches, 0644, show_subcaches, store_subcaches);
 
-#else  /* CONFIG_AMD_NB */
+#else
 #define amd_init_l3_cache(x, y)
-#endif /* CONFIG_AMD_NB */
+#endif  /* CONFIG_AMD_NB && CONFIG_SYSFS */
 
 static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
index 93b9e11..4914e94 100644 (file)
@@ -2019,7 +2019,10 @@ __init int intel_pmu_init(void)
                break;
 
        case 28: /* Atom */
-       case 54: /* Cedariew */
+       case 38: /* Lincroft */
+       case 39: /* Penwell */
+       case 53: /* Cloverview */
+       case 54: /* Cedarview */
                memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
@@ -2084,6 +2087,7 @@ __init int intel_pmu_init(void)
                pr_cont("SandyBridge events, ");
                break;
        case 58: /* IvyBridge */
+       case 62: /* IvyBridge EP */
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
index f2af39f..4820c23 100644 (file)
@@ -19,7 +19,7 @@ static const u64 p6_perfmon_event_map[] =
 
 };
 
-static __initconst u64 p6_hw_cache_event_ids
+static u64 p6_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
                                [PERF_COUNT_HW_CACHE_RESULT_MAX] =
index cc2f8c1..872eb60 100644 (file)
@@ -55,7 +55,7 @@ static FILE           *input_file;    /* Input file name */
 static void usage(const char *err)
 {
        if (err)
-               fprintf(stderr, "Error: %s\n\n", err);
+               fprintf(stderr, "%s: Error: %s\n\n", prog, err);
        fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog);
        fprintf(stderr, "\t-y   64bit mode\n");
        fprintf(stderr, "\t-n   32bit mode\n");
@@ -269,7 +269,13 @@ int main(int argc, char **argv)
                insns++;
        }
 
-       fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed);
+       fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+               prog,
+               (errors) ? "Failure" : "Success",
+               insns,
+               (input_file) ? "given" : "random",
+               errors,
+               seed);
 
        return errors ? 1 : 0;
 }
index 4acb5fe..172a02a 100644 (file)
@@ -170,4 +170,19 @@ dma_cache_sync(struct device *dev, void *vaddr, size_t size,
        consistent_sync(vaddr, size, direction);
 }
 
+/* Not supported for now */
+static inline int dma_mmap_coherent(struct device *dev,
+                                   struct vm_area_struct *vma, void *cpu_addr,
+                                   dma_addr_t dma_addr, size_t size)
+{
+       return -EINVAL;
+}
+
+static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
+                                 void *cpu_addr, dma_addr_t dma_addr,
+                                 size_t size)
+{
+       return -EINVAL;
+}
+
 #endif /* _XTENSA_DMA_MAPPING_H */
index 9a289d7..3993ebf 100644 (file)
@@ -35,6 +35,8 @@ static DEFINE_IDR(ext_devt_idr);
 
 static struct device_type disk_type;
 
+static void disk_check_events(struct disk_events *ev,
+                             unsigned int *clearing_ptr);
 static void disk_alloc_events(struct gendisk *disk);
 static void disk_add_events(struct gendisk *disk);
 static void disk_del_events(struct gendisk *disk);
@@ -1549,6 +1551,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
        const struct block_device_operations *bdops = disk->fops;
        struct disk_events *ev = disk->ev;
        unsigned int pending;
+       unsigned int clearing = mask;
 
        if (!ev) {
                /* for drivers still using the old ->media_changed method */
@@ -1558,34 +1561,53 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
                return 0;
        }
 
-       /* tell the workfn about the events being cleared */
+       disk_block_events(disk);
+
+       /*
+        * store the union of mask and ev->clearing on the stack so that the
+        * race with disk_flush_events does not cause ambiguity (ev->clearing
+        * can still be modified even if events are blocked).
+        */
        spin_lock_irq(&ev->lock);
-       ev->clearing |= mask;
+       clearing |= ev->clearing;
+       ev->clearing = 0;
        spin_unlock_irq(&ev->lock);
 
-       /* uncondtionally schedule event check and wait for it to finish */
-       disk_block_events(disk);
-       queue_delayed_work(system_freezable_wq, &ev->dwork, 0);
-       flush_delayed_work(&ev->dwork);
-       __disk_unblock_events(disk, false);
+       disk_check_events(ev, &clearing);
+       /*
+        * if ev->clearing is not 0, the disk_flush_events got called in the
+        * middle of this function, so we want to run the workfn without delay.
+        */
+       __disk_unblock_events(disk, ev->clearing ? true : false);
 
        /* then, fetch and clear pending events */
        spin_lock_irq(&ev->lock);
-       WARN_ON_ONCE(ev->clearing & mask);      /* cleared by workfn */
        pending = ev->pending & mask;
        ev->pending &= ~mask;
        spin_unlock_irq(&ev->lock);
+       WARN_ON_ONCE(clearing & mask);
 
        return pending;
 }
 
+/*
+ * Separate this part out so that a different pointer for clearing_ptr can be
+ * passed in for disk_clear_events.
+ */
 static void disk_events_workfn(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
        struct disk_events *ev = container_of(dwork, struct disk_events, dwork);
+
+       disk_check_events(ev, &ev->clearing);
+}
+
+static void disk_check_events(struct disk_events *ev,
+                             unsigned int *clearing_ptr)
+{
        struct gendisk *disk = ev->disk;
        char *envp[ARRAY_SIZE(disk_uevents) + 1] = { };
-       unsigned int clearing = ev->clearing;
+       unsigned int clearing = *clearing_ptr;
        unsigned int events;
        unsigned long intv;
        int nr_events = 0, i;
@@ -1598,7 +1620,7 @@ static void disk_events_workfn(struct work_struct *work)
 
        events &= ~ev->pending;
        ev->pending |= events;
-       ev->clearing &= ~clearing;
+       *clearing_ptr &= ~clearing;
 
        intv = disk_events_poll_jiffies(disk);
        if (!ev->block && intv)
index 6a0955e..53ecac5 100644 (file)
@@ -636,82 +636,82 @@ struct rx_buf_desc {
 #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE  
 #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE  
 
-typedef volatile u_int  freg_t;
+typedef volatile u_int ffreg_t;
 typedef u_int   rreg_t;
 
 typedef struct _ffredn_t {
-        freg_t  idlehead_high;  /* Idle cell header (high)              */
-        freg_t  idlehead_low;   /* Idle cell header (low)               */
-        freg_t  maxrate;        /* Maximum rate                         */
-        freg_t  stparms;        /* Traffic Management Parameters        */
-        freg_t  abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */
-        freg_t  rm_type;        /*                                      */
-        u_int   filler5[0x17 - 0x06];
-        freg_t  cmd_reg;        /* Command register                     */
-        u_int   filler18[0x20 - 0x18];
-        freg_t  cbr_base;       /* CBR Pointer Base                     */
-        freg_t  vbr_base;       /* VBR Pointer Base                     */
-        freg_t  abr_base;       /* ABR Pointer Base                     */
-        freg_t  ubr_base;       /* UBR Pointer Base                     */
-        u_int   filler24;
-        freg_t  vbrwq_base;     /* VBR Wait Queue Base                  */
-        freg_t  abrwq_base;     /* ABR Wait Queue Base                  */
-        freg_t  ubrwq_base;     /* UBR Wait Queue Base                  */
-        freg_t  vct_base;       /* Main VC Table Base                   */
-        freg_t  vcte_base;      /* Extended Main VC Table Base          */
-        u_int   filler2a[0x2C - 0x2A];
-        freg_t  cbr_tab_beg;    /* CBR Table Begin                      */
-        freg_t  cbr_tab_end;    /* CBR Table End                        */
-        freg_t  cbr_pointer;    /* CBR Pointer                          */
-        u_int   filler2f[0x30 - 0x2F];
-        freg_t  prq_st_adr;     /* Packet Ready Queue Start Address     */
-        freg_t  prq_ed_adr;     /* Packet Ready Queue End Address       */
-        freg_t  prq_rd_ptr;     /* Packet Ready Queue read pointer      */
-        freg_t  prq_wr_ptr;     /* Packet Ready Queue write pointer     */
-        freg_t  tcq_st_adr;     /* Transmit Complete Queue Start Address*/
-        freg_t  tcq_ed_adr;     /* Transmit Complete Queue End Address  */
-        freg_t  tcq_rd_ptr;     /* Transmit Complete Queue read pointer */
-        freg_t  tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/
-        u_int   filler38[0x40 - 0x38];
-        freg_t  queue_base;     /* Base address for PRQ and TCQ         */
-        freg_t  desc_base;      /* Base address of descriptor table     */
-        u_int   filler42[0x45 - 0x42];
-        freg_t  mode_reg_0;     /* Mode register 0                      */
-        freg_t  mode_reg_1;     /* Mode register 1                      */
-        freg_t  intr_status_reg;/* Interrupt Status register            */
-        freg_t  mask_reg;       /* Mask Register                        */
-        freg_t  cell_ctr_high1; /* Total cell transfer count (high)     */
-        freg_t  cell_ctr_lo1;   /* Total cell transfer count (low)      */
-        freg_t  state_reg;      /* Status register                      */
-        u_int   filler4c[0x58 - 0x4c];
-        freg_t  curr_desc_num;  /* Contains the current descriptor num  */
-        freg_t  next_desc;      /* Next descriptor                      */
-        freg_t  next_vc;        /* Next VC                              */
-        u_int   filler5b[0x5d - 0x5b];
-        freg_t  present_slot_cnt;/* Present slot count                  */
-        u_int   filler5e[0x6a - 0x5e];
-        freg_t  new_desc_num;   /* New descriptor number                */
-        freg_t  new_vc;         /* New VC                               */
-        freg_t  sched_tbl_ptr;  /* Schedule table pointer               */
-        freg_t  vbrwq_wptr;     /* VBR wait queue write pointer         */
-        freg_t  vbrwq_rptr;     /* VBR wait queue read pointer          */
-        freg_t  abrwq_wptr;     /* ABR wait queue write pointer         */
-        freg_t  abrwq_rptr;     /* ABR wait queue read pointer          */
-        freg_t  ubrwq_wptr;     /* UBR wait queue write pointer         */
-        freg_t  ubrwq_rptr;     /* UBR wait queue read pointer          */
-        freg_t  cbr_vc;         /* CBR VC                               */
-        freg_t  vbr_sb_vc;      /* VBR SB VC                            */
-        freg_t  abr_sb_vc;      /* ABR SB VC                            */
-        freg_t  ubr_sb_vc;      /* UBR SB VC                            */
-        freg_t  vbr_next_link;  /* VBR next link                        */
-        freg_t  abr_next_link;  /* ABR next link                        */
-        freg_t  ubr_next_link;  /* UBR next link                        */
-        u_int   filler7a[0x7c-0x7a];
-        freg_t  out_rate_head;  /* Out of rate head                     */
-        u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */
-        freg_t  cell_ctr_high1_nc;/* Total cell transfer count (high)   */
-        freg_t  cell_ctr_lo1_nc;/* Total cell transfer count (low)      */
-        u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */
+       ffreg_t idlehead_high;  /* Idle cell header (high)              */
+       ffreg_t idlehead_low;   /* Idle cell header (low)               */
+       ffreg_t maxrate;        /* Maximum rate                         */
+       ffreg_t stparms;        /* Traffic Management Parameters        */
+       ffreg_t abrubr_abr;     /* ABRUBR Priority Byte 1, TCR Byte 0   */
+       ffreg_t rm_type;        /*                                      */
+       u_int   filler5[0x17 - 0x06];
+       ffreg_t cmd_reg;        /* Command register                     */
+       u_int   filler18[0x20 - 0x18];
+       ffreg_t cbr_base;       /* CBR Pointer Base                     */
+       ffreg_t vbr_base;       /* VBR Pointer Base                     */
+       ffreg_t abr_base;       /* ABR Pointer Base                     */
+       ffreg_t ubr_base;       /* UBR Pointer Base                     */
+       u_int   filler24;
+       ffreg_t vbrwq_base;     /* VBR Wait Queue Base                  */
+       ffreg_t abrwq_base;     /* ABR Wait Queue Base                  */
+       ffreg_t ubrwq_base;     /* UBR Wait Queue Base                  */
+       ffreg_t vct_base;       /* Main VC Table Base                   */
+       ffreg_t vcte_base;      /* Extended Main VC Table Base          */
+       u_int   filler2a[0x2C - 0x2A];
+       ffreg_t cbr_tab_beg;    /* CBR Table Begin                      */
+       ffreg_t cbr_tab_end;    /* CBR Table End                        */
+       ffreg_t cbr_pointer;    /* CBR Pointer                          */
+       u_int   filler2f[0x30 - 0x2F];
+       ffreg_t prq_st_adr;     /* Packet Ready Queue Start Address     */
+       ffreg_t prq_ed_adr;     /* Packet Ready Queue End Address       */
+       ffreg_t prq_rd_ptr;     /* Packet Ready Queue read pointer      */
+       ffreg_t prq_wr_ptr;     /* Packet Ready Queue write pointer     */
+       ffreg_t tcq_st_adr;     /* Transmit Complete Queue Start Address*/
+       ffreg_t tcq_ed_adr;     /* Transmit Complete Queue End Address  */
+       ffreg_t tcq_rd_ptr;     /* Transmit Complete Queue read pointer */
+       ffreg_t tcq_wr_ptr;     /* Transmit Complete Queue write pointer*/
+       u_int   filler38[0x40 - 0x38];
+       ffreg_t queue_base;     /* Base address for PRQ and TCQ         */
+       ffreg_t desc_base;      /* Base address of descriptor table     */
+       u_int   filler42[0x45 - 0x42];
+       ffreg_t mode_reg_0;     /* Mode register 0                      */
+       ffreg_t mode_reg_1;     /* Mode register 1                      */
+       ffreg_t intr_status_reg;/* Interrupt Status register            */
+       ffreg_t mask_reg;       /* Mask Register                        */
+       ffreg_t cell_ctr_high1; /* Total cell transfer count (high)     */
+       ffreg_t cell_ctr_lo1;   /* Total cell transfer count (low)      */
+       ffreg_t state_reg;      /* Status register                      */
+       u_int   filler4c[0x58 - 0x4c];
+       ffreg_t curr_desc_num;  /* Contains the current descriptor num  */
+       ffreg_t next_desc;      /* Next descriptor                      */
+       ffreg_t next_vc;        /* Next VC                              */
+       u_int   filler5b[0x5d - 0x5b];
+       ffreg_t present_slot_cnt;/* Present slot count                  */
+       u_int   filler5e[0x6a - 0x5e];
+       ffreg_t new_desc_num;   /* New descriptor number                */
+       ffreg_t new_vc;         /* New VC                               */
+       ffreg_t sched_tbl_ptr;  /* Schedule table pointer               */
+       ffreg_t vbrwq_wptr;     /* VBR wait queue write pointer         */
+       ffreg_t vbrwq_rptr;     /* VBR wait queue read pointer          */
+       ffreg_t abrwq_wptr;     /* ABR wait queue write pointer         */
+       ffreg_t abrwq_rptr;     /* ABR wait queue read pointer          */
+       ffreg_t ubrwq_wptr;     /* UBR wait queue write pointer         */
+       ffreg_t ubrwq_rptr;     /* UBR wait queue read pointer          */
+       ffreg_t cbr_vc;         /* CBR VC                               */
+       ffreg_t vbr_sb_vc;      /* VBR SB VC                            */
+       ffreg_t abr_sb_vc;      /* ABR SB VC                            */
+       ffreg_t ubr_sb_vc;      /* UBR SB VC                            */
+       ffreg_t vbr_next_link;  /* VBR next link                        */
+       ffreg_t abr_next_link;  /* ABR next link                        */
+       ffreg_t ubr_next_link;  /* UBR next link                        */
+       u_int   filler7a[0x7c-0x7a];
+       ffreg_t out_rate_head;  /* Out of rate head                     */
+       u_int   filler7d[0xca-0x7d]; /* pad out to full address space   */
+       ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high)   */
+       ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low)      */
+       u_int   fillercc[0x100-0xcc]; /* pad out to full address space   */
 } ffredn_t;
 
 typedef struct _rfredn_t {
index 19e3fbf..cb0c454 100644 (file)
@@ -94,11 +94,16 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #ifdef CONFIG_BCMA_DRIVER_GPIO
 /* driver_gpio.c */
 int bcma_gpio_init(struct bcma_drv_cc *cc);
+int bcma_gpio_unregister(struct bcma_drv_cc *cc);
 #else
 static inline int bcma_gpio_init(struct bcma_drv_cc *cc)
 {
        return -ENOTSUPP;
 }
+static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return 0;
+}
 #endif /* CONFIG_BCMA_DRIVER_GPIO */
 
 #endif
index dbda91e..1f0b83e 100644 (file)
@@ -21,7 +21,7 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
        struct bcma_bus *bus = cc->core->bus;
 
        if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
-           cc->core->id.rev != 0x38) {
+           cc->core->id.rev != 38) {
                bcma_err(bus, "NAND flash on unsupported board!\n");
                return -ENOTSUPP;
        }
index 9a6f585..71f755c 100644 (file)
@@ -96,3 +96,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
 
        return gpiochip_add(chip);
 }
+
+int bcma_gpio_unregister(struct bcma_drv_cc *cc)
+{
+       return gpiochip_remove(&cc->gpio);
+}
index 4a92f64..324f9de 100644 (file)
@@ -268,6 +268,13 @@ int bcma_bus_register(struct bcma_bus *bus)
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
        struct bcma_device *cores[3];
+       int err;
+
+       err = bcma_gpio_unregister(&bus->drv_cc);
+       if (err == -EBUSY)
+               bcma_err(bus, "Some GPIOs are still in use.\n");
+       else if (err)
+               bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
 
        cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
        cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
index f58a4a4..2b8303a 100644 (file)
@@ -168,7 +168,7 @@ static void wake_all_senders(struct drbd_tconn *tconn) {
 }
 
 /* must hold resource->req_lock */
-static void start_new_tl_epoch(struct drbd_tconn *tconn)
+void start_new_tl_epoch(struct drbd_tconn *tconn)
 {
        /* no point closing an epoch, if it is empty, anyways. */
        if (tconn->current_tle_writes == 0)
index 016de6b..c08d229 100644 (file)
@@ -267,6 +267,7 @@ struct bio_and_error {
        int error;
 };
 
+extern void start_new_tl_epoch(struct drbd_tconn *tconn);
 extern void drbd_req_destroy(struct kref *kref);
 extern void _req_may_be_done(struct drbd_request *req,
                struct bio_and_error *m);
index 53bf618..0fe220c 100644 (file)
@@ -931,6 +931,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
        enum drbd_state_rv rv = SS_SUCCESS;
        enum sanitize_state_warnings ssw;
        struct after_state_chg_work *ascw;
+       bool did_remote, should_do_remote;
 
        os = drbd_read_state(mdev);
 
@@ -981,11 +982,17 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
            (os.disk != D_DISKLESS && ns.disk == D_DISKLESS))
                atomic_inc(&mdev->local_cnt);
 
+       did_remote = drbd_should_do_remote(mdev->state);
        mdev->state.i = ns.i;
+       should_do_remote = drbd_should_do_remote(mdev->state);
        mdev->tconn->susp = ns.susp;
        mdev->tconn->susp_nod = ns.susp_nod;
        mdev->tconn->susp_fen = ns.susp_fen;
 
+       /* put replicated vs not-replicated requests in seperate epochs */
+       if (did_remote != should_do_remote)
+               start_new_tl_epoch(mdev->tconn);
+
        if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
                drbd_print_uuids(mdev, "attached to UUIDs");
 
index 9694dd9..3fd1009 100644 (file)
@@ -626,12 +626,13 @@ static void mtip_timeout_function(unsigned long int data)
                }
        }
 
-       if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+       if (cmdto_cnt) {
                print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
-
-               mtip_restart_port(port);
+               if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+                       mtip_restart_port(port);
+                       wake_up_interruptible(&port->svc_wait);
+               }
                clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
-               wake_up_interruptible(&port->svc_wait);
        }
 
        if (port->ic_pause_timer) {
@@ -3887,7 +3888,12 @@ static int mtip_block_remove(struct driver_data *dd)
         * Delete our gendisk structure. This also removes the device
         * from /dev
         */
-       del_gendisk(dd->disk);
+       if (dd->disk) {
+               if (dd->disk->queue)
+                       del_gendisk(dd->disk);
+               else
+                       put_disk(dd->disk);
+       }
 
        spin_lock(&rssd_index_lock);
        ida_remove(&rssd_index_ida, dd->index);
@@ -3921,7 +3927,13 @@ static int mtip_block_shutdown(struct driver_data *dd)
                "Shutting down %s ...\n", dd->disk->disk_name);
 
        /* Delete our gendisk structure, and cleanup the blk queue. */
-       del_gendisk(dd->disk);
+       if (dd->disk) {
+               if (dd->disk->queue)
+                       del_gendisk(dd->disk);
+               else
+                       put_disk(dd->disk);
+       }
+
 
        spin_lock(&rssd_index_lock);
        ida_remove(&rssd_index_ida, dd->index);
index 74374fb..5ac841f 100644 (file)
@@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
 static void make_response(struct xen_blkif *blkif, u64 id,
                          unsigned short op, int st);
 
-#define foreach_grant(pos, rbtree, node) \
-       for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \
+#define foreach_grant_safe(pos, n, rbtree, node) \
+       for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
+            (n) = rb_next(&(pos)->node); \
             &(pos)->node != NULL; \
-            (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node))
+            (pos) = container_of(n, typeof(*(pos)), node), \
+            (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
 
 
 static void add_persistent_gnt(struct rb_root *root,
@@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
        struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct persistent_gnt *persistent_gnt;
+       struct rb_node *n;
        int ret = 0;
        int segs_to_unmap = 0;
 
-       foreach_grant(persistent_gnt, root, node) {
+       foreach_grant_safe(persistent_gnt, n, root, node) {
                BUG_ON(persistent_gnt->handle ==
                        BLKBACK_INVALID_HANDLE);
                gnttab_set_unmap_op(&unmap[segs_to_unmap],
@@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
                        persistent_gnt->handle);
 
                pages[segs_to_unmap] = persistent_gnt->page;
-               rb_erase(&persistent_gnt->node, root);
-               kfree(persistent_gnt);
-               num--;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
                        !rb_next(&persistent_gnt->node)) {
@@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num)
                        BUG_ON(ret);
                        segs_to_unmap = 0;
                }
+
+               rb_erase(&persistent_gnt->node, root);
+               kfree(persistent_gnt);
+               num--;
        }
        BUG_ON(num != 0);
 }
index 96e9b00..11043c1 100644 (file)
@@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 {
        struct llist_node *all_gnts;
        struct grant *persistent_gnt;
+       struct llist_node *n;
 
        /* Prevent new requests being issued until we fix things up. */
        spin_lock_irq(&info->io_lock);
@@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
        /* Remove all persistent grants */
        if (info->persistent_gnts_c) {
                all_gnts = llist_del_all(&info->persistent_gnts);
-               llist_for_each_entry(persistent_gnt, all_gnts, node) {
+               llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) {
                        gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
                        __free_page(pfn_to_page(persistent_gnt->pfn));
                        kfree(persistent_gnt);
@@ -835,7 +836,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                             struct blkif_response *bret)
 {
-       int i;
+       int i = 0;
        struct bio_vec *bvec;
        struct req_iterator iter;
        unsigned long flags;
@@ -852,7 +853,8 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                 */
                rq_for_each_segment(bvec, s->request, iter) {
                        BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE);
-                       i = offset >> PAGE_SHIFT;
+                       if (bvec->bv_offset < offset)
+                               i++;
                        BUG_ON(i >= s->req.u.rw.nr_segments);
                        shared_data = kmap_atomic(
                                pfn_to_page(s->grants_used[i]->pfn));
@@ -861,7 +863,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
                                bvec->bv_len);
                        bvec_kunmap_irq(bvec_data, &flags);
                        kunmap_atomic(shared_data);
-                       offset += bvec->bv_len;
+                       offset = bvec->bv_offset + bvec->bv_len;
                }
        }
        /* Add the persistent grant into the list of free grants */
index 684b0d5..ee4dbea 100644 (file)
@@ -2062,7 +2062,8 @@ static void virtcons_remove(struct virtio_device *vdev)
        /* Disable interrupts for vqs */
        vdev->config->reset(vdev);
        /* Finish up work that's lined up */
-       cancel_work_sync(&portdev->control_work);
+       if (use_multiport(portdev))
+               cancel_work_sync(&portdev->control_work);
 
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
                unplug_port(port);
index 6479842..e920cbe 100644 (file)
@@ -1,3 +1,6 @@
+config CLKSRC_OF
+       bool
+
 config CLKSRC_I8253
        bool
 
@@ -25,6 +28,9 @@ config ARMADA_370_XP_TIMER
 config SUNXI_TIMER
        bool
 
+config VT8500_TIMER
+       bool
+
 config CLKSRC_NOMADIK_MTU
        bool
        depends on (ARCH_NOMADIK || ARCH_U8500)
index e69511c..4927110 100644 (file)
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CLKSRC_OF)        += clksrc-of.o
 obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
 obj-$(CONFIG_X86_CYCLONE_TIMER)        += cyclone.o
 obj-$(CONFIG_X86_PM_TIMER)     += acpi_pm.o
@@ -16,5 +17,6 @@ obj-$(CONFIG_CLKSRC_DBX500_PRCMU)     += clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)      += time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)     += bcm2835_timer.o
 obj-$(CONFIG_SUNXI_TIMER)      += sunxi_timer.o
+obj-$(CONFIG_VT8500_TIMER)     += vt8500_timer.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)           += arm_arch_timer.o
index bc19f12..7f796d8 100644 (file)
@@ -101,7 +101,7 @@ static struct of_device_id bcm2835_time_match[] __initconst = {
        {}
 };
 
-static void __init bcm2835_time_init(void)
+void __init bcm2835_timer_init(void)
 {
        struct device_node *node;
        void __iomem *base;
@@ -155,7 +155,3 @@ static void __init bcm2835_time_init(void)
 
        pr_info("bcm2835: system timer (irq = %d)\n", irq);
 }
-
-struct sys_timer bcm2835_timer = {
-       .init = bcm2835_time_init,
-};
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
new file mode 100644 (file)
index 0000000..bdabdaa
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/of.h>
+
+extern struct of_device_id __clksrc_of_table[];
+
+static const struct of_device_id __clksrc_of_table_sentinel
+       __used __section(__clksrc_of_table_end);
+
+void __init clocksource_of_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       void (*init_func)(void);
+
+       for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+               init_func = match->data;
+               init_func();
+       }
+}
index d927938..ea21048 100644 (file)
@@ -100,7 +100,6 @@ static struct clock_event_device cs5535_clockevent = {
        .set_mode = mfgpt_set_mode,
        .set_next_event = mfgpt_next_event,
        .rating = 250,
-       .shift = 32
 };
 
 static irqreturn_t mfgpt_tick(int irq, void *dev_id)
@@ -169,17 +168,11 @@ static int __init cs5535_mfgpt_init(void)
        cs5535_mfgpt_write(cs5535_event_clock, MFGPT_REG_SETUP, val);
 
        /* Set up the clock event */
-       cs5535_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC,
-                       cs5535_clockevent.shift);
-       cs5535_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
-                       &cs5535_clockevent);
-       cs5535_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE,
-                       &cs5535_clockevent);
-
        printk(KERN_INFO DRV_NAME
                ": Registering MFGPT timer as a clock event, using IRQ %d\n",
                timer_irq);
-       clockevents_register_device(&cs5535_clockevent);
+       clockevents_config_and_register(&cs5535_clockevent, MFGPT_HZ,
+                                       0xF, 0xFFFE);
 
        return 0;
 
index f7dba5b..ab09ed3 100644 (file)
@@ -107,7 +107,7 @@ static const struct of_device_id osctimer_ids[] __initconst = {
        {},
 };
 
-static void __init timer_init(void)
+void __init dw_apb_timer_init(void)
 {
        struct device_node *event_timer, *source_timer;
 
@@ -125,7 +125,3 @@ static void __init timer_init(void)
 
        init_sched_clock();
 }
-
-struct sys_timer dw_apb_timer = {
-       .init = timer_init,
-};
index 8914c3c..025afc6 100644 (file)
@@ -134,12 +134,32 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
        }
 }
 
+void nmdk_clksrc_reset(void)
+{
+       /* Disable */
+       writel(0, mtu_base + MTU_CR(0));
+
+       /* ClockSource: configure load and background-load, and fire it up */
+       writel(nmdk_cycle, mtu_base + MTU_LR(0));
+       writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+       writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+              mtu_base + MTU_CR(0));
+}
+
+static void nmdk_clkevt_resume(struct clock_event_device *cedev)
+{
+       nmdk_clkevt_reset();
+       nmdk_clksrc_reset();
+}
+
 static struct clock_event_device nmdk_clkevt = {
        .name           = "mtu_1",
        .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
        .rating         = 200,
        .set_mode       = nmdk_clkevt_mode,
        .set_next_event = nmdk_clkevt_next,
+       .resume         = nmdk_clkevt_resume,
 };
 
 /*
@@ -161,19 +181,6 @@ static struct irqaction nmdk_timer_irq = {
        .dev_id         = &nmdk_clkevt,
 };
 
-void nmdk_clksrc_reset(void)
-{
-       /* Disable */
-       writel(0, mtu_base + MTU_CR(0));
-
-       /* ClockSource: configure load and background-load, and fire it up */
-       writel(nmdk_cycle, mtu_base + MTU_LR(0));
-       writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
-
-       writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
-              mtu_base + MTU_CR(0));
-}
-
 void __init nmdk_timer_init(void __iomem *base, int irq)
 {
        unsigned long rate;
index 3cd1bd3..0ce85e2 100644 (file)
@@ -74,7 +74,6 @@ static int sunxi_clkevt_next_event(unsigned long evt,
 
 static struct clock_event_device sunxi_clockevent = {
        .name = "sunxi_tick",
-       .shift = 32,
        .rating = 300,
        .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .set_mode = sunxi_clkevt_mode,
@@ -104,7 +103,7 @@ static struct of_device_id sunxi_timer_dt_ids[] = {
        { }
 };
 
-static void __init sunxi_timer_init(void)
+void __init sunxi_timer_init(void)
 {
        struct device_node *node;
        unsigned long rate = 0;
@@ -154,18 +153,8 @@ static void __init sunxi_timer_init(void)
        val = readl(timer_base + TIMER_CTL_REG);
        writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG);
 
-       sunxi_clockevent.mult = div_sc(rate / TIMER_SCAL,
-                               NSEC_PER_SEC,
-                               sunxi_clockevent.shift);
-       sunxi_clockevent.max_delta_ns = clockevent_delta2ns(0xff,
-                                                           &sunxi_clockevent);
-       sunxi_clockevent.min_delta_ns = clockevent_delta2ns(0x1,
-                                                           &sunxi_clockevent);
        sunxi_clockevent.cpumask = cpumask_of(0);
 
-       clockevents_register_device(&sunxi_clockevent);
+       clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL,
+                                       0x1, 0xff);
 }
-
-struct sys_timer sunxi_timer = {
-       .init = sunxi_timer_init,
-};
index 32cb929..8a61872 100644 (file)
@@ -157,7 +157,6 @@ static struct tc_clkevt_device clkevt = {
                .name           = "tc_clkevt",
                .features       = CLOCK_EVT_FEAT_PERIODIC
                                        | CLOCK_EVT_FEAT_ONESHOT,
-               .shift          = 32,
                /* Should be lower than at91rm9200's system timer */
                .rating         = 125,
                .set_next_event = tc_next_event,
@@ -196,13 +195,9 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
 
        timer_clock = clk32k_divisor_idx;
 
-       clkevt.clkevt.mult = div_sc(32768, NSEC_PER_SEC, clkevt.clkevt.shift);
-       clkevt.clkevt.max_delta_ns
-               = clockevent_delta2ns(0xffff, &clkevt.clkevt);
-       clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
        clkevt.clkevt.cpumask = cpumask_of(0);
 
-       clockevents_register_device(&clkevt.clkevt);
+       clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);
 
        setup_irq(irq, &tc_irqaction);
 }
similarity index 94%
rename from arch/arm/mach-vt8500/timer.c
rename to drivers/clocksource/vt8500_timer.c
index 3dd21a4..ed66cf0 100644 (file)
@@ -168,17 +168,12 @@ void __init vt8500_timer_init(void)
                pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n",
                                        __func__, clocksource.name);
 
-       clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
-
-       /* copy-pasted from mach-msm; no idea */
-       clockevent.max_delta_ns =
-               clockevent_delta2ns(0xf0000000, &clockevent);
-       clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
        clockevent.cpumask = cpumask_of(0);
 
        if (setup_irq(timer_irq, &irq))
                pr_err("%s: setup_irq failed for %s\n", __func__,
                                                        clockevent.name);
-       clockevents_register_device(&clockevent);
+       clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ,
+                                       4, 0xf0000000);
 }
 
index 4d0e60a..a2d478e 100644 (file)
@@ -1313,14 +1313,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
                                        radeon_wait_for_vblank(rdev, i);
                                        tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                        WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                                }
                        } else {
                                tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
                                if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
                                        radeon_wait_for_vblank(rdev, i);
                                        tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                        WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                                }
                        }
                        /* wait for the next frame */
@@ -1345,6 +1349,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                blackout &= ~BLACKOUT_MODE_MASK;
                WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
        }
+       /* wait for the MC to settle */
+       udelay(100);
 }
 
 void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
@@ -1378,11 +1384,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
                        if (ASIC_IS_DCE6(rdev)) {
                                tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
                                tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                        } else {
                                tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
                                tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
+                               WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                        }
                        /* wait for the next frame */
                        frame_count = radeon_get_vblank_counter(rdev, i);
@@ -2036,9 +2046,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        WREG32(HDP_ADDR_CONFIG, gb_addr_config);
        WREG32(DMA_TILING_CONFIG, gb_addr_config);
 
-       tmp = gb_addr_config & NUM_PIPES_MASK;
-       tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
-                                       EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
+       if ((rdev->config.evergreen.max_backends == 1) &&
+           (rdev->flags & RADEON_IS_IGP)) {
+               if ((disabled_rb_mask & 3) == 1) {
+                       /* RB0 disabled, RB1 enabled */
+                       tmp = 0x11111111;
+               } else {
+                       /* RB1 disabled, RB0 enabled */
+                       tmp = 0x00000000;
+               }
+       } else {
+               tmp = gb_addr_config & NUM_PIPES_MASK;
+               tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
+                                               EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
+       }
        WREG32(GB_BACKEND_MAP, tmp);
 
        WREG32(CGTS_SYS_TCC_DISABLE, 0);
index bc2540b..becb03e 100644 (file)
@@ -1462,12 +1462,15 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev,
                              u32 disabled_rb_mask)
 {
        u32 rendering_pipe_num, rb_num_width, req_rb_num;
-       u32 pipe_rb_ratio, pipe_rb_remain;
+       u32 pipe_rb_ratio, pipe_rb_remain, tmp;
        u32 data = 0, mask = 1 << (max_rb_num - 1);
        unsigned i, j;
 
        /* mask out the RBs that don't exist on that asic */
-       disabled_rb_mask |= (0xff << max_rb_num) & 0xff;
+       tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff);
+       /* make sure at least one RB is available */
+       if ((tmp & 0xff) != 0xff)
+               disabled_rb_mask = tmp;
 
        rendering_pipe_num = 1 << tiling_pipe_num;
        req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask);
index 9056faf..0b202c0 100644 (file)
@@ -1445,7 +1445,7 @@ static struct radeon_asic cayman_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1572,7 +1572,7 @@ static struct radeon_asic trinity_asic = {
        .vm = {
                .init = &cayman_vm_init,
                .fini = &cayman_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &cayman_vm_set_page,
        },
        .ring = {
@@ -1699,7 +1699,7 @@ static struct radeon_asic si_asic = {
        .vm = {
                .init = &si_vm_init,
                .fini = &si_vm_fini,
-               .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .set_page = &si_vm_set_page,
        },
        .ring = {
index 33a56a0..3e403bd 100644 (file)
@@ -2470,6 +2470,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
                                                                   1),
                                                                  ATOM_DEVICE_CRT1_SUPPORT);
                                }
+                               /* RV100 board with external TDMS bit mis-set.
+                                * Actually uses internal TMDS, clear the bit.
+                                */
+                               if (dev->pdev->device == 0x5159 &&
+                                   dev->pdev->subsystem_vendor == 0x1014 &&
+                                   dev->pdev->subsystem_device == 0x029A) {
+                                       tmp &= ~(1 << 4);
+                               }
                                if ((tmp >> 4) & 0x1) {
                                        devices |= ATOM_DEVICE_DFP2_SUPPORT;
                                        radeon_add_legacy_encoder(dev,
index ff3def7..05c96fa 100644 (file)
@@ -1115,8 +1115,10 @@ radeon_user_framebuffer_create(struct drm_device *dev,
        }
 
        radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
-       if (radeon_fb == NULL)
+       if (radeon_fb == NULL) {
+               drm_gem_object_unreference_unlocked(obj);
                return ERR_PTR(-ENOMEM);
+       }
 
        ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
        if (ret) {
index 2430d80..cd72062 100644 (file)
@@ -377,6 +377,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
 {
        int r;
 
+       /* make sure we aren't trying to allocate more space than there is on the ring */
+       if (ndw > (ring->ring_size / 4))
+               return -ENOMEM;
        /* Align requested size with padding so unlock_commit can
         * pad safely */
        ndw = (ndw + ring->align_mask) & ~ring->align_mask;
index 0f656b1..a072fa8 100644 (file)
@@ -1,5 +1,6 @@
 cayman 0x9400
 0x0000802C GRBM_GFX_INDEX
+0x00008040 WAIT_UNTIL
 0x000084FC CP_STRMOUT_CNTL
 0x000085F0 CP_COHER_CNTL
 0x000085F4 CP_COHER_SIZE
index 2bb6d0e..435ed35 100644 (file)
@@ -336,6 +336,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
                                WREG32(R600_CITF_CNTL, blackout);
                }
        }
+       /* wait for the MC to settle */
+       udelay(100);
 }
 
 void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
index 44420fc..8be35c8 100644 (file)
@@ -429,7 +429,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        struct ttm_bo_device *bdev = bo->bdev;
        struct ttm_bo_driver *driver = bdev->driver;
 
-       fbo = kzalloc(sizeof(*fbo), GFP_KERNEL);
+       fbo = kmalloc(sizeof(*fbo), GFP_KERNEL);
        if (!fbo)
                return -ENOMEM;
 
@@ -448,7 +448,12 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        fbo->vm_node = NULL;
        atomic_set(&fbo->cpu_writers, 0);
 
-       fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+       spin_lock(&bdev->fence_lock);
+       if (bo->sync_obj)
+               fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+       else
+               fbo->sync_obj = NULL;
+       spin_unlock(&bdev->fence_lock);
        kref_init(&fbo->list_kref);
        kref_init(&fbo->kref);
        fbo->destroy = &ttm_transfered_destroy;
@@ -661,13 +666,11 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
                 */
 
                set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
-
-               /* ttm_buffer_object_transfer accesses bo->sync_obj */
-               ret = ttm_buffer_object_transfer(bo, &ghost_obj);
                spin_unlock(&bdev->fence_lock);
                if (tmp_obj)
                        driver->sync_obj_unref(&tmp_obj);
 
+               ret = ttm_buffer_object_transfer(bo, &ghost_obj);
                if (ret)
                        return ret;
 
index 4dfa605..34e2547 100644 (file)
 #define USB_VENDOR_ID_EZKEY            0x0518
 #define USB_DEVICE_ID_BTC_8193         0x0002
 
+#define USB_VENDOR_ID_FORMOSA          0x147a
+#define USB_DEVICE_ID_FORMOSA_IR_RECEIVER      0xe03e
+
 #define USB_VENDOR_ID_FREESCALE                0x15A2
 #define USB_DEVICE_ID_FREESCALE_MX28   0x004F
 
index 12e4fdc..e766b56 100644 (file)
@@ -540,13 +540,24 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 {
        struct i2c_client *client = hid->driver_data;
        int report_id = buf[0];
+       int ret;
 
        if (report_type == HID_INPUT_REPORT)
                return -EINVAL;
 
-       return i2c_hid_set_report(client,
+       if (report_id) {
+               buf++;
+               count--;
+       }
+
+       ret = i2c_hid_set_report(client,
                                report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
                                report_id, buf, count);
+
+       if (report_id && ret >= 0)
+               ret++; /* add report_id to the number of transfered bytes */
+
+       return ret;
 }
 
 static int i2c_hid_parse(struct hid_device *hid)
index ac9e352..e0e6abf 100644 (file)
@@ -70,6 +70,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
index 4850d03..3527509 100644 (file)
@@ -263,20 +263,15 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
                struct qib_qp __rcu **qpp;
 
                qpp = &dev->qp_table[n];
-               q = rcu_dereference_protected(*qpp,
-                       lockdep_is_held(&dev->qpt_lock));
-               for (; q; qpp = &q->next) {
+               for (; (q = rcu_dereference_protected(*qpp,
+                               lockdep_is_held(&dev->qpt_lock))) != NULL;
+                               qpp = &q->next)
                        if (q == qp) {
                                atomic_dec(&qp->refcount);
                                *qpp = qp->next;
                                rcu_assign_pointer(qp->next, NULL);
-                               q = rcu_dereference_protected(*qpp,
-                                       lockdep_is_held(&dev->qpt_lock));
                                break;
                        }
-                       q = rcu_dereference_protected(*qpp,
-                               lockdep_is_held(&dev->qpt_lock));
-               }
        }
 
        spin_unlock_irqrestore(&dev->qpt_lock, flags);
index 03103d2..67b0c1d 100644 (file)
@@ -741,6 +741,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
 
        tx_req->mapping = addr;
 
+       skb_orphan(skb);
+       skb_dst_drop(skb);
+
        rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
                       addr, skb->len);
        if (unlikely(rc)) {
@@ -752,9 +755,6 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
                dev->trans_start = jiffies;
                ++tx->tx_head;
 
-               skb_orphan(skb);
-               skb_dst_drop(skb);
-
                if (++priv->tx_outstanding == ipoib_sendq_size) {
                        ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
                                  tx->qp->qp_num);
index a1bca70..2cfa76f 100644 (file)
@@ -600,6 +600,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                netif_stop_queue(dev);
        }
 
+       skb_orphan(skb);
+       skb_dst_drop(skb);
+
        rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
                       address->ah, qpn, tx_req, phead, hlen);
        if (unlikely(rc)) {
@@ -615,9 +618,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
 
                address->last_send = priv->tx_head;
                ++priv->tx_head;
-
-               skb_orphan(skb);
-               skb_dst_drop(skb);
        }
 
        if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
index 69d9a39..644d724 100644 (file)
@@ -353,6 +353,25 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
        irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static u8 gic_get_cpumask(struct gic_chip_data *gic)
+{
+       void __iomem *base = gic_data_dist_base(gic);
+       u32 mask, i;
+
+       for (i = mask = 0; i < 32; i += 4) {
+               mask = readl_relaxed(base + GIC_DIST_TARGET + i);
+               mask |= mask >> 16;
+               mask |= mask >> 8;
+               if (mask)
+                       break;
+       }
+
+       if (!mask)
+               pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
+
+       return mask;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic)
 {
        unsigned int i;
@@ -371,7 +390,9 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
        /*
         * Set all global interrupts to this CPU only.
         */
-       cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0);
+       cpumask = gic_get_cpumask(gic);
+       cpumask |= cpumask << 8;
+       cpumask |= cpumask << 16;
        for (i = 32; i < gic_irqs; i += 4)
                writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
@@ -402,7 +423,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
         * Get what the GIC says our CPU mask is.
         */
        BUG_ON(cpu >= NR_GIC_CPU_IF);
-       cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0);
+       cpu_mask = gic_get_cpumask(gic);
        gic_cpu_map[cpu] = cpu_mask;
 
        /*
index 675ae52..5409607 100644 (file)
@@ -2746,19 +2746,9 @@ static int thin_iterate_devices(struct dm_target *ti,
        return 0;
 }
 
-/*
- * A thin device always inherits its queue limits from its pool.
- */
-static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
-{
-       struct thin_c *tc = ti->private;
-
-       *limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
-}
-
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 6, 0},
+       .version = {1, 7, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
@@ -2767,7 +2757,6 @@ static struct target_type thin_target = {
        .postsuspend = thin_postsuspend,
        .status = thin_status,
        .iterate_devices = thin_iterate_devices,
-       .io_hints = thin_io_hints,
 };
 
 /*----------------------------------------------------------------*/
index c72e4d5..314a0e2 100644 (file)
@@ -1188,6 +1188,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci,
 {
        struct dm_target *ti;
        sector_t len;
+       unsigned num_requests;
 
        do {
                ti = dm_table_find_target(ci->map, ci->sector);
@@ -1200,7 +1201,8 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci,
                 * reconfiguration might also have changed that since the
                 * check was performed.
                 */
-               if (!get_num_requests || !get_num_requests(ti))
+               num_requests = get_num_requests ? get_num_requests(ti) : 0;
+               if (!num_requests)
                        return -EOPNOTSUPP;
 
                if (is_split_required && !is_split_required(ti))
@@ -1208,7 +1210,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci,
                else
                        len = min(ci->sector_count, max_io_len(ci->sector, ti));
 
-               __issue_target_requests(ci, ti, ti->num_discard_requests, len);
+               __issue_target_requests(ci, ti, num_requests, len);
 
                ci->sector += len;
        } while (ci->sector_count -= len);
index e10e525..296941a 100644 (file)
@@ -374,6 +374,7 @@ static int usb_keene_probe(struct usb_interface *intf,
        radio->vdev.ioctl_ops = &usb_keene_ioctl_ops;
        radio->vdev.lock = &radio->lock;
        radio->vdev.release = video_device_release_empty;
+       radio->vdev.vfl_dir = VFL_DIR_TX;
 
        radio->usbdev = interface_to_usbdev(intf);
        radio->intf = intf;
index a082e40..1507c9d 100644 (file)
@@ -250,6 +250,7 @@ static struct video_device radio_si4713_vdev_template = {
        .name                   = "radio-si4713",
        .release                = video_device_release,
        .ioctl_ops              = &radio_si4713_ioctl_ops,
+       .vfl_dir                = VFL_DIR_TX,
 };
 
 /* Platform driver interface */
index c48be19..cabbe3a 100644 (file)
@@ -1971,6 +1971,7 @@ static struct video_device wl1273_viddev_template = {
        .ioctl_ops              = &wl1273_ioctl_ops,
        .name                   = WL1273_FM_DRIVER_NAME,
        .release                = wl1273_vdev_release,
+       .vfl_dir                = VFL_DIR_TX,
 };
 
 static int wl1273_fm_radio_remove(struct platform_device *pdev)
index 048de45..0a8ee8f 100644 (file)
@@ -518,6 +518,16 @@ static struct video_device fm_viddev_template = {
        .ioctl_ops = &fm_drv_ioctl_ops,
        .name = FM_DRV_NAME,
        .release = video_device_release,
+       /*
+        * To ensure both the tuner and modulator ioctls are accessible we
+        * set the vfl_dir to M2M to indicate this.
+        *
+        * It is not really a mem2mem device of course, but it can both receive
+        * and transmit using the same radio device. It's the only radio driver
+        * that does this and it should really be split in two radio devices,
+        * but that would affect applications using this driver.
+        */
+       .vfl_dir = VFL_DIR_M2M,
 };
 
 int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
index 27f80cd..46dcb54 100644 (file)
@@ -272,6 +272,7 @@ config MTD_DOCG3
        tristate "M-Systems Disk-On-Chip G3"
        select BCH
        select BCH_CONST_PARAMS
+       select BITREVERSE
        ---help---
          This provides an MTD device driver for the M-Systems DiskOnChip
          G3 devices.
index 67cc73c..7901d72 100644 (file)
@@ -170,7 +170,7 @@ static int of_flash_probe(struct platform_device *dev)
        resource_size_t res_size;
        struct mtd_part_parser_data ppdata;
        bool map_indirect;
-       const char *mtd_name;
+       const char *mtd_name = NULL;
 
        match = of_match_device(of_flash_match, &dev->dev);
        if (!match)
index 86c9a79..595de40 100644 (file)
@@ -17,8 +17,8 @@
 #include "bcm47xxnflash.h"
 
 /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
- * shown 164 retries as maxiumum. */
-#define NFLASH_READY_RETRIES           1000
+ * shown ~1000 retries as maxiumum. */
+#define NFLASH_READY_RETRIES           10000
 
 #define NFLASH_SECTOR_SIZE             512
 
index 3502606..feae55c 100644 (file)
@@ -523,7 +523,7 @@ static struct nand_ecclayout hwecc4_2048 __initconst = {
 static const struct of_device_id davinci_nand_of_match[] = {
        {.compatible = "ti,davinci-nand", },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
 
 static struct davinci_nand_pdata
index 8323ac9..3766682 100644 (file)
@@ -2857,8 +2857,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        int i;
        int val;
 
-       /* ONFI need to be probed in 8 bits mode */
-       WARN_ON(chip->options & NAND_BUSWIDTH_16);
+       /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */
+       if (chip->options & NAND_BUSWIDTH_16) {
+               pr_err("Trying ONFI probe in 16 bits mode, aborting !\n");
+               return 0;
+       }
        /* Try ONFI for unknown chip or LP */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
        if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
index 1877ed7..1c9e09f 100644 (file)
@@ -1053,6 +1053,7 @@ static ssize_t bonding_store_primary(struct device *d,
                pr_info("%s: Setting primary slave to None.\n",
                        bond->dev->name);
                bond->primary_slave = NULL;
+               memset(bond->params.primary, 0, sizeof(bond->params.primary));
                bond_select_active_slave(bond);
                goto out;
        }
index 58607f1..2282b1a 100644 (file)
@@ -488,8 +488,12 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
 
        priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),
                        IFX_WRITE_LOW_16BIT(mask));
+
+       /* According to C_CAN documentation, the reserved bit
+        * in IFx_MASK2 register is fixed 1
+        */
        priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface),
-                       IFX_WRITE_HIGH_16BIT(mask));
+                       IFX_WRITE_HIGH_16BIT(mask) | BIT(13));
 
        priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
                        IFX_WRITE_LOW_16BIT(id));
index 4eba17b..f1b3df1 100644 (file)
 
 #define DRV_VER                        "4.4.161.0u"
 #define DRV_NAME               "be2net"
-#define BE_NAME                        "ServerEngines BladeEngine2 10Gbps NIC"
-#define BE3_NAME               "ServerEngines BladeEngine3 10Gbps NIC"
-#define OC_NAME                        "Emulex OneConnect 10Gbps NIC"
+#define BE_NAME                        "Emulex BladeEngine2"
+#define BE3_NAME               "Emulex BladeEngine3"
+#define OC_NAME                        "Emulex OneConnect"
 #define OC_NAME_BE             OC_NAME "(be3)"
 #define OC_NAME_LANCER         OC_NAME "(Lancer)"
 #define OC_NAME_SH             OC_NAME "(Skyhawk)"
-#define DRV_DESC               "ServerEngines BladeEngine 10Gbps NIC Driver"
+#define DRV_DESC               "Emulex OneConnect 10Gbps NIC Driver"
 
 #define BE_VENDOR_ID           0x19a2
 #define EMULEX_VENDOR_ID       0x10df
index 5c99570..4d6f3c5 100644 (file)
@@ -25,7 +25,7 @@
 MODULE_VERSION(DRV_VER);
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
 MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
-MODULE_AUTHOR("ServerEngines Corporation");
+MODULE_AUTHOR("Emulex Corporation");
 MODULE_LICENSE("GPL");
 
 static unsigned int num_vfs;
index 02a12b6..4dab6fc 100644 (file)
 #define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
 #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */
 #define E1000_CTRL_LANPHYPC_VALUE    0x00020000 /* SW value of LANPHYPC */
+#define E1000_CTRL_MEHE     0x00080000  /* Memory Error Handling Enable */
 #define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
 #define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
 #define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
 
 #define E1000_PBS_16K E1000_PBA_16K
 
+/* Uncorrectable/correctable ECC Error counts and enable bits */
+#define E1000_PBECCSTS_CORR_ERR_CNT_MASK       0x000000FF
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK     0x0000FF00
+#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT    8
+#define E1000_PBECCSTS_ECC_ENABLE              0x00010000
+
 #define IFS_MAX       80
 #define IFS_MIN       40
 #define IFS_RATIO     4
 #define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */
 #define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
 #define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
+#define E1000_ICR_ECCER         0x00400000 /* Uncorrectable ECC Error */
 #define E1000_ICR_INT_ASSERTED  0x80000000 /* If this bit asserted, the driver should claim the interrupt */
 #define E1000_ICR_RXQ0          0x00100000 /* Rx Queue 0 Interrupt */
 #define E1000_ICR_RXQ1          0x00200000 /* Rx Queue 1 Interrupt */
 #define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
 #define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
 #define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
+#define E1000_IMS_ECCER     E1000_ICR_ECCER     /* Uncorrectable ECC Error */
 #define E1000_IMS_RXQ0      E1000_ICR_RXQ0      /* Rx Queue 0 Interrupt */
 #define E1000_IMS_RXQ1      E1000_ICR_RXQ1      /* Rx Queue 1 Interrupt */
 #define E1000_IMS_TXQ0      E1000_ICR_TXQ0      /* Tx Queue 0 Interrupt */
index 6782a2e..7e95f22 100644 (file)
@@ -309,6 +309,8 @@ struct e1000_adapter {
 
        struct napi_struct napi;
 
+       unsigned int uncorr_errors;     /* uncorrectable ECC errors */
+       unsigned int corr_errors;       /* correctable ECC errors */
        unsigned int restart_queue;
        u32 txd_cmd;
 
index f95bc6e..fd4772a 100644 (file)
@@ -108,6 +108,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        E1000_STAT("dropped_smbus", stats.mgpdc),
        E1000_STAT("rx_dma_failed", rx_dma_failed),
        E1000_STAT("tx_dma_failed", tx_dma_failed),
+       E1000_STAT("uncorr_ecc_errors", uncorr_errors),
+       E1000_STAT("corr_ecc_errors", corr_errors),
 };
 
 #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
index cf21777..b88676f 100644 (file)
@@ -77,6 +77,7 @@ enum e1e_registers {
 #define E1000_POEMB    E1000_PHY_CTRL  /* PHY OEM Bits */
        E1000_PBA      = 0x01000, /* Packet Buffer Allocation - RW */
        E1000_PBS      = 0x01008, /* Packet Buffer Size */
+       E1000_PBECCSTS = 0x0100C, /* Packet Buffer ECC Status - RW */
        E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
        E1000_EEWR     = 0x0102C, /* EEPROM Write Register - RW */
        E1000_FLOP     = 0x0103C, /* FLASH Opcode Register */
index 9763365..24d9f61 100644 (file)
@@ -3624,6 +3624,17 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
        if (hw->mac.type == e1000_ich8lan)
                reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
        ew32(RFCTL, reg);
+
+       /* Enable ECC on Lynxpoint */
+       if (hw->mac.type == e1000_pch_lpt) {
+               reg = er32(PBECCSTS);
+               reg |= E1000_PBECCSTS_ECC_ENABLE;
+               ew32(PBECCSTS, reg);
+
+               reg = er32(CTRL);
+               reg |= E1000_CTRL_MEHE;
+               ew32(CTRL, reg);
+       }
 }
 
 /**
index fbf75fd..643c883 100644 (file)
@@ -1678,6 +1678,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
+       /* Reset on uncorrectable ECC error */
+       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+               u32 pbeccsts = er32(PBECCSTS);
+
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+
+               /* Do the reset outside of interrupt context */
+               schedule_work(&adapter->reset_task);
+
+               /* return immediately since reset is imminent */
+               return IRQ_HANDLED;
+       }
+
        if (napi_schedule_prep(&adapter->napi)) {
                adapter->total_tx_bytes = 0;
                adapter->total_tx_packets = 0;
@@ -1741,6 +1758,23 @@ static irqreturn_t e1000_intr(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
+       /* Reset on uncorrectable ECC error */
+       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+               u32 pbeccsts = er32(PBECCSTS);
+
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+
+               /* Do the reset outside of interrupt context */
+               schedule_work(&adapter->reset_task);
+
+               /* return immediately since reset is imminent */
+               return IRQ_HANDLED;
+       }
+
        if (napi_schedule_prep(&adapter->napi)) {
                adapter->total_tx_bytes = 0;
                adapter->total_tx_packets = 0;
@@ -2104,6 +2138,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
        if (adapter->msix_entries) {
                ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
                ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
+       } else if (hw->mac.type == e1000_pch_lpt) {
+               ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
        } else {
                ew32(IMS, IMS_ENABLE_MASK);
        }
@@ -4251,6 +4287,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.mgptc += er32(MGTPTC);
        adapter->stats.mgprc += er32(MGTPRC);
        adapter->stats.mgpdc += er32(MGTPDC);
+
+       /* Correctable ECC Errors */
+       if (hw->mac.type == e1000_pch_lpt) {
+               u32 pbeccsts = er32(PBECCSTS);
+               adapter->corr_errors +=
+                   pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK;
+               adapter->uncorr_errors +=
+                   (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >>
+                   E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT;
+       }
 }
 
 /**
index a6542d7..5163af3 100644 (file)
@@ -380,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                }
        }
 
-       if ((dev_cap->flags &
+       if ((dev->caps.flags &
            (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) &&
            mlx4_is_master(dev))
                dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
index 7992b3e..78ace59 100644 (file)
@@ -1801,7 +1801,7 @@ static void rhine_tx(struct net_device *dev)
                                         rp->tx_skbuff[entry]->len,
                                         PCI_DMA_TODEVICE);
                }
-               dev_kfree_skb_irq(rp->tx_skbuff[entry]);
+               dev_kfree_skb(rp->tx_skbuff[entry]);
                rp->tx_skbuff[entry] = NULL;
                entry = (++rp->dirty_tx) % TX_RING_SIZE;
        }
@@ -2010,11 +2010,7 @@ static void rhine_slow_event_task(struct work_struct *work)
        if (intr_status & IntrPCIErr)
                netif_warn(rp, hw, dev, "PCI error\n");
 
-       napi_disable(&rp->napi);
-       rhine_irq_disable(rp);
-       /* Slow and safe. Consider __napi_schedule as a replacement ? */
-       napi_enable(&rp->napi);
-       napi_schedule(&rp->napi);
+       iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable);
 
 out_unlock:
        mutex_unlock(&rp->task_lock);
index cc09b67..2917a86 100644 (file)
@@ -298,11 +298,12 @@ static void tun_flow_cleanup(unsigned long data)
 }
 
 static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
-                           u16 queue_index)
+                           struct tun_file *tfile)
 {
        struct hlist_head *head;
        struct tun_flow_entry *e;
        unsigned long delay = tun->ageing_time;
+       u16 queue_index = tfile->queue_index;
 
        if (!rxhash)
                return;
@@ -311,7 +312,9 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
 
        rcu_read_lock();
 
-       if (tun->numqueues == 1)
+       /* We may get a very small possibility of OOO during switching, not
+        * worth to optimize.*/
+       if (tun->numqueues == 1 || tfile->detached)
                goto unlock;
 
        e = tun_flow_find(head, rxhash);
@@ -411,21 +414,21 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 
        tun = rtnl_dereference(tfile->tun);
 
-       if (tun) {
+       if (tun && !tfile->detached) {
                u16 index = tfile->queue_index;
                BUG_ON(index >= tun->numqueues);
                dev = tun->dev;
 
                rcu_assign_pointer(tun->tfiles[index],
                                   tun->tfiles[tun->numqueues - 1]);
-               rcu_assign_pointer(tfile->tun, NULL);
                ntfile = rtnl_dereference(tun->tfiles[index]);
                ntfile->queue_index = index;
 
                --tun->numqueues;
-               if (clean)
+               if (clean) {
+                       rcu_assign_pointer(tfile->tun, NULL);
                        sock_put(&tfile->sk);
-               else
+               else
                        tun_disable_queue(tun, tfile);
 
                synchronize_net();
@@ -439,10 +442,13 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
        }
 
        if (clean) {
-               if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
-                   !(tun->flags & TUN_PERSIST))
-                       if (tun->dev->reg_state == NETREG_REGISTERED)
+               if (tun && tun->numqueues == 0 && tun->numdisabled == 0) {
+                       netif_carrier_off(tun->dev);
+
+                       if (!(tun->flags & TUN_PERSIST) &&
+                           tun->dev->reg_state == NETREG_REGISTERED)
                                unregister_netdevice(tun->dev);
+               }
 
                BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
                                 &tfile->socket.flags));
@@ -470,6 +476,10 @@ static void tun_detach_all(struct net_device *dev)
                rcu_assign_pointer(tfile->tun, NULL);
                --tun->numqueues;
        }
+       list_for_each_entry(tfile, &tun->disabled, next) {
+               wake_up_all(&tfile->wq.wait);
+               rcu_assign_pointer(tfile->tun, NULL);
+       }
        BUG_ON(tun->numqueues != 0);
 
        synchronize_net();
@@ -500,7 +510,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
                goto out;
 
        err = -EINVAL;
-       if (rtnl_dereference(tfile->tun))
+       if (rtnl_dereference(tfile->tun) && !tfile->detached)
                goto out;
 
        err = -EBUSY;
@@ -1199,7 +1209,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        tun->dev->stats.rx_packets++;
        tun->dev->stats.rx_bytes += len;
 
-       tun_flow_update(tun, rxhash, tfile->queue_index);
+       tun_flow_update(tun, rxhash, tfile);
        return total_len;
 }
 
@@ -1658,10 +1668,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
                    device_create_file(&tun->dev->dev, &dev_attr_group))
                        pr_err("Failed to create tun sysfs files\n");
-
-               netif_carrier_on(tun->dev);
        }
 
+       netif_carrier_on(tun->dev);
+
        tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
        if (ifr->ifr_flags & IFF_NO_PI)
@@ -1813,7 +1823,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
                ret = tun_attach(tun, file);
        } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
                tun = rtnl_dereference(tfile->tun);
-               if (!tun || !(tun->flags & TUN_TAP_MQ))
+               if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached)
                        ret = -EINVAL;
                else
                        __tun_detach(tfile, false);
index 9197b2c..00d3b2d 100644 (file)
@@ -1215,6 +1215,9 @@ static const struct usb_device_id cdc_devs[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
          .driver_info = (unsigned long)&wwan_info,
        },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76),
+         .driver_info = (unsigned long)&wwan_info,
+       },
 
        /* Infineon(now Intel) HSPA Modem platform */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
index 575a583..c8e05e2 100644 (file)
@@ -351,6 +351,10 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* HUAWEI_INTERFACE_NDIS_CONTROL_QUALCOMM */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 2. Combined interface devices matching on class+protocol */
        {       /* Huawei E367 and possibly others in "Windows mode" */
@@ -361,6 +365,14 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* HUAWEI_NDIS_SINGLE_INTERFACE_VDF */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x37),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* HUAWEI_INTERFACE_NDIS_HW_QUALCOMM */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x67),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
        {       /* Pantech UML290, P4200 and more */
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
@@ -461,6 +473,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
+       {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index f34b2eb..5e33606 100644 (file)
@@ -380,6 +380,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
        unsigned long           lockflags;
        size_t                  size = dev->rx_urb_size;
 
+       /* prevent rx skb allocation when error ratio is high */
+       if (test_bit(EVENT_RX_KILL, &dev->flags)) {
+               usb_free_urb(urb);
+               return -ENOLINK;
+       }
+
        skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
        if (!skb) {
                netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
@@ -539,6 +545,17 @@ block:
                break;
        }
 
+       /* stop rx if packet error rate is high */
+       if (++dev->pkt_cnt > 30) {
+               dev->pkt_cnt = 0;
+               dev->pkt_err = 0;
+       } else {
+               if (state == rx_cleanup)
+                       dev->pkt_err++;
+               if (dev->pkt_err > 20)
+                       set_bit(EVENT_RX_KILL, &dev->flags);
+       }
+
        state = defer_bh(dev, skb, &dev->rxq, state);
 
        if (urb) {
@@ -791,6 +808,11 @@ int usbnet_open (struct net_device *net)
                   (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" :
                   "simple");
 
+       /* reset rx error state */
+       dev->pkt_cnt = 0;
+       dev->pkt_err = 0;
+       clear_bit(EVENT_RX_KILL, &dev->flags);
+
        // delay posting reads until we're fully open
        tasklet_schedule (&dev->bh);
        if (info->manage_power) {
@@ -1103,13 +1125,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
        if (info->tx_fixup) {
                skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
                if (!skb) {
-                       if (netif_msg_tx_err(dev)) {
-                               netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
-                               goto drop;
-                       } else {
-                               /* cdc_ncm collected packet; waits for more */
+                       /* packet collected; minidriver waiting for more */
+                       if (info->flags & FLAG_MULTI_PACKET)
                                goto not_drop;
-                       }
+                       netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n");
+                       goto drop;
                }
        }
        length = skb->len;
@@ -1254,6 +1274,9 @@ static void usbnet_bh (unsigned long param)
                }
        }
 
+       /* restart RX again after disabling due to high error rate */
+       clear_bit(EVENT_RX_KILL, &dev->flags);
+
        // waiting for all pending urbs to complete?
        if (dev->wait) {
                if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
index dc8913c..12c6440 100644 (file)
@@ -154,8 +154,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
        if (ret & 1) { /* Link is up. */
                printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n",
                       adapter->netdev->name, adapter->link_speed);
-               if (!netif_carrier_ok(adapter->netdev))
-                       netif_carrier_on(adapter->netdev);
+               netif_carrier_on(adapter->netdev);
 
                if (affectTxQueue) {
                        for (i = 0; i < adapter->num_tx_queues; i++)
@@ -165,8 +164,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
        } else {
                printk(KERN_INFO "%s: NIC Link is Down\n",
                       adapter->netdev->name);
-               if (netif_carrier_ok(adapter->netdev))
-                       netif_carrier_off(adapter->netdev);
+               netif_carrier_off(adapter->netdev);
 
                if (affectTxQueue) {
                        for (i = 0; i < adapter->num_tx_queues; i++)
@@ -3061,6 +3059,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
        netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
        netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues);
 
+       netif_carrier_off(netdev);
        err = register_netdev(netdev);
 
        if (err) {
index 0f71d1d..e5fd209 100644 (file)
@@ -36,6 +36,7 @@
 #include "debug.h"
 
 #define N_TX_QUEUES    4 /* #tx queues on mac80211<->driver interface */
+#define BRCMS_FLUSH_TIMEOUT    500 /* msec */
 
 /* Flags we support */
 #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
@@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 }
 
+static bool brcms_tx_flush_completed(struct brcms_info *wl)
+{
+       bool result;
+
+       spin_lock_bh(&wl->lock);
+       result = brcms_c_tx_flush_completed(wl->wlc);
+       spin_unlock_bh(&wl->lock);
+       return result;
+}
+
 static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop)
 {
        struct brcms_info *wl = hw->priv;
+       int ret;
 
        no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
 
-       /* wait for packet queue and dma fifos to run empty */
-       spin_lock_bh(&wl->lock);
-       brcms_c_wait_for_tx_completion(wl->wlc, drop);
-       spin_unlock_bh(&wl->lock);
+       ret = wait_event_timeout(wl->tx_flush_wq,
+                                brcms_tx_flush_completed(wl),
+                                msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));
+
+       brcms_dbg_mac80211(wl->wlc->hw->d11core,
+                          "ret=%d\n", jiffies_to_msecs(ret));
 }
 
 static const struct ieee80211_ops brcms_ops = {
@@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data)
 
  done:
        spin_unlock_bh(&wl->lock);
+       wake_up(&wl->tx_flush_wq);
 }
 
 /*
@@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
 
        atomic_set(&wl->callbacks, 0);
 
+       init_waitqueue_head(&wl->tx_flush_wq);
+
        /* setup the bottom half handler */
        tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
 
@@ -1609,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
        spin_lock_bh(&wl->lock);
        return blocked;
 }
-
-/*
- * precondition: perimeter lock has been acquired
- */
-void brcms_msleep(struct brcms_info *wl, uint ms)
-{
-       spin_unlock_bh(&wl->lock);
-       msleep(ms);
-       spin_lock_bh(&wl->lock);
-}
index 9358bd5..947ccac 100644 (file)
@@ -68,6 +68,8 @@ struct brcms_info {
        spinlock_t lock;        /* per-device perimeter lock */
        spinlock_t isr_lock;    /* per-device ISR synchronization lock */
 
+       /* tx flush */
+       wait_queue_head_t tx_flush_wq;
 
        /* timer related fields */
        atomic_t callbacks;     /* # outstanding callback functions */
@@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
 extern void brcms_free_timer(struct brcms_timer *timer);
 extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
 extern bool brcms_del_timer(struct brcms_timer *timer);
-extern void brcms_msleep(struct brcms_info *wl, uint ms);
 extern void brcms_dpc(unsigned long data);
 extern void brcms_timer(struct brcms_timer *t);
 extern void brcms_fatal_error(struct brcms_info *wl);
index 17594de..8b58390 100644 (file)
@@ -1027,7 +1027,6 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
 static bool
 brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 {
-       bool morepending = false;
        struct bcma_device *core;
        struct tx_status txstatus, *txs;
        u32 s1, s2;
@@ -1041,23 +1040,20 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
        txs = &txstatus;
        core = wlc_hw->d11core;
        *fatal = false;
-       s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
-       while (!(*fatal)
-              && (s1 & TXS_V)) {
-               /* !give others some time to run! */
-               if (n >= max_tx_num) {
-                       morepending = true;
-                       break;
-               }
 
+       while (n < max_tx_num) {
+               s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
                if (s1 == 0xffffffff) {
                        brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
                                  __func__);
                        *fatal = true;
                        return false;
                }
-               s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
+               /* only process when valid */
+               if (!(s1 & TXS_V))
+                       break;
 
+               s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
                txs->status = s1 & TXS_STATUS_MASK;
                txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
                txs->sequence = s2 & TXS_SEQ_MASK;
@@ -1065,15 +1061,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
                txs->lasttxtime = 0;
 
                *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
-
-               s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
+               if (*fatal == true)
+                       return false;
                n++;
        }
 
-       if (*fatal)
-               return false;
-
-       return morepending;
+       return n >= max_tx_num;
 }
 
 static void brcms_c_tbtt(struct brcms_c_info *wlc)
@@ -7518,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
        return wlc->band->bandunit;
 }
 
-void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc)
 {
-       int timeout = 20;
        int i;
 
        /* Kick DMA to send any pending AMPDU */
        for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
                if (wlc->hw->di[i])
-                       dma_txflush(wlc->hw->di[i]);
-
-       /* wait for queue and DMA fifos to run dry */
-       while (brcms_txpktpendtot(wlc) > 0) {
-               brcms_msleep(wlc->wl, 1);
-
-               if (--timeout == 0)
-                       break;
-       }
+                       dma_kick_tx(wlc->hw->di[i]);
 
-       WARN_ON_ONCE(timeout == 0);
+       return !brcms_txpktpendtot(wlc);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
index 4fb2834..b0f14b7 100644 (file)
@@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
 extern void brcms_c_scan_start(struct brcms_c_info *wlc);
 extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
 extern int brcms_c_get_curband(struct brcms_c_info *wlc);
-extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc,
-                                          bool drop);
 extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
 extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
 extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
@@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
 extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
 extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
+extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
 
 #endif                         /* _BRCM_PUB_H_ */
index 31534f7..2797964 100644 (file)
@@ -1153,6 +1153,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
                        next_reclaimed = ssn;
                }
 
+               if (tid != IWL_TID_NON_QOS) {
+                       priv->tid_data[sta_id][tid].next_reclaimed =
+                               next_reclaimed;
+                       IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
+                                                 next_reclaimed);
+               }
+
                iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
 
                iwlagn_check_ratid_empty(priv, sta_id, tid);
@@ -1203,28 +1210,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
                        if (!is_agg)
                                iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
 
-                       /*
-                        * W/A for FW bug - the seq_ctl isn't updated when the
-                        * queues are flushed. Fetch it from the packet itself
-                        */
-                       if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) {
-                               next_reclaimed = le16_to_cpu(hdr->seq_ctrl);
-                               next_reclaimed =
-                                       SEQ_TO_SN(next_reclaimed + 0x10);
-                       }
-
                        is_offchannel_skb =
                                (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
                        freed++;
                }
 
-               if (tid != IWL_TID_NON_QOS) {
-                       priv->tid_data[sta_id][tid].next_reclaimed =
-                               next_reclaimed;
-                       IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
-                                          next_reclaimed);
-               }
-
                WARN_ON(!is_agg && freed != 1);
 
                /*
index 9189a32..973a9d9 100644 (file)
@@ -1563,7 +1563,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
                        scan_rsp->number_of_sets);
                ret = -1;
-               goto done;
+               goto check_next_scan;
        }
 
        bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
@@ -1634,7 +1634,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                if (!beacon_size || beacon_size > bytes_left) {
                        bss_info += bytes_left;
                        bytes_left = 0;
-                       return -1;
+                       ret = -1;
+                       goto check_next_scan;
                }
 
                /* Initialize the current working beacon pointer for this BSS
@@ -1690,7 +1691,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                                dev_err(priv->adapter->dev,
                                        "%s: bytes left < IE length\n",
                                        __func__);
-                               goto done;
+                               goto check_next_scan;
                        }
                        if (element_id == WLAN_EID_DS_PARAMS) {
                                channel = *(current_ptr + sizeof(struct ieee_types_header));
@@ -1753,6 +1754,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                }
        }
 
+check_next_scan:
        spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
        if (list_empty(&adapter->scan_pending_q)) {
                spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
@@ -1813,7 +1815,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                }
        }
 
-done:
        return ret;
 }
 
index 4494d13..0f8b051 100644 (file)
@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                                         is_tx ? "Tx" : "Rx");
 
                                if (is_tx) {
-                                       rtl_lps_leave(hw);
+                                       schedule_work(&rtlpriv->
+                                                     works.lps_leave_work);
                                        ppsc->last_delaylps_stamp_jiffies =
                                            jiffies;
                                }
@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                }
        } else if (ETH_P_ARP == ether_type) {
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                         "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
 
                if (is_tx) {
-                       rtl_lps_leave(hw);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
index f2ecdeb..1535efd 100644 (file)
@@ -542,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
        WARN_ON(skb_queue_empty(&rx_queue));
        while (!skb_queue_empty(&rx_queue)) {
                _skb = skb_dequeue(&rx_queue);
-               _rtl_usb_rx_process_agg(hw, skb);
-               ieee80211_rx_irqsafe(hw, skb);
+               _rtl_usb_rx_process_agg(hw, _skb);
+               ieee80211_rx_irqsafe(hw, _skb);
        }
 }
 
index 94b79c3..9d7f172 100644 (file)
@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);
 /* Notify xenvif that ring now has space to send an skb to the frontend */
 void xenvif_notify_tx_completion(struct xenvif *vif);
 
+/* Prevent the device from generating any further traffic. */
+void xenvif_carrier_off(struct xenvif *vif);
+
 /* Returns number of ring slots required to send an skb to the frontend */
 unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
 
index b7d41f8..b8c5193 100644 (file)
@@ -343,17 +343,22 @@ err:
        return err;
 }
 
-void xenvif_disconnect(struct xenvif *vif)
+void xenvif_carrier_off(struct xenvif *vif)
 {
        struct net_device *dev = vif->dev;
-       if (netif_carrier_ok(dev)) {
-               rtnl_lock();
-               netif_carrier_off(dev); /* discard queued packets */
-               if (netif_running(dev))
-                       xenvif_down(vif);
-               rtnl_unlock();
-               xenvif_put(vif);
-       }
+
+       rtnl_lock();
+       netif_carrier_off(dev); /* discard queued packets */
+       if (netif_running(dev))
+               xenvif_down(vif);
+       rtnl_unlock();
+       xenvif_put(vif);
+}
+
+void xenvif_disconnect(struct xenvif *vif)
+{
+       if (netif_carrier_ok(vif->dev))
+               xenvif_carrier_off(vif);
 
        atomic_dec(&vif->refcnt);
        wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
index f2d6b78..2b9520c 100644 (file)
@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif)
        atomic_dec(&netbk->netfront_count);
 }
 
-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx);
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
+                                 u8 status);
 static void make_tx_response(struct xenvif *vif,
                             struct xen_netif_tx_request *txp,
                             s8       st);
@@ -879,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif,
 
        do {
                make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               if (cons >= end)
+               if (cons == end)
                        break;
                txp = RING_GET_REQUEST(&vif->tx, cons++);
        } while (1);
@@ -888,6 +889,13 @@ static void netbk_tx_err(struct xenvif *vif,
        xenvif_put(vif);
 }
 
+static void netbk_fatal_tx_err(struct xenvif *vif)
+{
+       netdev_err(vif->dev, "fatal error; disabling device\n");
+       xenvif_carrier_off(vif);
+       xenvif_put(vif);
+}
+
 static int netbk_count_requests(struct xenvif *vif,
                                struct xen_netif_tx_request *first,
                                struct xen_netif_tx_request *txp,
@@ -901,19 +909,22 @@ static int netbk_count_requests(struct xenvif *vif,
 
        do {
                if (frags >= work_to_do) {
-                       netdev_dbg(vif->dev, "Need more frags\n");
+                       netdev_err(vif->dev, "Need more frags\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
                if (unlikely(frags >= MAX_SKB_FRAGS)) {
-                       netdev_dbg(vif->dev, "Too many frags\n");
+                       netdev_err(vif->dev, "Too many frags\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
                memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
                       sizeof(*txp));
                if (txp->size > first->size) {
-                       netdev_dbg(vif->dev, "Frags galore\n");
+                       netdev_err(vif->dev, "Frag is bigger than frame.\n");
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
 
@@ -921,8 +932,9 @@ static int netbk_count_requests(struct xenvif *vif,
                frags++;
 
                if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
-                       netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n",
+                       netdev_err(vif->dev, "txp->offset: %x, size: %u\n",
                                 txp->offset, txp->size);
+                       netbk_fatal_tx_err(vif);
                        return -frags;
                }
        } while ((txp++)->flags & XEN_NETTXF_more_data);
@@ -966,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
                pending_idx = netbk->pending_ring[index];
                page = xen_netbk_alloc_page(netbk, skb, pending_idx);
                if (!page)
-                       return NULL;
+                       goto err;
 
                gop->source.u.ref = txp->gref;
                gop->source.domid = vif->domid;
@@ -988,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
        }
 
        return gop;
+err:
+       /* Unwind, freeing all pages and sending error responses. */
+       while (i-- > start) {
+               xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]),
+                                     XEN_NETIF_RSP_ERROR);
+       }
+       /* The head too, if necessary. */
+       if (start)
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
+
+       return NULL;
 }
 
 static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
@@ -996,30 +1019,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 {
        struct gnttab_copy *gop = *gopp;
        u16 pending_idx = *((u16 *)skb->data);
-       struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
-       struct xenvif *vif = pending_tx_info[pending_idx].vif;
-       struct xen_netif_tx_request *txp;
        struct skb_shared_info *shinfo = skb_shinfo(skb);
        int nr_frags = shinfo->nr_frags;
        int i, err, start;
 
        /* Check status of header. */
        err = gop->status;
-       if (unlikely(err)) {
-               pending_ring_idx_t index;
-               index = pending_index(netbk->pending_prod++);
-               txp = &pending_tx_info[pending_idx].req;
-               make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               netbk->pending_ring[index] = pending_idx;
-               xenvif_put(vif);
-       }
+       if (unlikely(err))
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
 
        /* Skip first skb fragment if it is on same page as header fragment. */
        start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
 
        for (i = start; i < nr_frags; i++) {
                int j, newerr;
-               pending_ring_idx_t index;
 
                pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
 
@@ -1028,16 +1041,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
                if (likely(!newerr)) {
                        /* Had a previous error? Invalidate this fragment. */
                        if (unlikely(err))
-                               xen_netbk_idx_release(netbk, pending_idx);
+                               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                        continue;
                }
 
                /* Error on this fragment: respond to client with an error. */
-               txp = &netbk->pending_tx_info[pending_idx].req;
-               make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
-               index = pending_index(netbk->pending_prod++);
-               netbk->pending_ring[index] = pending_idx;
-               xenvif_put(vif);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR);
 
                /* Not the first error? Preceding frags already invalidated. */
                if (err)
@@ -1045,10 +1054,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 
                /* First error: invalidate header and preceding fragments. */
                pending_idx = *((u16 *)skb->data);
-               xen_netbk_idx_release(netbk, pending_idx);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                for (j = start; j < i; j++) {
                        pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
-                       xen_netbk_idx_release(netbk, pending_idx);
+                       xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                }
 
                /* Remember the error: invalidate all subsequent fragments. */
@@ -1082,7 +1091,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
 
                /* Take an extra reference to offset xen_netbk_idx_release */
                get_page(netbk->mmap_pages[pending_idx]);
-               xen_netbk_idx_release(netbk, pending_idx);
+               xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
        }
 }
 
@@ -1095,7 +1104,8 @@ static int xen_netbk_get_extras(struct xenvif *vif,
 
        do {
                if (unlikely(work_to_do-- <= 0)) {
-                       netdev_dbg(vif->dev, "Missing extra info\n");
+                       netdev_err(vif->dev, "Missing extra info\n");
+                       netbk_fatal_tx_err(vif);
                        return -EBADR;
                }
 
@@ -1104,8 +1114,9 @@ static int xen_netbk_get_extras(struct xenvif *vif,
                if (unlikely(!extra.type ||
                             extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
                        vif->tx.req_cons = ++cons;
-                       netdev_dbg(vif->dev,
+                       netdev_err(vif->dev,
                                   "Invalid extra type: %d\n", extra.type);
+                       netbk_fatal_tx_err(vif);
                        return -EINVAL;
                }
 
@@ -1121,13 +1132,15 @@ static int netbk_set_skb_gso(struct xenvif *vif,
                             struct xen_netif_extra_info *gso)
 {
        if (!gso->u.gso.size) {
-               netdev_dbg(vif->dev, "GSO size must not be zero.\n");
+               netdev_err(vif->dev, "GSO size must not be zero.\n");
+               netbk_fatal_tx_err(vif);
                return -EINVAL;
        }
 
        /* Currently only TCPv4 S.O. is supported. */
        if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
-               netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+               netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+               netbk_fatal_tx_err(vif);
                return -EINVAL;
        }
 
@@ -1264,9 +1277,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 
                /* Get a netif from the list with work to do. */
                vif = poll_net_schedule_list(netbk);
+               /* This can sometimes happen because the test of
+                * list_empty(net_schedule_list) at the top of the
+                * loop is unlocked.  Just go back and have another
+                * look.
+                */
                if (!vif)
                        continue;
 
+               if (vif->tx.sring->req_prod - vif->tx.req_cons >
+                   XEN_NETIF_TX_RING_SIZE) {
+                       netdev_err(vif->dev,
+                                  "Impossible number of requests. "
+                                  "req_prod %d, req_cons %d, size %ld\n",
+                                  vif->tx.sring->req_prod, vif->tx.req_cons,
+                                  XEN_NETIF_TX_RING_SIZE);
+                       netbk_fatal_tx_err(vif);
+                       continue;
+               }
+
                RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
                if (!work_to_do) {
                        xenvif_put(vif);
@@ -1294,17 +1323,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
                        work_to_do = xen_netbk_get_extras(vif, extras,
                                                          work_to_do);
                        idx = vif->tx.req_cons;
-                       if (unlikely(work_to_do < 0)) {
-                               netbk_tx_err(vif, &txreq, idx);
+                       if (unlikely(work_to_do < 0))
                                continue;
-                       }
                }
 
                ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do);
-               if (unlikely(ret < 0)) {
-                       netbk_tx_err(vif, &txreq, idx - ret);
+               if (unlikely(ret < 0))
                        continue;
-               }
+
                idx += ret;
 
                if (unlikely(txreq.size < ETH_HLEN)) {
@@ -1316,11 +1342,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 
                /* No crossing a page as the payload mustn't fragment. */
                if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
-                       netdev_dbg(vif->dev,
+                       netdev_err(vif->dev,
                                   "txreq.offset: %x, size: %u, end: %lu\n",
                                   txreq.offset, txreq.size,
                                   (txreq.offset&~PAGE_MASK) + txreq.size);
-                       netbk_tx_err(vif, &txreq, idx);
+                       netbk_fatal_tx_err(vif);
                        continue;
                }
 
@@ -1348,8 +1374,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
                        gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
 
                        if (netbk_set_skb_gso(vif, skb, gso)) {
+                               /* Failure in netbk_set_skb_gso is fatal. */
                                kfree_skb(skb);
-                               netbk_tx_err(vif, &txreq, idx);
                                continue;
                        }
                }
@@ -1448,7 +1474,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk)
                        txp->size -= data_len;
                } else {
                        /* Schedule a response immediately. */
-                       xen_netbk_idx_release(netbk, pending_idx);
+                       xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
                }
 
                if (txp->flags & XEN_NETTXF_csum_blank)
@@ -1500,7 +1526,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk)
        xen_netbk_tx_submit(netbk);
 }
 
-static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
+                                 u8 status)
 {
        struct xenvif *vif;
        struct pending_tx_info *pending_tx_info;
@@ -1514,7 +1541,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
 
        vif = pending_tx_info->vif;
 
-       make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY);
+       make_tx_response(vif, &pending_tx_info->req, status);
 
        index = pending_index(netbk->pending_prod++);
        netbk->pending_ring[index] = pending_idx;
index efaecef..a5f3c8c 100644 (file)
@@ -184,8 +184,8 @@ config PINCTRL_SAMSUNG
        select PINMUX
        select PINCONF
 
-config PINCTRL_EXYNOS4
-       bool "Pinctrl driver data for Exynos4 SoC"
+config PINCTRL_EXYNOS
+       bool "Pinctrl driver data for Samsung EXYNOS SoCs"
        depends on OF && GPIOLIB
        select PINCTRL_SAMSUNG
 
index fc4606f..6e87e52 100644 (file)
@@ -36,7 +36,7 @@ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
 obj-$(CONFIG_PINCTRL_U300)     += pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)   += pinctrl-coh901.o
 obj-$(CONFIG_PINCTRL_SAMSUNG)  += pinctrl-samsung.o
-obj-$(CONFIG_PINCTRL_EXYNOS4)  += pinctrl-exynos.o
+obj-$(CONFIG_PINCTRL_EXYNOS  += pinctrl-exynos.o
 obj-$(CONFIG_PINCTRL_EXYNOS5440)       += pinctrl-exynos5440.o
 obj-$(CONFIG_PINCTRL_XWAY)     += pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)   += pinctrl-lantiq.o
index 498b2ba..d02498b 100644 (file)
@@ -1246,6 +1246,22 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
        return of_iomap(np, 0);
 }
 
+static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc,
+       const struct of_phandle_args *gpiospec,
+       u32 *flags)
+{
+       if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE)
+               return -EINVAL;
+
+       if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc)
+               return -EINVAL;
+
+       if (flags)
+               *flags = gpiospec->args[1];
+
+       return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE;
+}
+
 static int sirfsoc_pinmux_probe(struct platform_device *pdev)
 {
        int ret;
@@ -1736,6 +1752,8 @@ static int sirfsoc_gpio_probe(struct device_node *np)
                bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
                bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
                bank->chip.gc.of_node = np;
+               bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate;
+               bank->chip.gc.of_gpio_n_cells = 2;
                bank->chip.regs = regs;
                bank->id = i;
                bank->is_marco = is_marco;
index b85040c..cca18a3 100644 (file)
@@ -379,9 +379,10 @@ static struct regulator_desc regulators[] = {
 };
 
 #ifdef CONFIG_OF
-static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max77686_platform_data *pdata)
 {
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct device_node *pmic_np, *regulators_np;
        struct max77686_regulator_data *rdata;
        struct of_regulator_match rmatch;
@@ -390,15 +391,15 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
        pmic_np = iodev->dev->of_node;
        regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
        if (!regulators_np) {
-               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               dev_err(&pdev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
        }
 
        pdata->num_regulators = ARRAY_SIZE(regulators);
-       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
                             pdata->num_regulators, GFP_KERNEL);
        if (!rdata) {
-               dev_err(iodev->dev,
+               dev_err(&pdev->dev,
                        "could not allocate memory for regulator data\n");
                return -ENOMEM;
        }
@@ -407,7 +408,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
                rmatch.name = regulators[i].name;
                rmatch.init_data = NULL;
                rmatch.of_node = NULL;
-               of_regulator_match(iodev->dev, regulators_np, &rmatch, 1);
+               of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
                rdata[i].initdata = rmatch.init_data;
                rdata[i].of_node = rmatch.of_node;
        }
@@ -417,7 +418,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
        return 0;
 }
 #else
-static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max77686_platform_data *pdata)
 {
        return 0;
@@ -440,7 +441,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
        }
 
        if (iodev->dev->of_node) {
-               ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
+               ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
                if (ret)
                        return ret;
        }
index d1a7751..d40cf7f 100644 (file)
@@ -237,8 +237,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       ret = of_regulator_match(pdev->dev.parent, regulators,
-                                max8907_matches,
+       ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
                                 ARRAY_SIZE(max8907_matches));
        if (ret < 0) {
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
index 02be7fc..836908c 100644 (file)
@@ -934,7 +934,7 @@ static struct regulator_desc regulators[] = {
 };
 
 #ifdef CONFIG_OF
-static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev,
                        struct max8997_platform_data *pdata,
                        struct device_node *pmic_np)
 {
@@ -944,7 +944,7 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
                gpio = of_get_named_gpio(pmic_np,
                                        "max8997,pmic-buck125-dvs-gpios", i);
                if (!gpio_is_valid(gpio)) {
-                       dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+                       dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio);
                        return -EINVAL;
                }
                pdata->buck125_gpios[i] = gpio;
@@ -952,22 +952,23 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
        return 0;
 }
 
-static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max8997_platform_data *pdata)
 {
+       struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct device_node *pmic_np, *regulators_np, *reg_np;
        struct max8997_regulator_data *rdata;
        unsigned int i, dvs_voltage_nr = 1, ret;
 
        pmic_np = iodev->dev->of_node;
        if (!pmic_np) {
-               dev_err(iodev->dev, "could not find pmic sub-node\n");
+               dev_err(&pdev->dev, "could not find pmic sub-node\n");
                return -ENODEV;
        }
 
        regulators_np = of_find_node_by_name(pmic_np, "regulators");
        if (!regulators_np) {
-               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               dev_err(&pdev->dev, "could not find regulators sub-node\n");
                return -EINVAL;
        }
 
@@ -976,11 +977,10 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
        for_each_child_of_node(regulators_np, reg_np)
                pdata->num_regulators++;
 
-       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
                                pdata->num_regulators, GFP_KERNEL);
        if (!rdata) {
-               dev_err(iodev->dev, "could not allocate memory for "
-                                               "regulator data\n");
+               dev_err(&pdev->dev, "could not allocate memory for regulator data\n");
                return -ENOMEM;
        }
 
@@ -991,14 +991,14 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
                                break;
 
                if (i == ARRAY_SIZE(regulators)) {
-                       dev_warn(iodev->dev, "don't know how to configure "
-                               "regulator %s\n", reg_np->name);
+                       dev_warn(&pdev->dev, "don't know how to configure regulator %s\n",
+                                reg_np->name);
                        continue;
                }
 
                rdata->id = i;
-               rdata->initdata = of_get_regulator_init_data(
-                                               iodev->dev, reg_np);
+               rdata->initdata = of_get_regulator_init_data(&pdev->dev,
+                                                            reg_np);
                rdata->reg_node = reg_np;
                rdata++;
        }
@@ -1014,7 +1014,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
 
        if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
                                                pdata->buck5_gpiodvs) {
-               ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+               ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np);
                if (ret)
                        return -EINVAL;
 
@@ -1025,8 +1025,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
                } else {
                        if (pdata->buck125_default_idx >= 8) {
                                pdata->buck125_default_idx = 0;
-                               dev_info(iodev->dev, "invalid value for "
-                               "default dvs index, using 0 instead\n");
+                               dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n");
                        }
                }
 
@@ -1040,28 +1039,28 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck1-dvs-voltage",
                                pdata->buck1_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck1 voltages not specified\n");
+               dev_err(&pdev->dev, "buck1 voltages not specified\n");
                return -EINVAL;
        }
 
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck2-dvs-voltage",
                                pdata->buck2_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck2 voltages not specified\n");
+               dev_err(&pdev->dev, "buck2 voltages not specified\n");
                return -EINVAL;
        }
 
        if (of_property_read_u32_array(pmic_np,
                                "max8997,pmic-buck5-dvs-voltage",
                                pdata->buck5_voltage, dvs_voltage_nr)) {
-               dev_err(iodev->dev, "buck5 voltages not specified\n");
+               dev_err(&pdev->dev, "buck5 voltages not specified\n");
                return -EINVAL;
        }
 
        return 0;
 }
 #else
-static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
                                        struct max8997_platform_data *pdata)
 {
        return 0;
@@ -1085,7 +1084,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
        }
 
        if (iodev->dev->of_node) {
-               ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+               ret = max8997_pmic_dt_parse_pdata(pdev, pdata);
                if (ret)
                        return ret;
        }
index 1f0df40..0a8dd1c 100644 (file)
@@ -65,7 +65,7 @@ static const struct voltage_map_desc ldo9_voltage_map_desc = {
        .min = 2800000, .step = 100000, .max = 3100000,
 };
 static const struct voltage_map_desc ldo10_voltage_map_desc = {
-       .min = 95000  .step = 50000,  .max = 1300000,
+       .min = 950000,  .step = 50000,  .max = 1300000,
 };
 static const struct voltage_map_desc ldo1213_voltage_map_desc = {
        .min = 800000,  .step = 100000, .max = 3300000,
index 6f68491..66ca769 100644 (file)
@@ -120,6 +120,12 @@ int of_regulator_match(struct device *dev, struct device_node *node,
        if (!dev || !node)
                return -EINVAL;
 
+       for (i = 0; i < num_matches; i++) {
+               struct of_regulator_match *match = &matches[i];
+               match->init_data = NULL;
+               match->of_node = NULL;
+       }
+
        for_each_child_of_node(node, child) {
                name = of_get_property(child,
                                        "regulator-compatible", NULL);
index bd062a2..cd9ea2e 100644 (file)
@@ -174,9 +174,9 @@ static struct regulator_ops s2mps11_buck_ops = {
        .min_uV         = S2MPS11_BUCK_MIN2,                    \
        .uV_step        = S2MPS11_BUCK_STEP2,                   \
        .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
-       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_reg       = S2MPS11_REG_B10CTRL2,                 \
        .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
-       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_reg     = S2MPS11_REG_B10CTRL1,                 \
        .enable_mask    = S2MPS11_ENABLE_MASK                   \
 }
 
index 73dce76..df39518 100644 (file)
@@ -305,8 +305,8 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
        if (!regs)
                return NULL;
 
-       count = of_regulator_match(pdev->dev.parent, regs,
-                               reg_matches, TPS65217_NUM_REGULATOR);
+       count = of_regulator_match(&pdev->dev, regs, reg_matches,
+                                  TPS65217_NUM_REGULATOR);
        of_node_put(regs);
        if ((count < 0) || (count > TPS65217_NUM_REGULATOR))
                return NULL;
index 59c3770..b0e4c0b 100644 (file)
@@ -998,7 +998,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
                return NULL;
        }
 
-       ret = of_regulator_match(pdev->dev.parent, regulators, matches, count);
+       ret = of_regulator_match(&pdev->dev, regulators, matches, count);
        if (ret < 0) {
                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
                        ret);
index afb7cfa..c016ad8 100644 (file)
@@ -506,6 +506,7 @@ isl1208_rtc_interrupt(int irq, void *data)
 {
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        struct i2c_client *client = data;
+       struct rtc_device *rtc = i2c_get_clientdata(client);
        int handled = 0, sr, err;
 
        /*
@@ -528,6 +529,8 @@ isl1208_rtc_interrupt(int irq, void *data)
        if (sr & ISL1208_REG_SR_ALM) {
                dev_dbg(&client->dev, "alarm!\n");
 
+               rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+
                /* Clear the alarm */
                sr &= ~ISL1208_REG_SR_ALM;
                sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
index 08378e3..10c1a34 100644 (file)
@@ -44,6 +44,7 @@
 #define RTC_YMR                0x34    /* Year match register */
 #define RTC_YLR                0x38    /* Year data load register */
 
+#define RTC_CR_EN      (1 << 0)        /* counter enable bit */
 #define RTC_CR_CWEN    (1 << 26)       /* Clockwatch enable bit */
 
 #define RTC_TCR_EN     (1 << 1) /* Periodic timer enable bit */
@@ -320,7 +321,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
        struct pl031_local *ldata;
        struct pl031_vendor_data *vendor = id->data;
        struct rtc_class_ops *ops = &vendor->ops;
-       unsigned long time;
+       unsigned long time, data;
 
        ret = amba_request_regions(adev, NULL);
        if (ret)
@@ -345,10 +346,11 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
        dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
        dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
 
+       data = readl(ldata->base + RTC_CR);
        /* Enable the clockwatch on ST Variants */
        if (vendor->clockwatch)
-               writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
-                      ldata->base + RTC_CR);
+               data |= RTC_CR_CWEN;
+       writel(data | RTC_CR_EN, ldata->base + RTC_CR);
 
        /*
         * On ST PL031 variants, the RTC reset value does not provide correct
index 00c930f..2730533 100644 (file)
@@ -137,7 +137,7 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S)
+       writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S)
                | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)
                | (bin2bcd(tm->tm_mday))
                | ((tm->tm_year >= 200) << DATE_CENTURY_S),
index 97ac0a3..eb27530 100644 (file)
@@ -174,3 +174,15 @@ int ssb_gpio_init(struct ssb_bus *bus)
 
        return -1;
 }
+
+int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       if (ssb_chipco_available(&bus->chipco) ||
+           ssb_extif_available(&bus->extif)) {
+               return gpiochip_remove(&bus->gpio);
+       } else {
+               SSB_WARN_ON(1);
+       }
+
+       return -1;
+}
index 772ad9b..24dc331 100644 (file)
@@ -443,6 +443,15 @@ static void ssb_devices_unregister(struct ssb_bus *bus)
 
 void ssb_bus_unregister(struct ssb_bus *bus)
 {
+       int err;
+
+       err = ssb_gpio_unregister(bus);
+       if (err == -EBUSY)
+               ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n");
+       else if (err)
+               ssb_dprintk(KERN_ERR PFX
+                           "Can not unregister GPIO driver: %i\n", err);
+
        ssb_buses_lock();
        ssb_devices_unregister(bus);
        list_del(&bus->list);
index 6c10b66..da38305 100644 (file)
@@ -252,11 +252,16 @@ static inline void ssb_extif_init(struct ssb_extif *extif)
 
 #ifdef CONFIG_SSB_DRIVER_GPIO
 extern int ssb_gpio_init(struct ssb_bus *bus);
+extern int ssb_gpio_unregister(struct ssb_bus *bus);
 #else /* CONFIG_SSB_DRIVER_GPIO */
 static inline int ssb_gpio_init(struct ssb_bus *bus)
 {
        return -ENOTSUPP;
 }
+static inline int ssb_gpio_unregister(struct ssb_bus *bus)
+{
+       return 0;
+}
 #endif /* CONFIG_SSB_DRIVER_GPIO */
 
 #endif /* LINUX_SSB_PRIVATE_H_ */
index e269510..f2aa754 100644 (file)
@@ -941,6 +941,8 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
 
 int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
 {
+       int block_size = dev->dev_attrib.block_size;
+
        if (dev->export_count) {
                pr_err("dev[%p]: Unable to change SE Device"
                        " fabric_max_sectors while export_count is %d\n",
@@ -978,8 +980,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
        /*
         * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
         */
+       if (!block_size) {
+               block_size = 512;
+               pr_warn("Defaulting to 512 for zero block_size\n");
+       }
        fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors,
-                                                     dev->dev_attrib.block_size);
+                                                     block_size);
 
        dev->dev_attrib.fabric_max_sectors = fabric_max_sectors;
        pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
index 810263d..c57bbbc 100644 (file)
@@ -754,6 +754,11 @@ static int target_fabric_port_link(
                return -EFAULT;
        }
 
+       if (!(dev->dev_flags & DF_CONFIGURED)) {
+               pr_err("se_device not configured yet, cannot port link\n");
+               return -ENODEV;
+       }
+
        tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;
        se_tpg = container_of(to_config_group(tpg_ci),
                                struct se_portal_group, tpg_group);
index 26a6d18..a664c66 100644 (file)
@@ -58,11 +58,10 @@ sbc_emulate_readcapacity(struct se_cmd *cmd)
        buf[7] = dev->dev_attrib.block_size & 0xff;
 
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
@@ -97,11 +96,10 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
                buf[14] = 0x80;
 
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        target_complete_cmd(cmd, GOOD);
        return 0;
index 84f9e96..2d88f08 100644 (file)
@@ -641,11 +641,10 @@ spc_emulate_inquiry(struct se_cmd *cmd)
 
 out:
        rbuf = transport_kmap_data_sg(cmd);
-       if (!rbuf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-       memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
 
        if (!ret)
                target_complete_cmd(cmd, GOOD);
@@ -851,7 +850,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        char *cdb = cmd->t_task_cdb;
-       unsigned char *buf, *map_buf;
+       unsigned char buf[SE_MODE_PAGE_BUF], *rbuf;
        int type = dev->transport->get_device_type(dev);
        int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
        bool dbd = !!(cdb[1] & 0x08);
@@ -863,26 +862,8 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
        int ret;
        int i;
 
-       map_buf = transport_kmap_data_sg(cmd);
-       if (!map_buf)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-       /*
-        * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
-        * know we actually allocated a full page.  Otherwise, if the
-        * data buffer is too small, allocate a temporary buffer so we
-        * don't have to worry about overruns in all our INQUIRY
-        * emulation handling.
-        */
-       if (cmd->data_length < SE_MODE_PAGE_BUF &&
-           (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
-               buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL);
-               if (!buf) {
-                       transport_kunmap_data_sg(cmd);
-                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-               }
-       } else {
-               buf = map_buf;
-       }
+       memset(buf, 0, SE_MODE_PAGE_BUF);
+
        /*
         * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for
         * MODE_SENSE_10 and byte 2 for MODE_SENSE (6).
@@ -934,8 +915,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
        if (page == 0x3f) {
                if (subpage != 0x00 && subpage != 0xff) {
                        pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage);
-                       kfree(buf);
-                       transport_kunmap_data_sg(cmd);
                        return TCM_INVALID_CDB_FIELD;
                }
 
@@ -972,7 +951,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
                pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
                       page, subpage);
 
-       transport_kunmap_data_sg(cmd);
        return TCM_UNKNOWN_MODE_PAGE;
 
 set_length:
@@ -981,12 +959,12 @@ set_length:
        else
                buf[0] = length - 1;
 
-       if (buf != map_buf) {
-               memcpy(map_buf, buf, cmd->data_length);
-               kfree(buf);
+       rbuf = transport_kmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length));
+               transport_kunmap_data_sg(cmd);
        }
 
-       transport_kunmap_data_sg(cmd);
        target_complete_cmd(cmd, GOOD);
        return 0;
 }
index 4225d5e..8e64adf 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd)
        return retval;
 }
 
+/*
+ * usb_hcd_start_port_resume - a root-hub port is sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal is
+ * being sent to a root-hub port.  The root hub will be prevented from
+ * going into autosuspend until usb_hcd_end_port_resume() is called.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum)
+{
+       unsigned bit = 1 << portnum;
+
+       if (!(bus->resuming_ports & bit)) {
+               bus->resuming_ports |= bit;
+               pm_runtime_get_noresume(&bus->root_hub->dev);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume);
+
+/*
+ * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal has
+ * stopped being sent to a root-hub port.  The root hub will be allowed to
+ * autosuspend again.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum)
+{
+       unsigned bit = 1 << portnum;
+
+       if (bus->resuming_ports & bit) {
+               bus->resuming_ports &= ~bit;
+               pm_runtime_put_noidle(&bus->root_hub->dev);
+       }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
 
 /*-------------------------------------------------------------------------*/
 
index 957ed2c..cbf7168 100644 (file)
@@ -2838,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev)
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
 
 #ifdef CONFIG_USB_SUSPEND
+/*
+ * usb_disable_function_remotewakeup - disable usb3.0
+ * device's function remote wakeup
+ * @udev: target device
+ *
+ * Assume there's only one function on the USB 3.0
+ * device and disable remote wake for the first
+ * interface. FIXME if the interface association
+ * descriptor shows there's more than one function.
+ */
+static int usb_disable_function_remotewakeup(struct usb_device *udev)
+{
+       return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
+                               USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+}
 
 /*
  * usb_port_suspend - suspend a usb device's upstream port
@@ -2955,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
                /* paranoia:  "should not happen" */
-               if (udev->do_remote_wakeup)
-                       (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                               USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
-                               USB_DEVICE_REMOTE_WAKEUP, 0,
-                               NULL, 0,
-                               USB_CTRL_SET_TIMEOUT);
+               if (udev->do_remote_wakeup) {
+                       if (!hub_is_superspeed(hub->hdev)) {
+                               (void) usb_control_msg(udev,
+                                               usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
+                                               USB_RECIP_DEVICE,
+                                               USB_DEVICE_REMOTE_WAKEUP, 0,
+                                               NULL, 0,
+                                               USB_CTRL_SET_TIMEOUT);
+                       } else
+                               (void) usb_disable_function_remotewakeup(udev);
+
+               }
 
                /* Try to enable USB2 hardware LPM again */
                if (udev->usb2_hw_lpm_capable == 1)
@@ -3052,20 +3076,30 @@ static int finish_port_resume(struct usb_device *udev)
         * udev->reset_resume
         */
        } else if (udev->actconfig && !udev->reset_resume) {
-               le16_to_cpus(&devstatus);
-               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
-                       status = usb_control_msg(udev,
-                                       usb_sndctrlpipe(udev, 0),
-                                       USB_REQ_CLEAR_FEATURE,
+               if (!hub_is_superspeed(udev->parent)) {
+                       le16_to_cpus(&devstatus);
+                       if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+                               status = usb_control_msg(udev,
+                                               usb_sndctrlpipe(udev, 0),
+                                               USB_REQ_CLEAR_FEATURE,
                                                USB_RECIP_DEVICE,
-                                       USB_DEVICE_REMOTE_WAKEUP, 0,
-                                       NULL, 0,
-                                       USB_CTRL_SET_TIMEOUT);
-                       if (status)
-                               dev_dbg(&udev->dev,
-                                       "disable remote wakeup, status %d\n",
-                                       status);
+                                               USB_DEVICE_REMOTE_WAKEUP, 0,
+                                               NULL, 0,
+                                               USB_CTRL_SET_TIMEOUT);
+               } else {
+                       status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
+                                       &devstatus);
+                       le16_to_cpus(&devstatus);
+                       if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
+                                       | USB_INTRF_STAT_FUNC_RW))
+                               status =
+                                       usb_disable_function_remotewakeup(udev);
                }
+
+               if (status)
+                       dev_dbg(&udev->dev,
+                               "disable remote wakeup, status %d\n",
+                               status);
                status = 0;
        }
        return status;
index 09537b2..b416a3f 100644 (file)
@@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                        ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
                        set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+                       usb_hcd_start_port_resume(&hcd->self, i);
                        mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
                }
        }
index 4ccb97c..4d3b294 100644 (file)
@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                        status = STS_PCD;
                }
        }
-       /* FIXME autosuspend idle root hubs */
+
+       /* If a resume is in progress, make sure it can finish */
+       if (ehci->resuming_ports)
+               mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25));
+
        spin_unlock_irqrestore (&ehci->lock, flags);
        return status ? retval : 0;
 }
@@ -851,6 +855,7 @@ static int ehci_hub_control (
                                /* resume signaling for 20 msec */
                                ehci->reset_done[wIndex] = jiffies
                                                + msecs_to_jiffies(20);
+                               usb_hcd_start_port_resume(&hcd->self, wIndex);
                                /* check the port again */
                                mod_timer(&ehci_to_hcd(ehci)->rh_timer,
                                                ehci->reset_done[wIndex]);
@@ -862,6 +867,7 @@ static int ehci_hub_control (
                                clear_bit(wIndex, &ehci->suspended_ports);
                                set_bit(wIndex, &ehci->port_c_suspend);
                                ehci->reset_done[wIndex] = 0;
+                               usb_hcd_end_port_resume(&hcd->self, wIndex);
 
                                /* stop resume signaling */
                                temp = ehci_readl(ehci, status_reg);
@@ -950,6 +956,7 @@ static int ehci_hub_control (
                        ehci->reset_done[wIndex] = 0;
                        if (temp & PORT_PE)
                                set_bit(wIndex, &ehci->port_c_suspend);
+                       usb_hcd_end_port_resume(&hcd->self, wIndex);
                }
 
                if (temp & PORT_OC)
index 3d98902..fd252f0 100644 (file)
@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
        if (ehci->async_iaa || ehci->async_unlinking)
                return;
 
-       /* Do all the waiting QHs at once */
-       ehci->async_iaa = ehci->async_unlink;
-       ehci->async_unlink = NULL;
-
        /* If the controller isn't running, we don't have to wait for it */
        if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+
+               /* Do all the waiting QHs */
+               ehci->async_iaa = ehci->async_unlink;
+               ehci->async_unlink = NULL;
+
                if (!nested)            /* Avoid recursion */
                        end_unlink_async(ehci);
 
        /* Otherwise start a new IAA cycle */
        } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+               struct ehci_qh          *qh;
+
+               /* Do only the first waiting QH (nVidia bug?) */
+               qh = ehci->async_unlink;
+               ehci->async_iaa = qh;
+               ehci->async_unlink = qh->unlink_next;
+               qh->unlink_next = NULL;
+
                /* Make sure the unlinks are all visible to the hardware */
                wmb();
 
@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)
        }
 }
 
+static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
 static void unlink_empty_async(struct ehci_hcd *ehci)
 {
-       struct ehci_qh          *qh, *next;
-       bool                    stopped = (ehci->rh_state < EHCI_RH_RUNNING);
+       struct ehci_qh          *qh;
+       struct ehci_qh          *qh_to_unlink = NULL;
        bool                    check_unlinks_later = false;
+       int                     count = 0;
 
-       /* Unlink all the async QHs that have been empty for a timer cycle */
-       next = ehci->async->qh_next.qh;
-       while (next) {
-               qh = next;
-               next = qh->qh_next.qh;
-
+       /* Find the last async QH which has been empty for a timer cycle */
+       for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {
                if (list_empty(&qh->qtd_list) &&
                                qh->qh_state == QH_STATE_LINKED) {
-                       if (!stopped && qh->unlink_cycle ==
-                                       ehci->async_unlink_cycle)
+                       ++count;
+                       if (qh->unlink_cycle == ehci->async_unlink_cycle)
                                check_unlinks_later = true;
                        else
-                               single_unlink_async(ehci, qh);
+                               qh_to_unlink = qh;
                }
        }
 
-       /* Start a new IAA cycle if any QHs are waiting for it */
-       if (ehci->async_unlink)
-               start_iaa_cycle(ehci, false);
+       /* If nothing else is being unlinked, unlink the last empty QH */
+       if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+               start_unlink_async(ehci, qh_to_unlink);
+               --count;
+       }
 
-       /* QHs that haven't been empty for long enough will be handled later */
-       if (check_unlinks_later) {
+       /* Other QHs will be handled later */
+       if (count > 0) {
                ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
                ++ehci->async_unlink_cycle;
        }
index 69ebee7..b476daf 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
 }
 
 static const unsigned char
-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
 
 /* carryover low/fullspeed bandwidth that crosses uframe boundries */
 static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
        }
        ehci->now_frame = now_frame;
 
+       frame = ehci->last_iso_frame;
        for (;;) {
                union ehci_shadow       q, *q_p;
                __hc32                  type, *hw_p;
 
-               frame = ehci->last_iso_frame;
 restart:
                /* scan each element in frame's queue for completions */
                q_p = &ehci->pshadow [frame];
@@ -2321,6 +2321,9 @@ restart:
                /* Stop when we have reached the current frame */
                if (frame == now_frame)
                        break;
-               ehci->last_iso_frame = (frame + 1) & fmask;
+
+               /* The last frame may still have active siTDs */
+               ehci->last_iso_frame = frame;
+               frame = (frame + 1) & fmask;
        }
 }
index 20dbdcb..f904071 100644 (file)
@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->ASS_poll_count++ < 20) {
-                       ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
-                       return;
-               }
-               ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
-                               want, actual);
+               /* Poll again later */
+               ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+               ++ehci->ASS_poll_count;
+               return;
        }
+
+       if (ehci->ASS_poll_count > 20)
+               ehci_dbg(ehci, "ASS poll count reached %d\n",
+                               ehci->ASS_poll_count);
        ehci->ASS_poll_count = 0;
 
        /* The status is up-to-date; restart or stop the schedule as needed */
@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->PSS_poll_count++ < 20) {
-                       ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
-                       return;
-               }
-               ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
-                               want, actual);
+               /* Poll again later */
+               ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+               return;
        }
+
+       if (ehci->PSS_poll_count > 20)
+               ehci_dbg(ehci, "PSS poll count reached %d\n",
+                               ehci->PSS_poll_count);
        ehci->PSS_poll_count = 0;
 
        /* The status is up-to-date; restart or stop the schedule as needed */
index a3b6d71..4c338ec 100644 (file)
@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
                                "defaulting to EHCI.\n");
                dev_warn(&xhci_pdev->dev,
                                "USB 3.0 devices will work at USB 2.0 speeds.\n");
+               usb_disable_xhci_ports(xhci_pdev);
                return;
        }
 
index 768d542..15d1322 100644 (file)
@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
                }
        }
        clear_bit(port, &uhci->resuming_ports);
+       usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);
 }
 
 /* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
                                set_bit(port, &uhci->resuming_ports);
                                uhci->ports_timeout = jiffies +
                                                msecs_to_jiffies(25);
+                               usb_hcd_start_port_resume(
+                                               &uhci_to_hcd(uhci)->self, port);
 
                                /* Make sure we see the port again
                                 * after the resuming period is over. */
index 59fb5c6..7f76a49 100644 (file)
@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                                faked_port_index + 1);
                if (slot_id && xhci->devs[slot_id])
                        xhci_ring_device(xhci, slot_id);
-               if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
+               if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {
                        bus_state->port_remote_wakeup &=
                                ~(1 << faked_port_index);
                        xhci_test_and_clear_bit(xhci, port_array,
@@ -2589,6 +2589,8 @@ cleanup:
                                (trb_comp_code != COMP_STALL &&
                                        trb_comp_code != COMP_BABBLE))
                                xhci_urb_free_priv(xhci, urb_priv);
+                       else
+                               kfree(urb_priv);
 
                        usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
                        if ((urb->actual_length != urb->transfer_buffer_length &&
@@ -3108,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
         * running_total.
         */
        packets_transferred = (running_total + trb_buff_len) /
-               usb_endpoint_maxp(&urb->ep->desc);
+               GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
 
        if ((total_packet_count - packets_transferred) > 31)
                return 31 << 17;
@@ -3642,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                td_len = urb->iso_frame_desc[i].length;
                td_remain_len = td_len;
                total_packet_count = DIV_ROUND_UP(td_len,
-                               usb_endpoint_maxp(&urb->ep->desc));
+                               GET_MAX_PACKET(
+                                       usb_endpoint_maxp(&urb->ep->desc)));
                /* A zero-length transfer still involves at least one packet. */
                if (total_packet_count == 0)
                        total_packet_count++;
@@ -3664,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                td = urb_priv->td[i];
                for (j = 0; j < trbs_per_td; j++) {
                        u32 remainder = 0;
-                       field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
+                       field = 0;
 
                        if (first_trb) {
+                               field = TRB_TBC(burst_count) |
+                                       TRB_TLBPC(residue);
                                /* Queue the isoc TRB */
                                field |= TRB_TYPE(TRB_ISOC);
                                /* Assume URB_ISO_ASAP is set */
index f14736f..edc0f0d 100644 (file)
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
        { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
        { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+       { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
        { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
index ba68835..90ceef1 100644 (file)
@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = {
        /*
         * ELV devices:
         */
+       { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
        { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
index fa5d560..9d359e1 100644 (file)
 #define XSENS_CONVERTER_6_PID  0xD38E
 #define XSENS_CONVERTER_7_PID  0xD38F
 
+/**
+ * Zolix (www.zolix.com.cb) product ids
+ */
+#define FTDI_OMNI1509                  0xD491  /* Omni1509 embedded USB-serial */
+
 /*
  * NDI (www.ndigital.com) product ids
  */
 
 /*
  * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
+ * Almost all of these devices use FTDI's vendor ID (0x0403).
  * Further IDs taken from ELV Windows .inf file.
  *
  * The previously included PID for the UO 100 module was incorrect.
  *
  * Armin Laeuger originally sent the PID for the UM 100 module.
  */
+#define FTDI_ELV_VID   0x1B1F  /* ELV AG */
+#define FTDI_ELV_WS300_PID     0xC006  /* eQ3 WS 300 PC II */
 #define FTDI_ELV_USR_PID       0xE000  /* ELV Universal-Sound-Recorder */
 #define FTDI_ELV_MSM1_PID      0xE001  /* ELV Mini-Sound-Modul */
 #define FTDI_ELV_KL100_PID     0xE002  /* ELV Kfz-Leistungsmesser KL 100 */
index 0d9dac9..567bc77 100644 (file)
@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_CC864_DUAL               0x1005
 #define TELIT_PRODUCT_CC864_SINGLE             0x1006
 #define TELIT_PRODUCT_DE910_DUAL               0x1010
+#define TELIT_PRODUCT_LE920                    0x1200
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID                          0x19d2
@@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb);
 #define TPLINK_VENDOR_ID                       0x2357
 #define TPLINK_PRODUCT_MA180                   0x0201
 
+/* Changhong products */
+#define CHANGHONG_VENDOR_ID                    0x2077
+#define CHANGHONG_PRODUCT_CH690                        0x7001
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -534,6 +539,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
        .reserved = BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info telit_le920_blacklist = {
+       .sendsetup = BIT(0),
+       .reserved = BIT(1) | BIT(5),
+};
+
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -784,6 +794,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+               .driver_info = (kernel_ulong_t)&telit_le920_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -1318,6 +1330,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
        { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index aa148c2..2466254 100644 (file)
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_G1K(0x05c6, 0x9221)},   /* Generic Gobi QDL device */
        {DEVICE_G1K(0x05c6, 0x9231)},   /* Generic Gobi QDL device */
        {DEVICE_G1K(0x1f45, 0x0001)},   /* Unknown Gobi QDL device */
+       {DEVICE_G1K(0x1bc7, 0x900e)},   /* Telit Gobi QDL device */
 
        /* Gobi 2000 devices */
        {USB_DEVICE(0x1410, 0xa010)},   /* Novatel Gobi 2000 QDL device */
index 105d900..16b0bf0 100644 (file)
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        return 0;
 }
 
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us)
+/* This places the HUAWEI usb dongles in multi-port mode */
+static int usb_stor_huawei_feature_init(struct us_data *us)
 {
        int result;
 
@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us)
        US_DEBUGP("Huawei mode set result is %d\n", result);
        return 0;
 }
+
+/*
+ * It will send a scsi switch command called rewind' to huawei dongle.
+ * When the dongle receives this command at the first time,
+ * it will reboot immediately. After rebooted, it will ignore this command.
+ * So it is  unnecessary to read its response.
+ */
+static int usb_stor_huawei_scsi_init(struct us_data *us)
+{
+       int result = 0;
+       int act_len = 0;
+       struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
+       char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
+                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+       bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcbw->Tag = 0;
+       bcbw->DataTransferLength = 0;
+       bcbw->Flags = bcbw->Lun = 0;
+       bcbw->Length = sizeof(rewind_cmd);
+       memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
+       memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
+
+       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
+                                       US_BULK_CB_WRAP_LEN, &act_len);
+       US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
+       return result;
+}
+
+/*
+ * It tries to find the supported Huawei USB dongles.
+ * In Huawei, they assign the following product IDs
+ * for all of their mobile broadband dongles,
+ * including the new dongles in the future.
+ * So if the product ID is not included in this list,
+ * it means it is not Huawei's mobile broadband dongles.
+ */
+static int usb_stor_huawei_dongles_pid(struct us_data *us)
+{
+       struct usb_interface_descriptor *idesc;
+       int idProduct;
+
+       idesc = &us->pusb_intf->cur_altsetting->desc;
+       idProduct = us->pusb_dev->descriptor.idProduct;
+       /* The first port is CDROM,
+        * means the dongle in the single port mode,
+        * and a switch command is required to be sent. */
+       if (idesc && idesc->bInterfaceNumber == 0) {
+               if ((idProduct == 0x1001)
+                       || (idProduct == 0x1003)
+                       || (idProduct == 0x1004)
+                       || (idProduct >= 0x1401 && idProduct <= 0x1500)
+                       || (idProduct >= 0x1505 && idProduct <= 0x1600)
+                       || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+int usb_stor_huawei_init(struct us_data *us)
+{
+       int result = 0;
+
+       if (usb_stor_huawei_dongles_pid(us)) {
+               if (us->pusb_dev->descriptor.idProduct >= 0x1446)
+                       result = usb_stor_huawei_scsi_init(us);
+               else
+                       result = usb_stor_huawei_feature_init(us);
+       }
+       return result;
+}
index 529327f..5376d4f 100644 (file)
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
 
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us);
+/* This places the HUAWEI usb dongles in multi-port mode */
+int usb_stor_huawei_init(struct us_data *us);
index d305a5a..72923b5 100644 (file)
@@ -1527,335 +1527,10 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 /* Reported by fangxiaozhi <huananhu@huawei.com>
  * This brings the HUAWEI data card devices into multi-port mode
  */
-UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
+UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
                "HUAWEI MOBILE",
                "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
-               0),
-UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
-               "HUAWEI MOBILE",
-               "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
                0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
index 31b3e1a..cf09b6b 100644 (file)
@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
        .useTransport = use_transport,  \
 }
 
+#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
+               vendor_name, product_name, use_protocol, use_transport, \
+               init_function, Flags) \
+{ \
+       .vendorName = vendor_name,      \
+       .productName = product_name,    \
+       .useProtocol = use_protocol,    \
+       .useTransport = use_transport,  \
+       .initFunction = init_function,  \
+}
+
 static struct us_unusual_dev us_unusual_dev_list[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids =
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
 
 #ifdef CONFIG_LOCKDEP
 
index b78a526..5ef8ce7 100644 (file)
 #define USUAL_DEV(useProto, useTrans) \
 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) }
 
+/* Define the device is matched with Vendor ID and interface descriptors */
+#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \
+                       vendorName, productName, useProtocol, useTransport, \
+                       initFunction, flags) \
+{ \
+       .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+                               | USB_DEVICE_ID_MATCH_VENDOR, \
+       .idVendor    = (id_vendor), \
+       .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), \
+       .bInterfaceProtocol = (pr), \
+       .driver_info = (flags) \
+}
+
 struct usb_device_id usb_storage_usb_ids[] = {
 #      include "unusual_devs.h"
        { }             /* Terminating entry */
@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
 
 /*
  * The table of devices to ignore
index ebd08b2..959b1cd 100644 (file)
@@ -165,12 +165,16 @@ static void tx_poll_stop(struct vhost_net *net)
 }
 
 /* Caller must have TX VQ lock */
-static void tx_poll_start(struct vhost_net *net, struct socket *sock)
+static int tx_poll_start(struct vhost_net *net, struct socket *sock)
 {
+       int ret;
+
        if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED))
-               return;
-       vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
-       net->tx_poll_state = VHOST_NET_POLL_STARTED;
+               return 0;
+       ret = vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
+       if (!ret)
+               net->tx_poll_state = VHOST_NET_POLL_STARTED;
+       return ret;
 }
 
 /* In case of DMA done not in order in lower device driver for some reason.
@@ -642,20 +646,23 @@ static void vhost_net_disable_vq(struct vhost_net *n,
                vhost_poll_stop(n->poll + VHOST_NET_VQ_RX);
 }
 
-static void vhost_net_enable_vq(struct vhost_net *n,
+static int vhost_net_enable_vq(struct vhost_net *n,
                                struct vhost_virtqueue *vq)
 {
        struct socket *sock;
+       int ret;
 
        sock = rcu_dereference_protected(vq->private_data,
                                         lockdep_is_held(&vq->mutex));
        if (!sock)
-               return;
+               return 0;
        if (vq == n->vqs + VHOST_NET_VQ_TX) {
                n->tx_poll_state = VHOST_NET_POLL_STOPPED;
-               tx_poll_start(n, sock);
+               ret = tx_poll_start(n, sock);
        } else
-               vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+               ret = vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+
+       return ret;
 }
 
 static struct socket *vhost_net_stop_vq(struct vhost_net *n,
@@ -827,15 +834,18 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
                        r = PTR_ERR(ubufs);
                        goto err_ubufs;
                }
-               oldubufs = vq->ubufs;
-               vq->ubufs = ubufs;
+
                vhost_net_disable_vq(n, vq);
                rcu_assign_pointer(vq->private_data, sock);
-               vhost_net_enable_vq(n, vq);
-
                r = vhost_init_used(vq);
                if (r)
-                       goto err_vq;
+                       goto err_used;
+               r = vhost_net_enable_vq(n, vq);
+               if (r)
+                       goto err_used;
+
+               oldubufs = vq->ubufs;
+               vq->ubufs = ubufs;
 
                n->tx_packets = 0;
                n->tx_zcopy_err = 0;
@@ -859,6 +869,11 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        mutex_unlock(&n->dev.mutex);
        return 0;
 
+err_used:
+       rcu_assign_pointer(vq->private_data, oldsock);
+       vhost_net_enable_vq(n, vq);
+       if (ubufs)
+               vhost_ubuf_put_and_wait(ubufs);
 err_ubufs:
        fput(sock->file);
 err_vq:
index b20df5c..22321cf 100644 (file)
@@ -575,10 +575,8 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs)
 
        /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */
        tv_tpg = vs->vs_tpg;
-       if (unlikely(!tv_tpg)) {
-               pr_err("%s endpoint not set\n", __func__);
+       if (unlikely(!tv_tpg))
                return;
-       }
 
        mutex_lock(&vq->mutex);
        vhost_disable_notify(&vs->dev, vq);
index 34389f7..9759249 100644 (file)
@@ -77,26 +77,38 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
        init_poll_funcptr(&poll->table, vhost_poll_func);
        poll->mask = mask;
        poll->dev = dev;
+       poll->wqh = NULL;
 
        vhost_work_init(&poll->work, fn);
 }
 
 /* Start polling a file. We add ourselves to file's wait queue. The caller must
  * keep a reference to a file until after vhost_poll_stop is called. */
-void vhost_poll_start(struct vhost_poll *poll, struct file *file)
+int vhost_poll_start(struct vhost_poll *poll, struct file *file)
 {
        unsigned long mask;
+       int ret = 0;
 
        mask = file->f_op->poll(file, &poll->table);
        if (mask)
                vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
+       if (mask & POLLERR) {
+               if (poll->wqh)
+                       remove_wait_queue(poll->wqh, &poll->wait);
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
 
 /* Stop polling a file. After this function returns, it becomes safe to drop the
  * file reference. You must also flush afterwards. */
 void vhost_poll_stop(struct vhost_poll *poll)
 {
-       remove_wait_queue(poll->wqh, &poll->wait);
+       if (poll->wqh) {
+               remove_wait_queue(poll->wqh, &poll->wait);
+               poll->wqh = NULL;
+       }
 }
 
 static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work,
@@ -792,7 +804,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
                fput(filep);
 
        if (pollstart && vq->handle_kick)
-               vhost_poll_start(&vq->poll, vq->kick);
+               r = vhost_poll_start(&vq->poll, vq->kick);
 
        mutex_unlock(&vq->mutex);
 
index 2639c58..17261e2 100644 (file)
@@ -42,7 +42,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);
 
 void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
                     unsigned long mask, struct vhost_dev *dev);
-void vhost_poll_start(struct vhost_poll *poll, struct file *file);
+int vhost_poll_start(struct vhost_poll *poll, struct file *file);
 void vhost_poll_stop(struct vhost_poll *poll);
 void vhost_poll_flush(struct vhost_poll *poll);
 void vhost_poll_queue(struct vhost_poll *poll);
index 0be4df3..74d77df 100644 (file)
@@ -840,7 +840,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
 
        if (irq == -1) {
                irq = xen_allocate_irq_dynamic();
-               if (irq == -1)
+               if (irq < 0)
                        goto out;
 
                irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
@@ -944,7 +944,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 
        if (irq == -1) {
                irq = xen_allocate_irq_dynamic();
-               if (irq == -1)
+               if (irq < 0)
                        goto out;
 
                irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
index 97f5d26..37c1f82 100644 (file)
@@ -135,7 +135,6 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
                         struct pci_dev *dev, struct xen_pci_op *op)
 {
        struct xen_pcibk_dev_data *dev_data;
-       int otherend = pdev->xdev->otherend_id;
        int status;
 
        if (unlikely(verbose_request))
@@ -144,8 +143,9 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
        status = pci_enable_msi(dev);
 
        if (status) {
-               printk(KERN_ERR "error enable msi for guest %x status %x\n",
-                       otherend, status);
+               pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI for guest %u: err %d\n",
+                                   pci_name(dev), pdev->xdev->otherend_id,
+                                   status);
                op->value = 0;
                return XEN_PCI_ERR_op_failed;
        }
@@ -223,10 +223,10 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
                                                pci_name(dev), i,
                                                op->msix_entries[i].vector);
                }
-       } else {
-               printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n",
-                       pci_name(dev), result);
-       }
+       } else
+               pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI-X for guest %u: err %d!\n",
+                                   pci_name(dev), pdev->xdev->otherend_id,
+                                   result);
        kfree(entries);
 
        op->value = result;
index a8b8adc..5a3327b 100644 (file)
@@ -4534,7 +4534,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        unsigned nr_extents = 0;
        int extra_reserve = 0;
        enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
-       int ret;
+       int ret = 0;
        bool delalloc_lock = true;
 
        /* If we are a free space inode we need to not flush since we will be in
@@ -4579,20 +4579,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        csum_bytes = BTRFS_I(inode)->csum_bytes;
        spin_unlock(&BTRFS_I(inode)->lock);
 
-       if (root->fs_info->quota_enabled) {
+       if (root->fs_info->quota_enabled)
                ret = btrfs_qgroup_reserve(root, num_bytes +
                                           nr_extents * root->leafsize);
-               if (ret) {
-                       spin_lock(&BTRFS_I(inode)->lock);
-                       calc_csum_metadata_size(inode, num_bytes, 0);
-                       spin_unlock(&BTRFS_I(inode)->lock);
-                       if (delalloc_lock)
-                               mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
-                       return ret;
-               }
-       }
 
-       ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
+       /*
+        * ret != 0 here means the qgroup reservation failed, we go straight to
+        * the shared error handling then.
+        */
+       if (ret == 0)
+               ret = reserve_metadata_bytes(root, block_rsv,
+                                            to_reserve, flush);
+
        if (ret) {
                u64 to_free = 0;
                unsigned dropped;
index 2e8cae6..fdb7a8d 100644 (file)
@@ -288,7 +288,8 @@ out:
 void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)
 {
        clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
-       try_merge_map(tree, em);
+       if (em->in_tree)
+               try_merge_map(tree, em);
 }
 
 /**
index f76b1fd..aeb8446 100644 (file)
@@ -293,15 +293,24 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
        struct btrfs_key key;
        struct btrfs_ioctl_defrag_range_args range;
        int num_defrag;
+       int index;
+       int ret;
 
        /* get the inode */
        key.objectid = defrag->root;
        btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
        key.offset = (u64)-1;
+
+       index = srcu_read_lock(&fs_info->subvol_srcu);
+
        inode_root = btrfs_read_fs_root_no_name(fs_info, &key);
        if (IS_ERR(inode_root)) {
-               kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
-               return PTR_ERR(inode_root);
+               ret = PTR_ERR(inode_root);
+               goto cleanup;
+       }
+       if (btrfs_root_refs(&inode_root->root_item) == 0) {
+               ret = -ENOENT;
+               goto cleanup;
        }
 
        key.objectid = defrag->ino;
@@ -309,9 +318,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
        key.offset = 0;
        inode = btrfs_iget(fs_info->sb, &key, inode_root, NULL);
        if (IS_ERR(inode)) {
-               kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
-               return PTR_ERR(inode);
+               ret = PTR_ERR(inode);
+               goto cleanup;
        }
+       srcu_read_unlock(&fs_info->subvol_srcu, index);
 
        /* do a chunk of defrag */
        clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags);
@@ -346,6 +356,10 @@ static int __btrfs_run_defrag_inode(struct btrfs_fs_info *fs_info,
 
        iput(inode);
        return 0;
+cleanup:
+       srcu_read_unlock(&fs_info->subvol_srcu, index);
+       kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
+       return ret;
 }
 
 /*
@@ -1594,9 +1608,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
                if (err < 0 && num_written > 0)
                        num_written = err;
        }
-out:
+
        if (sync)
                atomic_dec(&BTRFS_I(inode)->sync_writers);
+out:
        sb_end_write(inode->i_sb);
        current->backing_dev_info = NULL;
        return num_written ? num_written : err;
index 5b22d45..338f259 100644 (file)
@@ -515,7 +515,6 @@ static noinline int create_subvol(struct btrfs_root *root,
 
        BUG_ON(ret);
 
-       d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
        if (async_transid) {
                *async_transid = trans->transid;
@@ -525,6 +524,10 @@ fail:
        }
        if (err && !ret)
                ret = err;
+
+       if (!ret)
+               d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
+
        return ret;
 }
 
index f107312..e5ed567 100644 (file)
@@ -836,9 +836,16 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
         * if the disk i_size is already at the inode->i_size, or
         * this ordered extent is inside the disk i_size, we're done
         */
-       if (disk_i_size == i_size || offset <= disk_i_size) {
+       if (disk_i_size == i_size)
+               goto out;
+
+       /*
+        * We still need to update disk_i_size if outstanding_isize is greater
+        * than disk_i_size.
+        */
+       if (offset <= disk_i_size &&
+           (!ordered || ordered->outstanding_isize <= disk_i_size))
                goto out;
-       }
 
        /*
         * walk backward from this ordered extent to disk_i_size.
@@ -870,7 +877,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
                        break;
                if (test->file_offset >= i_size)
                        break;
-               if (test->file_offset >= disk_i_size) {
+               if (entry_end(test) > disk_i_size) {
                        /*
                         * we don't update disk_i_size now, so record this
                         * undealt i_size. Or we will not know the real
index bdbb94f..67783e0 100644 (file)
@@ -580,20 +580,29 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
        int corrected = 0;
        struct btrfs_key key;
        struct inode *inode = NULL;
+       struct btrfs_fs_info *fs_info;
        u64 end = offset + PAGE_SIZE - 1;
        struct btrfs_root *local_root;
+       int srcu_index;
 
        key.objectid = root;
        key.type = BTRFS_ROOT_ITEM_KEY;
        key.offset = (u64)-1;
-       local_root = btrfs_read_fs_root_no_name(fixup->root->fs_info, &key);
-       if (IS_ERR(local_root))
+
+       fs_info = fixup->root->fs_info;
+       srcu_index = srcu_read_lock(&fs_info->subvol_srcu);
+
+       local_root = btrfs_read_fs_root_no_name(fs_info, &key);
+       if (IS_ERR(local_root)) {
+               srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
                return PTR_ERR(local_root);
+       }
 
        key.type = BTRFS_INODE_ITEM_KEY;
        key.objectid = inum;
        key.offset = 0;
-       inode = btrfs_iget(fixup->root->fs_info->sb, &key, local_root, NULL);
+       inode = btrfs_iget(fs_info->sb, &key, local_root, NULL);
+       srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
@@ -606,7 +615,6 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
        }
 
        if (PageUptodate(page)) {
-               struct btrfs_fs_info *fs_info;
                if (PageDirty(page)) {
                        /*
                         * we need to write the data to the defect sector. the
@@ -3180,18 +3188,25 @@ static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx)
        u64 physical_for_dev_replace;
        u64 len;
        struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info;
+       int srcu_index;
 
        key.objectid = root;
        key.type = BTRFS_ROOT_ITEM_KEY;
        key.offset = (u64)-1;
+
+       srcu_index = srcu_read_lock(&fs_info->subvol_srcu);
+
        local_root = btrfs_read_fs_root_no_name(fs_info, &key);
-       if (IS_ERR(local_root))
+       if (IS_ERR(local_root)) {
+               srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
                return PTR_ERR(local_root);
+       }
 
        key.type = BTRFS_INODE_ITEM_KEY;
        key.objectid = inum;
        key.offset = 0;
        inode = btrfs_iget(fs_info->sb, &key, local_root, NULL);
+       srcu_read_unlock(&fs_info->subvol_srcu, srcu_index);
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
index f154946..fc03aa6 100644 (file)
@@ -333,12 +333,14 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
                                          &root->fs_info->trans_block_rsv,
                                          num_bytes, flush);
                if (ret)
-                       return ERR_PTR(ret);
+                       goto reserve_fail;
        }
 again:
        h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
-       if (!h)
-               return ERR_PTR(-ENOMEM);
+       if (!h) {
+               ret = -ENOMEM;
+               goto alloc_fail;
+       }
 
        /*
         * If we are JOIN_NOLOCK we're already committing a transaction and
@@ -365,11 +367,7 @@ again:
        if (ret < 0) {
                /* We must get the transaction if we are JOIN_NOLOCK. */
                BUG_ON(type == TRANS_JOIN_NOLOCK);
-
-               if (type < TRANS_JOIN_NOLOCK)
-                       sb_end_intwrite(root->fs_info->sb);
-               kmem_cache_free(btrfs_trans_handle_cachep, h);
-               return ERR_PTR(ret);
+               goto join_fail;
        }
 
        cur_trans = root->fs_info->running_transaction;
@@ -410,6 +408,19 @@ got_it:
        if (!current->journal_info && type != TRANS_USERSPACE)
                current->journal_info = h;
        return h;
+
+join_fail:
+       if (type < TRANS_JOIN_NOLOCK)
+               sb_end_intwrite(root->fs_info->sb);
+       kmem_cache_free(btrfs_trans_handle_cachep, h);
+alloc_fail:
+       if (num_bytes)
+               btrfs_block_rsv_release(root, &root->fs_info->trans_block_rsv,
+                                       num_bytes);
+reserve_fail:
+       if (qgroup_reserved)
+               btrfs_qgroup_free(root, qgroup_reserved);
+       return ERR_PTR(ret);
 }
 
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
index 15f6efd..5cbb7f4 100644 (file)
@@ -1556,7 +1556,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        ret = 0;
 
        /* Notify udev that device has changed */
-       btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
+       if (bdev)
+               btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
 
 error_brelse:
        brelse(bh);
index 7ff4985..911649a 100644 (file)
@@ -503,11 +503,11 @@ static ssize_t device_write(struct file *file, const char __user *buf,
 #endif
                return -EINVAL;
 
-#ifdef CONFIG_COMPAT
-       if (count > sizeof(struct dlm_write_request32) + DLM_RESNAME_MAXLEN)
-#else
+       /*
+        * can't compare against COMPAT/dlm_write_request32 because
+        * we don't yet know if is64bit is zero
+        */
        if (count > sizeof(struct dlm_write_request) + DLM_RESNAME_MAXLEN)
-#endif
                return -EINVAL;
 
        kbuf = kzalloc(count + 1, GFP_NOFS);
index dd057bc..fc8dc20 100644 (file)
@@ -177,11 +177,31 @@ out_nofree:
        return mnt;
 }
 
+static int
+nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+       if (NFS_FH(dentry->d_inode)->size != 0)
+               return nfs_getattr(mnt, dentry, stat);
+       generic_fillattr(dentry->d_inode, stat);
+       return 0;
+}
+
+static int
+nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       if (NFS_FH(dentry->d_inode)->size != 0)
+               return nfs_setattr(dentry, attr);
+       return -EACCES;
+}
+
 const struct inode_operations nfs_mountpoint_inode_operations = {
        .getattr        = nfs_getattr,
+       .setattr        = nfs_setattr,
 };
 
 const struct inode_operations nfs_referral_inode_operations = {
+       .getattr        = nfs_namespace_getattr,
+       .setattr        = nfs_namespace_setattr,
 };
 
 static void nfs_expire_automounts(struct work_struct *work)
index acc3472..2e9779b 100644 (file)
@@ -236,11 +236,10 @@ 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;
-               nfs_put_client(clp);
                clp = old;
-               atomic_inc(&clp->cl_count);
        }
 
        return clp;
@@ -306,7 +305,7 @@ int nfs40_walk_client_list(struct nfs_client *new,
                .clientid       = new->cl_clientid,
                .confirm        = new->cl_confirm,
        };
-       int status;
+       int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
        list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -332,40 +331,33 @@ int nfs40_walk_client_list(struct nfs_client *new,
 
                if (prev)
                        nfs_put_client(prev);
+               prev = pos;
 
                status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
-               if (status == 0) {
+               switch (status) {
+               case -NFS4ERR_STALE_CLIENTID:
+                       break;
+               case 0:
                        nfs4_swap_callback_idents(pos, new);
 
-                       nfs_put_client(pos);
+                       prev = NULL;
                        *result = pos;
                        dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
                                __func__, pos, atomic_read(&pos->cl_count));
-                       return 0;
-               }
-               if (status != -NFS4ERR_STALE_CLIENTID) {
-                       nfs_put_client(pos);
-                       dprintk("NFS: <-- %s status = %d, no result\n",
-                               __func__, status);
-                       return status;
+               default:
+                       goto out;
                }
 
                spin_lock(&nn->nfs_client_lock);
-               prev = pos;
        }
+       spin_unlock(&nn->nfs_client_lock);
 
-       /*
-        * No matching nfs_client found.  This should be impossible,
-        * because the new nfs_client has already been added to
-        * nfs_client_list by nfs_get_client().
-        *
-        * Don't BUG(), since the caller is holding a mutex.
-        */
+       /* No match found. The server lost our clientid */
+out:
        if (prev)
                nfs_put_client(prev);
-       spin_unlock(&nn->nfs_client_lock);
-       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-       return -NFS4ERR_STALE_CLIENTID;
+       dprintk("NFS: <-- %s status = %d\n", __func__, status);
+       return status;
 }
 
 #ifdef CONFIG_NFS_V4_1
@@ -432,7 +424,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
 {
        struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
        struct nfs_client *pos, *n, *prev = NULL;
-       int error;
+       int status = -NFS4ERR_STALE_CLIENTID;
 
        spin_lock(&nn->nfs_client_lock);
        list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -448,14 +440,17 @@ int nfs41_walk_client_list(struct nfs_client *new,
                                nfs_put_client(prev);
                        prev = pos;
 
-                       error = nfs_wait_client_init_complete(pos);
-                       if (error < 0) {
+                       nfs4_schedule_lease_recovery(pos);
+                       status = nfs_wait_client_init_complete(pos);
+                       if (status < 0) {
                                nfs_put_client(pos);
                                spin_lock(&nn->nfs_client_lock);
                                continue;
                        }
-
+                       status = pos->cl_cons_state;
                        spin_lock(&nn->nfs_client_lock);
+                       if (status < 0)
+                               continue;
                }
 
                if (pos->rpc_ops != new->rpc_ops)
@@ -473,6 +468,7 @@ int nfs41_walk_client_list(struct nfs_client *new,
                if (!nfs4_match_serverowners(pos, new))
                        continue;
 
+               atomic_inc(&pos->cl_count);
                spin_unlock(&nn->nfs_client_lock);
                dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
                        __func__, pos, atomic_read(&pos->cl_count));
@@ -481,16 +477,10 @@ int nfs41_walk_client_list(struct nfs_client *new,
                return 0;
        }
 
-       /*
-        * No matching nfs_client found.  This should be impossible,
-        * because the new nfs_client has already been added to
-        * nfs_client_list by nfs_get_client().
-        *
-        * Don't BUG(), since the caller is holding a mutex.
-        */
+       /* No matching nfs_client found. */
        spin_unlock(&nn->nfs_client_lock);
-       pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-       return -NFS4ERR_STALE_CLIENTID;
+       dprintk("NFS: <-- %s status = %d\n", __func__, status);
+       return status;
 }
 #endif /* CONFIG_NFS_V4_1 */
 
index 9448c57..e61f68d 100644 (file)
@@ -136,16 +136,11 @@ int nfs40_discover_server_trunking(struct nfs_client *clp,
        clp->cl_confirm = clid.confirm;
 
        status = nfs40_walk_client_list(clp, result, cred);
-       switch (status) {
-       case -NFS4ERR_STALE_CLIENTID:
-               set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
-       case 0:
+       if (status == 0) {
                /* Sustain the lease, even if it's empty.  If the clientid4
                 * goes stale it's of no use for trunking discovery. */
                nfs4_schedule_state_renewal(*result);
-               break;
        }
-
 out:
        return status;
 }
@@ -1863,6 +1858,7 @@ again:
        case -ETIMEDOUT:
        case -EAGAIN:
                ssleep(1);
+       case -NFS4ERR_STALE_CLIENTID:
                dprintk("NFS: %s after status %d, retrying\n",
                        __func__, status);
                goto again;
@@ -2022,8 +2018,18 @@ static int nfs4_reset_session(struct nfs_client *clp)
        nfs4_begin_drain_session(clp);
        cred = nfs4_get_exchange_id_cred(clp);
        status = nfs4_proc_destroy_session(clp->cl_session, cred);
-       if (status && status != -NFS4ERR_BADSESSION &&
-           status != -NFS4ERR_DEADSESSION) {
+       switch (status) {
+       case 0:
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+               break;
+       case -NFS4ERR_BACK_CHAN_BUSY:
+       case -NFS4ERR_DELAY:
+               set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+               status = 0;
+               ssleep(1);
+               goto out;
+       default:
                status = nfs4_recovery_handle_error(clp, status);
                goto out;
        }
index 2e7e8c8..b056b16 100644 (file)
@@ -2589,27 +2589,23 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
        struct nfs_server *server;
        struct dentry *mntroot = ERR_PTR(-ENOMEM);
        struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
-       int error;
 
-       dprintk("--> nfs_xdev_mount_common()\n");
+       dprintk("--> nfs_xdev_mount()\n");
 
        mount_info.mntfh = mount_info.cloned->fh;
 
        /* create a new volume representation */
        server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
-       if (IS_ERR(server)) {
-               error = PTR_ERR(server);
-               goto out_err;
-       }
 
-       mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod);
-       dprintk("<-- nfs_xdev_mount_common() = 0\n");
-out:
-       return mntroot;
+       if (IS_ERR(server))
+               mntroot = ERR_CAST(server);
+       else
+               mntroot = nfs_fs_mount_common(server, flags,
+                               dev_name, &mount_info, nfs_mod);
 
-out_err:
-       dprintk("<-- nfs_xdev_mount_common() = %d [error]\n", error);
-       goto out;
+       dprintk("<-- nfs_xdev_mount() = %ld\n",
+                       IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
+       return mntroot;
 }
 
 #if IS_ENABLED(CONFIG_NFS_V4)
index fdb1807..f385935 100644 (file)
@@ -664,8 +664,11 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
        if (ret < 0)
                printk(KERN_ERR "NILFS: GC failed during preparation: "
                        "cannot read source blocks: err=%d\n", ret);
-       else
+       else {
+               if (nilfs_sb_need_update(nilfs))
+                       set_nilfs_discontinued(nilfs);
                ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
+       }
 
        nilfs_remove_all_gcinodes(nilfs);
        clear_nilfs_gc_running(nilfs);
index c80c599..fc62ac5 100644 (file)
 #define TRACE_SYSCALLS()
 #endif
 
+#ifdef CONFIG_CLKSRC_OF
+#define CLKSRC_OF_TABLES() . = ALIGN(8);                               \
+                          VMLINUX_SYMBOL(__clksrc_of_table) = .;       \
+                          *(__clksrc_of_table)                         \
+                          *(__clksrc_of_table_end)
+#else
+#define CLKSRC_OF_TABLES()
+#endif
+
 #ifdef CONFIG_IRQCHIP
 #define IRQCHIP_OF_MATCH_TABLE()                                       \
        . = ALIGN(8);                                                   \
        DEV_DISCARD(init.rodata)                                        \
        CPU_DISCARD(init.rodata)                                        \
        MEM_DISCARD(init.rodata)                                        \
+       CLKSRC_OF_TABLES()                                              \
        KERNEL_DTB()                                                    \
        IRQCHIP_OF_MATCH_TABLE()
 
index 25680fe..ca17aa8 100644 (file)
@@ -17,6 +17,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer bcm2835_timer;
+extern void bcm2835_timer_init(void);
 
 #endif
index 4dceaf8..7944f14 100644 (file)
@@ -332,4 +332,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
+#ifdef CONFIG_CLKSRC_OF
+extern void clocksource_of_init(void);
+
+#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)                       \
+       static const struct of_device_id __clksrc_of_table_##name       \
+               __used __section(__clksrc_of_table)                     \
+                = { .compatible = compat, .data = fn };
+#endif
+
 #endif /* _LINUX_CLOCKSOURCE_H */
index 1148575..dd755ce 100644 (file)
@@ -53,5 +53,5 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
 cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
 void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
 
-extern struct sys_timer dw_apb_timer;
+extern void dw_apb_timer_init(void);
 #endif /* __DW_APB_TIMER_H__ */
index a5199f6..d0ab98f 100644 (file)
@@ -125,6 +125,31 @@ static inline void init_llist_head(struct llist_head *list)
             (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
 
 /**
+ * llist_for_each_entry_safe - iterate safely against remove over some entries
+ * of lock-less list of given type.
+ * @pos:       the type * to use as a loop cursor.
+ * @n:         another type * to use as a temporary storage.
+ * @node:      the fist entry of deleted list entries.
+ * @member:    the name of the llist_node with the struct.
+ *
+ * In general, some entries of the lock-less list can be traversed
+ * safely only after being removed from list, so start with an entry
+ * instead of list head. This variant allows removal of entries
+ * as we iterate.
+ *
+ * If being used on entries deleted from lock-less list directly, the
+ * traverse order is from the newest to the oldest added entry.  If
+ * you want to traverse from the oldest to the newest, you must
+ * reverse the order by yourself before traversing.
+ */
+#define llist_for_each_entry_safe(pos, n, node, member)                \
+       for ((pos) = llist_entry((node), typeof(*(pos)), member),       \
+            (n) = (pos)->member.next;                                  \
+            &(pos)->member != NULL;                                    \
+            (pos) = llist_entry(n, typeof(*(pos)), member),            \
+            (n) = (&(pos)->member != NULL) ? (pos)->member.next : NULL)
+
+/**
  * llist_empty - tests whether a lock-less list is empty
  * @head:      the list to test
  *
index 0108a56..28bd5fa 100644 (file)
@@ -429,7 +429,7 @@ extern int memcg_limited_groups_array_size;
  * the slab_mutex must be held when looping through those caches
  */
 #define for_each_memcg_cache_index(_idx)       \
-       for ((_idx) = 0; i < memcg_limited_groups_array_size; (_idx)++)
+       for ((_idx) = 0; (_idx) < memcg_limited_groups_array_size; (_idx)++)
 
 static inline bool memcg_kmem_enabled(void)
 {
index bc823c4..deca874 100644 (file)
@@ -151,7 +151,7 @@ struct mmu_notifier_ops {
  * Therefore notifier chains can only be traversed when either
  *
  * 1. mmap_sem is held.
- * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->mutex).
+ * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->rwsem).
  * 3. No other concurrent thread can access the list (release)
  */
 struct mmu_notifier {
index b9165bb..1808178 100644 (file)
@@ -19,6 +19,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer sunxi_timer;
+void sunxi_timer_init(void);
 
 #endif
index 4d358e9..05e32a7 100644 (file)
@@ -142,9 +142,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta);
  * finer then tick granular time.
  */
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-extern u32 arch_gettimeoffset(void);
-#else
-static inline u32 arch_gettimeoffset(void) { return 0; }
+extern u32 (*arch_gettimeoffset)(void);
 #endif
 
 extern void do_gettimeofday(struct timeval *tv);
index 689b14b..4d22d0f 100644 (file)
@@ -357,6 +357,8 @@ struct usb_bus {
        int bandwidth_int_reqs;         /* number of Interrupt requests */
        int bandwidth_isoc_reqs;        /* number of Isoc. requests */
 
+       unsigned resuming_ports;        /* bit array: resuming root-hub ports */
+
 #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
        struct mon_bus *mon_bus;        /* non-null when associated */
        int monitored;                  /* non-zero when monitored */
index 608050b..0a78df5 100644 (file)
@@ -430,6 +430,9 @@ extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
 extern void usb_wakeup_notification(struct usb_device *hdev,
                unsigned int portnum);
 
+extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
+extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
+
 /* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
 #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
 #define        usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
index 5de7a22..0e5ac93 100644 (file)
@@ -33,6 +33,7 @@ struct usbnet {
        wait_queue_head_t       *wait;
        struct mutex            phy_mutex;
        unsigned char           suspend_count;
+       unsigned char           pkt_cnt, pkt_err;
 
        /* i/o info: pipes etc */
        unsigned                in, out;
@@ -70,6 +71,7 @@ struct usbnet {
 #              define EVENT_DEV_OPEN   7
 #              define EVENT_DEVICE_REPORT_IDLE 8
 #              define EVENT_NO_RUNTIME_PM      9
+#              define EVENT_RX_KILL    10
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -100,7 +102,6 @@ struct driver_info {
 #define FLAG_LINK_INTR 0x0800          /* updates link (carrier) status */
 
 #define FLAG_POINTTOPOINT 0x1000       /* possibly use "usb%d" names */
-#define FLAG_NOARP     0x2000          /* device can't do ARP */
 
 /*
  * Indicates to usbnet, that USB driver accumulates multiple IP packets.
@@ -108,6 +109,7 @@ struct driver_info {
  */
 #define FLAG_MULTI_PACKET      0x2000
 #define FLAG_RX_ASSEMBLE       0x4000  /* rx packets may span >1 frames */
+#define FLAG_NOARP             0x8000  /* device can't do ARP */
 
        /* init device ... can sleep, or cause probe() failure */
        int     (*bind)(struct usbnet *, struct usb_interface *);
diff --git a/include/linux/vt8500_timer.h b/include/linux/vt8500_timer.h
new file mode 100644 (file)
index 0000000..33b0ee8
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#ifndef __VT8500_TIMER_H
+#define __VT8500_TIMER_H
+
+#include <asm/mach/time.h>
+
+void vt8500_timer_init(void);
+
+#endif
index 498433d..938b7fd 100644 (file)
@@ -34,17 +34,17 @@ extern int                          udpv6_connect(struct sock *sk,
                                                      struct sockaddr *uaddr,
                                                      int addr_len);
 
-extern int                     datagram_recv_ctl(struct sock *sk,
-                                                 struct msghdr *msg,
-                                                 struct sk_buff *skb);
-
-extern int                     datagram_send_ctl(struct net *net,
-                                                 struct sock *sk,
-                                                 struct msghdr *msg,
-                                                 struct flowi6 *fl6,
-                                                 struct ipv6_txoptions *opt,
-                                                 int *hlimit, int *tclass,
-                                                 int *dontfrag);
+extern int                     ip6_datagram_recv_ctl(struct sock *sk,
+                                                     struct msghdr *msg,
+                                                     struct sk_buff *skb);
+
+extern int                     ip6_datagram_send_ctl(struct net *net,
+                                                     struct sock *sk,
+                                                     struct msghdr *msg,
+                                                     struct flowi6 *fl6,
+                                                     struct ipv6_txoptions *opt,
+                                                     int *hlimit, int *tclass,
+                                                     int *dontfrag);
 
 #define                LOOPBACK4_IPV6          cpu_to_be32(0x7f000006)
 
index e6e5d4b..7f2360a 100644 (file)
@@ -115,6 +115,7 @@ struct kvm_irq_level {
         * ACPI gsi notion of irq.
         * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
         * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
+        * For ARM: See Documentation/virtual/kvm/api.txt
         */
        union {
                __u32 irq;
@@ -635,6 +636,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_IRQFD_RESAMPLE 82
 #define KVM_CAP_PPC_BOOKE_WATCHDOG 83
 #define KVM_CAP_PPC_HTAB_FD 84
+#define KVM_CAP_ARM_PSCI 87
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -764,6 +766,11 @@ struct kvm_dirty_tlb {
 #define KVM_REG_SIZE_U512      0x0060000000000000ULL
 #define KVM_REG_SIZE_U1024     0x0070000000000000ULL
 
+struct kvm_reg_list {
+       __u64 n; /* number of regs */
+       __u64 reg[0];
+};
+
 struct kvm_one_reg {
        __u64 id;
        __u64 addr;
@@ -932,6 +939,8 @@ struct kvm_s390_ucas_mapping {
 #define KVM_SET_ONE_REG                  _IOW(KVMIO,  0xac, struct kvm_one_reg)
 /* VM is being stopped by host */
 #define KVM_KVMCLOCK_CTRL        _IO(KVMIO,   0xad)
+#define KVM_ARM_VCPU_INIT        _IOW(KVMIO,  0xae, struct kvm_vcpu_init)
+#define KVM_GET_REG_LIST         _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
 
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
index 5059847..f738e25 100644 (file)
 #define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
 #define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
 
+/*
+ * Interface status, Figure 9-5 USB 3.0 spec
+ */
+#define USB_INTRF_STAT_FUNC_RW_CAP     1
+#define USB_INTRF_STAT_FUNC_RW         2
+
 #define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
 
 /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
index 301079d..7b6646a 100644 (file)
@@ -908,6 +908,15 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 }
 
 /*
+ * Initialize event state based on the perf_event_attr::disabled.
+ */
+static inline void perf_event__state_init(struct perf_event *event)
+{
+       event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF :
+                                             PERF_EVENT_STATE_INACTIVE;
+}
+
+/*
  * Called at perf_event creation and when events are attached/detached from a
  * group.
  */
@@ -6179,8 +6188,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        event->overflow_handler = overflow_handler;
        event->overflow_handler_context = context;
 
-       if (attr->disabled)
-               event->state = PERF_EVENT_STATE_OFF;
+       perf_event__state_init(event);
 
        pmu = NULL;
 
@@ -6609,9 +6617,17 @@ SYSCALL_DEFINE5(perf_event_open,
 
                mutex_lock(&gctx->mutex);
                perf_remove_from_context(group_leader);
+
+               /*
+                * Removing from the context ends up with disabled
+                * event. What we want here is event in the initial
+                * startup state, ready to be add into new context.
+                */
+               perf_event__state_init(group_leader);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
                        perf_remove_from_context(sibling);
+                       perf_event__state_init(sibling);
                        put_ctx(gctx);
                }
                mutex_unlock(&gctx->mutex);
index f6e5ec2..c1cc7e1 100644 (file)
@@ -40,8 +40,7 @@
 #ifdef CONFIG_RCU_NOCB_CPU
 static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
 static bool have_rcu_nocb_mask;            /* Was rcu_nocb_mask allocated? */
-static bool rcu_nocb_poll;         /* Offload kthread are to poll. */
-module_param(rcu_nocb_poll, bool, 0444);
+static bool __read_mostly rcu_nocb_poll;    /* Offload kthread are to poll. */
 static char __initdata nocb_buf[NR_CPUS * 5];
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
@@ -2159,6 +2158,13 @@ static int __init rcu_nocb_setup(char *str)
 }
 __setup("rcu_nocbs=", rcu_nocb_setup);
 
+static int __init parse_rcu_nocb_poll(char *arg)
+{
+       rcu_nocb_poll = 1;
+       return 0;
+}
+early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
+
 /* Is the specified CPU a no-CPUs CPU? */
 static bool is_nocb_cpu(int cpu)
 {
@@ -2366,10 +2372,11 @@ static int rcu_nocb_kthread(void *arg)
        for (;;) {
                /* If not polling, wait for next batch of callbacks. */
                if (!rcu_nocb_poll)
-                       wait_event(rdp->nocb_wq, rdp->nocb_head);
+                       wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
                list = ACCESS_ONCE(rdp->nocb_head);
                if (!list) {
                        schedule_timeout_interruptible(1);
+                       flush_signals(current);
                        continue;
                }
 
index 2cd3c1b..7ae4c4c 100644 (file)
@@ -222,8 +222,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
                        cfs_rq->runnable_load_avg);
        SEQ_printf(m, "  .%-30s: %lld\n", "blocked_load_avg",
                        cfs_rq->blocked_load_avg);
-       SEQ_printf(m, "  .%-30s: %ld\n", "tg_load_avg",
-                       atomic64_read(&cfs_rq->tg->load_avg));
+       SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_avg",
+                       (unsigned long long)atomic64_read(&cfs_rq->tg->load_avg));
        SEQ_printf(m, "  .%-30s: %lld\n", "tg_load_contrib",
                        cfs_rq->tg_load_contrib);
        SEQ_printf(m, "  .%-30s: %d\n", "tg_runnable_contrib",
index 5eea870..81fa536 100644 (file)
@@ -2663,7 +2663,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
        hrtimer_cancel(&cfs_b->slack_timer);
 }
 
-static void unthrottle_offline_cfs_rqs(struct rq *rq)
+static void __maybe_unused unthrottle_offline_cfs_rqs(struct rq *rq)
 {
        struct cfs_rq *cfs_rq;
 
index 418feb0..4f02b28 100644 (file)
@@ -566,7 +566,7 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq)
 static int do_balance_runtime(struct rt_rq *rt_rq)
 {
        struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
-       struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
+       struct root_domain *rd = rq_of_rt_rq(rt_rq)->rd;
        int i, weight, more = 0;
        u64 rt_period;
 
index 30b6de0..c6d6400 100644 (file)
@@ -339,6 +339,7 @@ void clockevents_config_and_register(struct clock_event_device *dev,
        clockevents_config(dev, freq);
        clockevents_register_device(dev);
 }
+EXPORT_SYMBOL_GPL(clockevents_config_and_register);
 
 /**
  * clockevents_update_freq - Update frequency and reprogram a clock event device.
index cbc6acb..8ed9346 100644 (file)
@@ -135,6 +135,20 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
 }
 
 /* Timekeeper helper functions. */
+
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+u32 (*arch_gettimeoffset)(void);
+
+u32 get_arch_timeoffset(void)
+{
+       if (likely(arch_gettimeoffset))
+               return arch_gettimeoffset();
+       return 0;
+}
+#else
+static inline u32 get_arch_timeoffset(void) { return 0; }
+#endif
+
 static inline s64 timekeeping_get_ns(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
@@ -151,8 +165,8 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk)
        nsec = cycle_delta * tk->mult + tk->xtime_nsec;
        nsec >>= tk->shift;
 
-       /* If arch requires, add in gettimeoffset() */
-       return nsec + arch_gettimeoffset();
+       /* If arch requires, add in get_arch_timeoffset() */
+       return nsec + get_arch_timeoffset();
 }
 
 static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
@@ -171,8 +185,8 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
        /* convert delta to nanoseconds. */
        nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
 
-       /* If arch requires, add in gettimeoffset() */
-       return nsec + arch_gettimeoffset();
+       /* If arch requires, add in get_arch_timeoffset() */
+       return nsec + get_arch_timeoffset();
 }
 
 static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
@@ -254,8 +268,8 @@ static void timekeeping_forward_now(struct timekeeper *tk)
 
        tk->xtime_nsec += cycle_delta * tk->mult;
 
-       /* If arch requires, add in gettimeoffset() */
-       tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;
+       /* If arch requires, add in get_arch_timeoffset() */
+       tk->xtime_nsec += (u64)get_arch_timeoffset() << tk->shift;
 
        tk_normalize_xtime(tk);
 
index 8c0e629..dc2be7e 100644 (file)
@@ -162,6 +162,8 @@ static int digsig_verify_rsa(struct key *key,
        memset(out1, 0, head);
        memcpy(out1 + head, p, l);
 
+       kfree(p);
+
        err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
        if (err)
                goto err;
index 6001ee6..b5783d8 100644 (file)
@@ -1257,6 +1257,10 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        if (flags & FOLL_WRITE && !pmd_write(*pmd))
                goto out;
 
+       /* Avoid dumping huge zero page */
+       if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
+               return ERR_PTR(-EFAULT);
+
        page = pmd_page(*pmd);
        VM_BUG_ON(!PageHead(page));
        if (flags & FOLL_TOUCH) {
index 4f3ea0b..546db81 100644 (file)
@@ -3033,6 +3033,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
                if (!huge_pte_none(huge_ptep_get(ptep))) {
                        pte = huge_ptep_get_and_clear(mm, address, ptep);
                        pte = pte_mkhuge(pte_modify(pte, newprot));
+                       pte = arch_make_huge_pte(pte, vma, NULL, 0);
                        set_huge_pte_at(mm, address, ptep, pte);
                        pages++;
                }
index c387786..2fd8b4a 100644 (file)
@@ -160,8 +160,10 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
        if (is_write_migration_entry(entry))
                pte = pte_mkwrite(pte);
 #ifdef CONFIG_HUGETLB_PAGE
-       if (PageHuge(new))
+       if (PageHuge(new)) {
                pte = pte_mkhuge(pte);
+               pte = arch_make_huge_pte(pte, vma, new, 0);
+       }
 #endif
        flush_cache_page(vma, addr, pte_pfn(pte));
        set_pte_at(mm, addr, ptep, pte);
index 35730ee..d1e4124 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2943,7 +2943,7 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping)
  * vma in this mm is backed by the same anon_vma or address_space.
  *
  * We can take all the locks in random order because the VM code
- * taking i_mmap_mutex or anon_vma->mutex outside the mmap_sem never
+ * taking i_mmap_mutex or anon_vma->rwsem outside the mmap_sem never
  * takes more than one of them in a row. Secondly we're protected
  * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex.
  *
index 25bfce0..4925a02 100644 (file)
@@ -249,12 +249,12 @@ static void hci_conn_disconnect(struct hci_conn *conn)
        __u8 reason = hci_proto_disconn_ind(conn);
 
        switch (conn->type) {
-       case ACL_LINK:
-               hci_acl_disconn(conn, reason);
-               break;
        case AMP_LINK:
                hci_amp_disconn(conn, reason);
                break;
+       default:
+               hci_acl_disconn(conn, reason);
+               break;
        }
 }
 
index 68a9587..5abefb1 100644 (file)
@@ -859,6 +859,19 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
        skb_pull(skb, sizeof(code));
 
+       /*
+        * The SMP context must be initialized for all other PDUs except
+        * pairing and security requests. If we get any other PDU when
+        * not initialized simply disconnect (done if this function
+        * returns an error).
+        */
+       if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
+           !conn->smp_chan) {
+               BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
+               kfree_skb(skb);
+               return -ENOTSUPP;
+       }
+
        switch (code) {
        case SMP_CMD_PAIRING_REQ:
                reason = smp_cmd_pairing_req(conn, skb);
index b29dacf..e6e1cbe 100644 (file)
@@ -1781,10 +1781,13 @@ static ssize_t pktgen_thread_write(struct file *file,
                        return -EFAULT;
                i += len;
                mutex_lock(&pktgen_thread_lock);
-               pktgen_add_device(t, f);
+               ret = pktgen_add_device(t, f);
                mutex_unlock(&pktgen_thread_lock);
-               ret = count;
-               sprintf(pg_result, "OK: add_device=%s", f);
+               if (!ret) {
+                       ret = count;
+                       sprintf(pg_result, "OK: add_device=%s", f);
+               } else
+                       sprintf(pg_result, "ERROR: can not add device %s", f);
                goto out;
        }
 
index a9a2ae3..32443eb 100644 (file)
@@ -683,7 +683,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->network_header     = old->network_header;
        new->mac_header         = old->mac_header;
        new->inner_transport_header = old->inner_transport_header;
-       new->inner_network_header = old->inner_transport_header;
+       new->inner_network_header = old->inner_network_header;
        skb_dst_copy(new, old);
        new->rxhash             = old->rxhash;
        new->ooo_okay           = old->ooo_okay;
index 291f2ed..cdf2e70 100644 (file)
@@ -310,6 +310,12 @@ void tcp_slow_start(struct tcp_sock *tp)
 {
        int cnt; /* increase in packets */
        unsigned int delta = 0;
+       u32 snd_cwnd = tp->snd_cwnd;
+
+       if (unlikely(!snd_cwnd)) {
+               pr_err_once("snd_cwnd is nul, please report this bug.\n");
+               snd_cwnd = 1U;
+       }
 
        /* RFC3465: ABC Slow start
         * Increase only after a full MSS of bytes is acked
@@ -324,7 +330,7 @@ void tcp_slow_start(struct tcp_sock *tp)
        if (sysctl_tcp_max_ssthresh > 0 && tp->snd_cwnd > sysctl_tcp_max_ssthresh)
                cnt = sysctl_tcp_max_ssthresh >> 1;     /* limited slow start */
        else
-               cnt = tp->snd_cwnd;                     /* exponential increase */
+               cnt = snd_cwnd;                         /* exponential increase */
 
        /* RFC3465: ABC
         * We MAY increase by 2 if discovered delayed ack
@@ -334,11 +340,11 @@ void tcp_slow_start(struct tcp_sock *tp)
        tp->bytes_acked = 0;
 
        tp->snd_cwnd_cnt += cnt;
-       while (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
-               tp->snd_cwnd_cnt -= tp->snd_cwnd;
+       while (tp->snd_cwnd_cnt >= snd_cwnd) {
+               tp->snd_cwnd_cnt -= snd_cwnd;
                delta++;
        }
-       tp->snd_cwnd = min(tp->snd_cwnd + delta, tp->snd_cwnd_clamp);
+       tp->snd_cwnd = min(snd_cwnd + delta, tp->snd_cwnd_clamp);
 }
 EXPORT_SYMBOL_GPL(tcp_slow_start);
 
index 18f97ca..ad70a96 100644 (file)
@@ -3504,6 +3504,11 @@ static bool tcp_process_frto(struct sock *sk, int flag)
                }
        } else {
                if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) {
+                       if (!tcp_packets_in_flight(tp)) {
+                               tcp_enter_frto_loss(sk, 2, flag);
+                               return true;
+                       }
+
                        /* Prevent sending of new data. */
                        tp->snd_cwnd = min(tp->snd_cwnd,
                                           tcp_packets_in_flight(tp));
@@ -5649,8 +5654,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
         * the remote receives only the retransmitted (regular) SYNs: either
         * the original SYN-data or the corresponding SYN-ACK is lost.
         */
-       syn_drop = (cookie->len <= 0 && data &&
-                   inet_csk(sk)->icsk_retransmits);
+       syn_drop = (cookie->len <= 0 && data && tp->total_retrans);
 
        tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
 
index 70b09ef..eadb693 100644 (file)
@@ -496,6 +496,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                 * errors returned from accept().
                 */
                inet_csk_reqsk_queue_drop(sk, req, prev);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
        case TCP_SYN_SENT:
@@ -1500,8 +1501,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
         * clogging syn queue with openreqs with exponentially increasing
         * timeout.
         */
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
+       }
 
        req = inet_reqsk_alloc(&tcp_request_sock_ops);
        if (!req)
@@ -1666,6 +1669,7 @@ drop_and_release:
 drop_and_free:
        reqsk_free(req);
 drop:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return 0;
 }
 EXPORT_SYMBOL(tcp_v4_conn_request);
index 420e563..1b5d8cb 100644 (file)
@@ -1660,6 +1660,7 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)
        if (dev->addr_len != IEEE802154_ADDR_LEN)
                return -1;
        memcpy(eui, dev->dev_addr, 8);
+       eui[0] ^= 2;
        return 0;
 }
 
index 8edf260..7a778b9 100644 (file)
@@ -380,7 +380,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
-                               datagram_recv_ctl(sk, msg, skb);
+                               ip6_datagram_recv_ctl(sk, msg, skb);
                        if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
                                sin->sin6_scope_id = IP6CB(skb)->iif;
                } else {
@@ -468,7 +468,8 @@ out:
 }
 
 
-int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
+int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
+                         struct sk_buff *skb)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct inet6_skb_parm *opt = IP6CB(skb);
@@ -597,11 +598,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);
 
-int datagram_send_ctl(struct net *net, struct sock *sk,
-                     struct msghdr *msg, struct flowi6 *fl6,
-                     struct ipv6_txoptions *opt,
-                     int *hlimit, int *tclass, int *dontfrag)
+int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
+                         struct msghdr *msg, struct flowi6 *fl6,
+                         struct ipv6_txoptions *opt,
+                         int *hlimit, int *tclass, int *dontfrag)
 {
        struct in6_pktinfo *src_info;
        struct cmsghdr *cmsg;
@@ -871,4 +873,4 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
 exit_f:
        return err;
 }
-EXPORT_SYMBOL_GPL(datagram_send_ctl);
+EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
index 29124b7..d6de4b4 100644 (file)
@@ -365,8 +365,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
                msg.msg_control = (void*)(fl->opt+1);
                memset(&flowi6, 0, sizeof(flowi6));
 
-               err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk,
-                                       &junk, &junk);
+               err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt,
+                                           &junk, &junk, &junk);
                if (err)
                        goto done;
                err = -EINVAL;
index c727e47..131dd09 100644 (file)
@@ -960,7 +960,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
        int ret;
 
        if (!ip6_tnl_xmit_ctl(t))
-               return -1;
+               goto tx_err;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
index ee94d31..d1e2e8e 100644 (file)
@@ -476,8 +476,8 @@ sticky_done:
                msg.msg_controllen = optlen;
                msg.msg_control = (void*)(opt+1);
 
-               retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk,
-                                        &junk);
+               retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk,
+                                            &junk, &junk);
                if (retv)
                        goto done;
 update:
@@ -1002,7 +1002,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                release_sock(sk);
 
                if (skb) {
-                       int err = datagram_recv_ctl(sk, &msg, skb);
+                       int err = ip6_datagram_recv_ctl(sk, &msg, skb);
                        kfree_skb(skb);
                        if (err)
                                return err;
index 6cd29b1..70fa814 100644 (file)
@@ -507,7 +507,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        sock_recv_ts_and_drops(msg, sk, skb);
 
        if (np->rxopt.all)
-               datagram_recv_ctl(sk, msg, skb);
+               ip6_datagram_recv_ctl(sk, msg, skb);
 
        err = copied;
        if (flags & MSG_TRUNC)
@@ -822,8 +822,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
index e229a3b..363d8b7 100644 (file)
@@ -928,7 +928,7 @@ restart:
        dst_hold(&rt->dst);
        read_unlock_bh(&table->tb6_lock);
 
-       if (!rt->n && !(rt->rt6i_flags & RTF_NONEXTHOP))
+       if (!rt->n && !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))
                nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
        else if (!(rt->dst.flags & DST_HOST))
                nrt = rt6_alloc_clone(rt, &fl6->daddr);
index 93825dd..4f43537 100644 (file)
@@ -423,6 +423,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                }
 
                inet_csk_reqsk_queue_drop(sk, req, prev);
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
                goto out;
 
        case TCP_SYN_SENT:
@@ -958,8 +959,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
                        goto drop;
        }
 
-       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
+       }
 
        req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
        if (req == NULL)
@@ -1108,6 +1111,7 @@ drop_and_release:
 drop_and_free:
        reqsk_free(req);
 drop:
+       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return 0; /* don't send reset */
 }
 
index dfaa29b..fb08329 100644 (file)
@@ -443,7 +443,7 @@ try_again:
                        ip_cmsg_recv(msg, skb);
        } else {
                if (np->rxopt.all)
-                       datagram_recv_ctl(sk, msg, skb);
+                       ip6_datagram_recv_ctl(sk, msg, skb);
        }
 
        err = copied;
@@ -1153,8 +1153,8 @@ do_udp_sendmsg:
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(*opt);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
index 1a9f372..2ac884d 100644 (file)
@@ -168,6 +168,51 @@ l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
 
 }
 
+/* Lookup the tunnel socket, possibly involving the fs code if the socket is
+ * owned by userspace.  A struct sock returned from this function must be
+ * released using l2tp_tunnel_sock_put once you're done with it.
+ */
+struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
+{
+       int err = 0;
+       struct socket *sock = NULL;
+       struct sock *sk = NULL;
+
+       if (!tunnel)
+               goto out;
+
+       if (tunnel->fd >= 0) {
+               /* Socket is owned by userspace, who might be in the process
+                * of closing it.  Look the socket up using the fd to ensure
+                * consistency.
+                */
+               sock = sockfd_lookup(tunnel->fd, &err);
+               if (sock)
+                       sk = sock->sk;
+       } else {
+               /* Socket is owned by kernelspace */
+               sk = tunnel->sock;
+       }
+
+out:
+       return sk;
+}
+EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_lookup);
+
+/* Drop a reference to a tunnel socket obtained via. l2tp_tunnel_sock_put */
+void l2tp_tunnel_sock_put(struct sock *sk)
+{
+       struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
+       if (tunnel) {
+               if (tunnel->fd >= 0) {
+                       /* Socket is owned by userspace */
+                       sockfd_put(sk->sk_socket);
+               }
+               sock_put(sk);
+       }
+}
+EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put);
+
 /* Lookup a session by id in the global session list
  */
 static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id)
@@ -1123,8 +1168,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
        struct udphdr *uh;
        struct inet_sock *inet;
        __wsum csum;
-       int old_headroom;
-       int new_headroom;
        int headroom;
        int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
        int udp_len;
@@ -1136,16 +1179,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
         */
        headroom = NET_SKB_PAD + sizeof(struct iphdr) +
                uhlen + hdr_len;
-       old_headroom = skb_headroom(skb);
        if (skb_cow_head(skb, headroom)) {
                kfree_skb(skb);
                return NET_XMIT_DROP;
        }
 
-       new_headroom = skb_headroom(skb);
        skb_orphan(skb);
-       skb->truesize += new_headroom - old_headroom;
-
        /* Setup L2TP header */
        session->build_header(session, __skb_push(skb, hdr_len));
 
@@ -1607,6 +1646,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
        tunnel->sock = sk;
+       tunnel->fd = fd;
        lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
 
        sk->sk_allocation = GFP_ATOMIC;
@@ -1642,24 +1682,32 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
  */
 int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
-       int err = 0;
-       struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL;
+       int err = -EBADF;
+       struct socket *sock = NULL;
+       struct sock *sk = NULL;
+
+       sk = l2tp_tunnel_sock_lookup(tunnel);
+       if (!sk)
+               goto out;
+
+       sock = sk->sk_socket;
+       BUG_ON(!sock);
 
        /* Force the tunnel socket to close. This will eventually
         * cause the tunnel to be deleted via the normal socket close
         * mechanisms when userspace closes the tunnel socket.
         */
-       if (sock != NULL) {
-               err = inet_shutdown(sock, 2);
+       err = inet_shutdown(sock, 2);
 
-               /* If the tunnel's socket was created by the kernel,
-                * close the socket here since the socket was not
-                * created by userspace.
-                */
-               if (sock->file == NULL)
-                       err = inet_release(sock);
-       }
+       /* If the tunnel's socket was created by the kernel,
+        * close the socket here since the socket was not
+        * created by userspace.
+        */
+       if (sock->file == NULL)
+               err = inet_release(sock);
 
+       l2tp_tunnel_sock_put(sk);
+out:
        return err;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
index 56d583e..e62204c 100644 (file)
@@ -188,7 +188,8 @@ struct l2tp_tunnel {
        int (*recv_payload_hook)(struct sk_buff *skb);
        void (*old_sk_destruct)(struct sock *);
        struct sock             *sock;          /* Parent socket */
-       int                     fd;
+       int                     fd;             /* Parent fd, if tunnel socket
+                                                * was created by userspace */
 
        uint8_t                 priv[0];        /* private data */
 };
@@ -228,6 +229,8 @@ out:
        return tunnel;
 }
 
+extern struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel);
+extern void l2tp_tunnel_sock_put(struct sock *sk);
 extern struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunnel, u32 session_id);
 extern struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
 extern struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
index 9275471..8ee4a86 100644 (file)
@@ -554,8 +554,8 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
                memset(opt, 0, sizeof(struct ipv6_txoptions));
                opt->tot_len = sizeof(struct ipv6_txoptions);
 
-               err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
-                                       &hlimit, &tclass, &dontfrag);
+               err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
+                                           &hlimit, &tclass, &dontfrag);
                if (err < 0) {
                        fl6_sock_release(flowlabel);
                        return err;
@@ -646,7 +646,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                            struct msghdr *msg, size_t len, int noblock,
                            int flags, int *addr_len)
 {
-       struct inet_sock *inet = inet_sk(sk);
+       struct ipv6_pinfo *np = inet6_sk(sk);
        struct sockaddr_l2tpip6 *lsa = (struct sockaddr_l2tpip6 *)msg->msg_name;
        size_t copied = 0;
        int err = -EOPNOTSUPP;
@@ -688,8 +688,8 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                        lsa->l2tp_scope_id = IP6CB(skb)->iif;
        }
 
-       if (inet->cmsg_flags)
-               ip_cmsg_recv(msg, skb);
+       if (np->rxopt.all)
+               ip6_datagram_recv_ctl(sk, msg, skb);
 
        if (flags & MSG_TRUNC)
                copied = skb->len;
index 286366e..716605c 100644 (file)
@@ -388,8 +388,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        struct l2tp_session *session;
        struct l2tp_tunnel *tunnel;
        struct pppol2tp_session *ps;
-       int old_headroom;
-       int new_headroom;
        int uhlen, headroom;
 
        if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
@@ -408,7 +406,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        if (tunnel == NULL)
                goto abort_put_sess;
 
-       old_headroom = skb_headroom(skb);
        uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
        headroom = NET_SKB_PAD +
                   sizeof(struct iphdr) + /* IP header */
@@ -418,9 +415,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        if (skb_cow_head(skb, headroom))
                goto abort_put_sess_tun;
 
-       new_headroom = skb_headroom(skb);
-       skb->truesize += new_headroom - old_headroom;
-
        /* Setup PPP header */
        __skb_push(skb, sizeof(ppph));
        skb->data[0] = ppph[0];
index a9327e2..670cbc3 100644 (file)
 /* Must be called with rcu_read_lock. */
 static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 {
-       if (unlikely(!vport)) {
-               kfree_skb(skb);
-               return;
-       }
+       if (unlikely(!vport))
+               goto error;
+
+       if (unlikely(skb_warn_if_lro(skb)))
+               goto error;
 
        /* Make our own copy of the packet.  Otherwise we will mangle the
         * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
@@ -50,6 +51,10 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 
        skb_push(skb, ETH_HLEN);
        ovs_vport_receive(vport, skb);
+       return;
+
+error:
+       kfree_skb(skb);
 }
 
 /* Called with rcu_read_lock and bottom-halves disabled. */
@@ -169,9 +174,6 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
                goto error;
        }
 
-       if (unlikely(skb_warn_if_lro(skb)))
-               goto error;
-
        skb->dev = netdev_vport->dev;
        len = skb->len;
        dev_queue_xmit(skb);
index e639645..c111bd0 100644 (file)
@@ -2361,13 +2361,15 @@ static int packet_release(struct socket *sock)
 
        packet_flush_mclist(sk);
 
-       memset(&req_u, 0, sizeof(req_u));
-
-       if (po->rx_ring.pg_vec)
+       if (po->rx_ring.pg_vec) {
+               memset(&req_u, 0, sizeof(req_u));
                packet_set_ring(sk, &req_u, 1, 0);
+       }
 
-       if (po->tx_ring.pg_vec)
+       if (po->tx_ring.pg_vec) {
+               memset(&req_u, 0, sizeof(req_u));
                packet_set_ring(sk, &req_u, 1, 1);
+       }
 
        fanout_release(sk);
 
index 298c0dd..3d2acc7 100644 (file)
@@ -438,18 +438,18 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                if (q->rate) {
                        struct sk_buff_head *list = &sch->q;
 
-                       delay += packet_len_2_sched_time(skb->len, q);
-
                        if (!skb_queue_empty(list)) {
                                /*
-                                * Last packet in queue is reference point (now).
-                                * First packet in queue is already in flight,
-                                * calculate this time bonus and substract
+                                * Last packet in queue is reference point (now),
+                                * calculate this time bonus and subtract
                                 * from delay.
                                 */
-                               delay -= now - netem_skb_cb(skb_peek(list))->time_to_send;
+                               delay -= netem_skb_cb(skb_peek_tail(list))->time_to_send - now;
+                               delay = max_t(psched_tdiff_t, 0, delay);
                                now = netem_skb_cb(skb_peek_tail(list))->time_to_send;
                        }
+
+                       delay += packet_len_2_sched_time(skb->len, q);
                }
 
                cb->time_to_send = now + delay;
index 159b9bc..d8420ae 100644 (file)
@@ -71,7 +71,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
                return;
 
        if (atomic_dec_and_test(&key->refcnt)) {
-               kfree(key);
+               kzfree(key);
                SCTP_DBG_OBJCNT_DEC(keys);
        }
 }
index 17a001b..1a9c5fb 100644 (file)
@@ -249,6 +249,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)
 /* Final destructor for endpoint.  */
 static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 {
+       int i;
+
        SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
 
        /* Free up the HMAC transform. */
@@ -271,6 +273,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
        sctp_inq_free(&ep->base.inqueue);
        sctp_bind_addr_free(&ep->base.bind_addr);
 
+       for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i)
+               memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE);
+
        /* Remove and free the port */
        if (sctp_sk(ep->base.sk)->bind_hash)
                sctp_put_port(ep->base.sk);
index 9e65758..cedd9bf 100644 (file)
@@ -3390,7 +3390,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
 
        ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);
 out:
-       kfree(authkey);
+       kzfree(authkey);
        return ret;
 }
 
index bfa3171..fb20f25 100644 (file)
@@ -98,9 +98,25 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
        list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
 }
 
+static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue)
+{
+       struct list_head *q = &queue->tasks[queue->priority];
+       struct rpc_task *task;
+
+       if (!list_empty(q)) {
+               task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
+               if (task->tk_owner == queue->owner)
+                       list_move_tail(&task->u.tk_wait.list, q);
+       }
+}
+
 static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
 {
-       queue->priority = priority;
+       if (queue->priority != priority) {
+               /* Fairness: rotate the list when changing priority */
+               rpc_rotate_queue_owner(queue);
+               queue->priority = priority;
+       }
 }
 
 static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid)
index 0a148c9..0f679df 100644 (file)
@@ -465,7 +465,7 @@ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp,
 }
 
 /*
- * See net/ipv6/datagram.c : datagram_recv_ctl
+ * See net/ipv6/datagram.c : ip6_datagram_recv_ctl
  */
 static int svc_udp_get_dest_address6(struct svc_rqst *rqstp,
                                     struct cmsghdr *cmh)
index 01592d7..45f1618 100644 (file)
@@ -1358,7 +1358,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info,
                                                  &iwe, IW_EV_UINT_LEN);
        }
 
-       buf = kmalloc(30, GFP_ATOMIC);
+       buf = kmalloc(31, GFP_ATOMIC);
        if (buf) {
                memset(&iwe, 0, sizeof(iwe));
                iwe.cmd = IWEVCUSTOM;
index bbbd276..7203e66 100644 (file)
@@ -19,6 +19,7 @@ bpf-direct-objs := bpf-direct.o
 
 # Try to match the kernel target.
 ifndef CONFIG_64BIT
+ifndef CROSS_COMPILE
 
 # s390 has -m31 flag to build 31 bit binaries
 ifndef CONFIG_S390
@@ -35,6 +36,7 @@ HOSTLOADLIBES_bpf-direct += $(MFLAG)
 HOSTLOADLIBES_bpf-fancy += $(MFLAG)
 HOSTLOADLIBES_dropper += $(MFLAG)
 endif
+endif
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
index 4d2c7df..2bb08a9 100755 (executable)
@@ -230,12 +230,12 @@ our $Inline       = qr{inline|__always_inline|noinline};
 our $Member    = qr{->$Ident|\.$Ident|\[[^]]*\]};
 our $Lval      = qr{$Ident(?:$Member)*};
 
-our $Float_hex = qr{(?i:0x[0-9a-f]+p-?[0-9]+[fl]?)};
-our $Float_dec = qr{(?i:((?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?))};
-our $Float_int = qr{(?i:[0-9]+e-?[0-9]+[fl]?)};
+our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
+our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
+our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
 our $Float     = qr{$Float_hex|$Float_dec|$Float_int};
-our $Constant  = qr{(?:$Float|(?i:(?:0x[0-9a-f]+|[0-9]+)[ul]*))};
-our $Assignment        = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
+our $Constant  = qr{$Float|(?i)(?:0x[0-9a-f]+|[0-9]+)[ul]*};
+our $Assignment        = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
 our $Compare    = qr{<=|>=|==|!=|<|>};
 our $Operators = qr{
                        <=|>=|==|!=|
index a210c8d..3b98159 100644 (file)
@@ -108,13 +108,18 @@ if SND_IMX_SOC
 config SND_SOC_IMX_SSI
        tristate
 
-config SND_SOC_IMX_PCM_FIQ
+config SND_SOC_IMX_PCM
        tristate
+
+config SND_SOC_IMX_PCM_FIQ
+       bool
        select FIQ
+       select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_PCM_DMA
-       tristate
+       bool
        select SND_SOC_DMAENGINE_PCM
+       select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_AUDMUX
        tristate
index ec14579..afd3479 100644 (file)
@@ -41,10 +41,7 @@ endif
 obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
 obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
-obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += snd-soc-imx-pcm-fiq.o
-snd-soc-imx-pcm-fiq-y := imx-pcm-fiq.o imx-pcm.o
-obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += snd-soc-imx-pcm-dma.o
-snd-soc-imx-pcm-dma-y := imx-pcm-dma.o imx-pcm.o
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
index bf363d8..500f8ce 100644 (file)
@@ -154,26 +154,7 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
        .pcm_free       = imx_pcm_free,
 };
 
-static int imx_soc_platform_probe(struct platform_device *pdev)
+int imx_pcm_dma_init(struct platform_device *pdev)
 {
        return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
 }
-
-static int imx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver imx_pcm_driver = {
-       .driver = {
-                       .name = "imx-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-       .probe = imx_soc_platform_probe,
-       .remove = imx_soc_platform_remove,
-};
-
-module_platform_driver(imx_pcm_driver);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-pcm-audio");
index 5ec362a..920f945 100644 (file)
@@ -281,7 +281,7 @@ static struct snd_soc_platform_driver imx_soc_platform_fiq = {
        .pcm_free       = imx_pcm_fiq_free,
 };
 
-static int imx_soc_platform_probe(struct platform_device *pdev)
+int imx_pcm_fiq_init(struct platform_device *pdev)
 {
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
        int ret;
@@ -314,23 +314,3 @@ failed_register:
 
        return ret;
 }
-
-static int imx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver imx_pcm_driver = {
-       .driver = {
-                       .name = "imx-fiq-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = imx_soc_platform_probe,
-       .remove = imx_soc_platform_remove,
-};
-
-module_platform_driver(imx_pcm_driver);
-
-MODULE_LICENSE("GPL");
index 0c9f188..0d0625b 100644 (file)
@@ -31,6 +31,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
                        runtime->dma_bytes);
        return ret;
 }
+EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
 
 static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
@@ -79,6 +80,7 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(imx_pcm_new);
 
 void imx_pcm_free(struct snd_pcm *pcm)
 {
@@ -100,6 +102,39 @@ void imx_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(imx_pcm_free);
+
+static int imx_pcm_probe(struct platform_device *pdev)
+{
+       if (strcmp(pdev->id_entry->name, "imx-fiq-pcm-audio") == 0)
+               return imx_pcm_fiq_init(pdev);
+
+       return imx_pcm_dma_init(pdev);
+}
+
+static int imx_pcm_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_device_id imx_pcm_devtype[] = {
+       { .name = "imx-pcm-audio", },
+       { .name = "imx-fiq-pcm-audio", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, imx_pcm_devtype);
+
+static struct platform_driver imx_pcm_driver = {
+       .driver = {
+                       .name = "imx-pcm",
+                       .owner = THIS_MODULE,
+       },
+       .id_table = imx_pcm_devtype,
+       .probe = imx_pcm_probe,
+       .remove = imx_pcm_remove,
+};
+module_platform_driver(imx_pcm_driver);
 
 MODULE_DESCRIPTION("Freescale i.MX PCM driver");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
index 83c0ed7..5ae13a1 100644 (file)
@@ -30,4 +30,22 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
 void imx_pcm_free(struct snd_pcm *pcm);
 
+#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
+int imx_pcm_dma_init(struct platform_device *pdev);
+#else
+static inline int imx_pcm_dma_init(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
+#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
+int imx_pcm_fiq_init(struct platform_device *pdev);
+#else
+static inline int imx_pcm_fiq_init(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
 #endif /* _IMX_PCM_H */
diff --git a/tools/vm/.gitignore b/tools/vm/.gitignore
new file mode 100644 (file)
index 0000000..44f095f
--- /dev/null
@@ -0,0 +1,2 @@
+slabinfo
+page-types